StreamIO HTB
StreamIO Summary StreamIO is a Medium-rated Windows machine that requires chaining together web exploitation, credential abuse, and Active Directory privilege escalation. Starting from a vulnerable web application, we obtain an initial foothold through Remote File Inclusion, pivot through multiple user accounts using recovered credentials, and ultimately abuse Active Directory permissions to obtain the Administrator LAPS password. Attack Overview Enumeration Nmap Enumeration Starting with a full Nmap scan against the target. Nmap Analysis The Nmap scan reveals several services commonly found in an Active Directory environment. | Port | Service | |--------|---------| | 53 | DNS | | 80 | HTTP | | 88 | Kerberos | | 389 | LDAP | | 443 | HTTPS | | 445 | SMB | | 3268 | Global Catalog | | 5985 | WinRM | From the presence of Kerberos, LDAP, SMB, and the Global Catalog, we can immediately identify that this machine is acting as a Domain Controller. Another interesting finding comes from the SSL certificate: This reveals an additional hostname called watch.streamIO.htb, which immediately becomes a target for further enumeration. At this stage my areas of interest were: Adding the Domain Names Adding the discovered hostnames to /etc/hosts. Web Enumeration Browsing port 80 reveals the default IIS page. Screenshot 2026-06-11 at 23-38-44 Nothing interesting here. Moving over to HTTPS on port 443. Screenshot 2026-06-11 at 23-39-15 The website contains: At first glance it looks like a movie streaming platform. Virtual Host Enumeration Since the SSL certificate revealed an additional hostname, I decided to perform virtual host enumeration. A valid subdomain was discovered: Browsing to the subdomain reveals a subscription page. Screenshot 2026-06-11 at 23-41-48 This appears to be the actual application used by customers. Directory Enumeration Running Gobuster against the newly discovered subdomain. Three interesting pages were discovered: search.php Browsing to search.php reveals a movie search functionality. Screenshot 2026-06-13 at 00-36-21 Since user input is accepted here, it immediately becomes a candidate for injection testing. blocked.php Browsing to blocked.php reveals: Screenshot 2026-06-13 at 00-37-03 The page indicates that users can be temporarily blocked for suspicious activity. This suggests that some sort of filtering or WAF is present. SQL Injection The search functionality looked interesting, so I intercepted the request using Burp Suite and started testing for SQL injection. Testing with: Monitoring the response in Burp confirmed that the parameter was injectable. image Now that SQL injection was confirmed, I began enumerating the backend database. Database Version Testing a UNION query: The query executes successfully. image This confirms that the injection is working correctly. Enumerating Databases Checking available databases: Among the results I identified: image Since the application itself is called StreamIO, this database became the primary target. Enumerating Tables Checking tables present in the STREAMIO database. image Several tables were returned. The most interesting one was: Enumerating Columns Extracting the schema of the users table. image This confirms that usernames and password hashes are stored inside the table. Dumping User Credentials Dumping the contents of the users table reveals multiple usernames and password hashes. The hashes appear to be MD5. Cracking the Hashes Extracting only the hashes: Cleaning the file for John: Running John: A total of 12 hashes were successfully cracked. Finding Valid Credentials Separating usernames and passwords: Using Hydra to identify valid credentials. Success. We now have valid credentials: Logging In Using the credentials above successfully logs us into the application. Screenshot 2026-06-13 at 12-39-11 After authentication, I wanted to identify any hidden functionality available only to logged-in users. Authenticated Directory Enumeration Using the authenticated session cookie: The discovery of: immediately stood out. Admin Panel Discovery Visiting /admin reveals an administrative interface. Screenshot 2026-06-13 at 12-50-29 The next step is to investigate the functionality exposed by the admin panel. Admin Panel Enumeration After discovering the /admin panel, I decided to enumerate it further to identify any hidden functionality. Running feroxbuster against the /admin directory: A new file was discovered: Browsing to it reveals: Screenshot 2026-06-13 at 13-00-33 The page displays: This suggests that master.php is intended to be loaded through a PHP include() statement rather than being accessed directly. Investigating the Admin Panel Back in the admin panel, clicking on Site Management redirects us to: Screenshot 2026-06-13 at 13-02-36 This immediately caught my attention because it looked like a parameter was being used to dynamically load content. I captured the request in Burp Suite and started testing different values. Without any modifications, the response length was: Screenshot 2026-06-13 at 13-04-49 My first thought was to try the newly discovered master.php, but the response remained unchanged. At this point it felt like another parameter might be involved, so I decided to fuzz for hidden parameters. Parameter Fuzzing Using Gobuster in fuzzing mode: Interesting. A hidden parameter was discovered: Discovering File Inclusion Accessing: returns a page with a content length of: Screenshot 2026-06-13 at 13-11-55 Next I supplied the previously discovered file: The content length immediately increased: Screenshot 2026-06-13 at 13-13-02 This strongly suggests that the application is loading and processing the supplied file. Reviewing the source code at the bottom of the response reveals: Screenshot 2026-06-13 at 13-14-37 This confirms that user-supplied input is being included by the application. At this point it appears possible to include arbitrary files, potentially even remote resources. Verifying Code Execution To test this theory, I created a simple PHP payload: Hosting the payload from my attacker machine: Server logs: The requests coming from the target confirm that the remote file is being fetched successfully. Using Burp Suite, I sent a POST request containing: The command executes successfully and returns: Screenshot 2026-06-13 at 14-00-11 We now have confirmed remote code execution. Obtaining an Initial Shell To obtain an interactive session, I generated a PHP Meterpreter payload. Setting up a listener: Output: After hosting shell.php and including it through the vulnerable parameter, the payload executes successfully. Screenshot 2026-06-13 at 14-07-46 Listener output: Success. We now have an initial shell on the target. Upgrading the Shell Although the PHP Meterpreter shell works, it isn't particularly stable. To obtain a more reliable session, I decided to upload a Windows Meterpreter executable. Generating the payload: Creating the Download Payload Creating rce.php: Notice that I intentionally omitted the closing PHP tag: For small payloads like this, it isn't required. Creating the Execution Payload Creating rce1.php: Hosting the Files Starting a web server: Triggering the download: The extra ?1 simply forces the file to be processed. Once the executable has been downloaded, triggering execution: Stable Meterpreter Session Setting up a new listener: Extracting Database Credentials Now that we have a stable shell, it's time to start enumerating the box internally. While reviewing the source code of the web application, I noticed hardcoded database credentials inside index.php. Credentials discovered: Looking for SQL Server Tools Before attempting to access the database, I checked whether any SQL client was installed on the target. Perfect. Microsoft's SQL client is installed. Attempting to connect locally: The session hangs and doesn't provide an interactive shell. Instead of fighting with sqlcmd, I decided to expose the MSSQL service externally using Chisel. Port Forwarding MSSQL with Chisel Starting Chisel Server On my Kali machine: Uploading Chisel Using Meterpreter's upload feature: Connecting Back to Chisel Server From the compromised Windows host: Back on Kali: The MSSQL service is now accessible locally. Connecting to MSSQL Using Impacket: Success. Database Enumeration Listing available databases: Output: One database immediately stands out: Backup databases often contain forgotten credentials or sensitive information. Switching into it: Enumerating tables: The users table looks interesting. Dumping User Credentials Dumping all records: The hashes appear to be MD5. Cracking the Hashes Instead of using John, I used CrackStation. Screenshot 2026-06-13 at 18-06-52 One password immediately stood out: Testing the Credentials Checking SMB access: Valid credentials. Checking WinRM: Even better. The account has WinRM access. Shell as nikk37 Connecting using Evil-WinRM: We now have a proper shell on the target. User Flag Privilege Escalation to Administrator Now that we have access as nikk37, it's time to look for a path to Administrator. As usual, I started by running WinPEAS to gather additional information about the system. First, upload WinPEAS to the target: Running WinPEAS revealed something interesting. It showed that we have access to a Firefox profile containing saved credentials. Screenshot 2026-06-13 at 18-57-09 Firefox stores saved passwords inside: Let's download both files and inspect them locally. Extracting Firefox Credentials To decrypt the Firefox credential database, I used Firepwd : Running Firepwd: Recovered credentials: I separated the usernames and passwords into two files: Testing the Credentials Instead of manually testing every combination, I used NetExec. Interesting. We discovered a valid domain credential: Verifying manually: BloodHound Enumeration Now that we have another valid domain user, let's see what permissions this account has in Active Directory. Collecting BloodHound data: Importing the ZIP file into BloodHound: Screenshot 2026-06-13 at 19-39-21 Screenshot 2026-06-13 at 19-40-21 BloodHound reveals an interesting attack path. The WriteOwner privilege means that JDgodd can change the owner of the CORE STAFF group. If we make ourselves the owner of that group, we can grant ourselves additional permissions over it and modify its membership. The CORE STAFF group also has the following privilege: This means members of that group can read the LAPS password of the Domain Controller's local administrator account. Creating a Credential Object Before abusing the ACLs, let's create a PowerShell credential object. Uploading PowerView To abuse the permissions discovered in BloodHound, I uploaded PowerView. Adding nikk37 to CORE STAFF Loading PowerView: Set the owner of CORE STAFF to JDgodd: Grant full rights over the group: Add nikk37 to the group: Checking whether the user was added successfully: Awesome. nikk37 is now a member of the CORE STAFF group. Reading the LAPS Password Since CORE STAFF has ReadLAPSPassword privileges, we can now retrieve the local administrator password. Using NetExec: Success. We now have the local Administrator password: Administrator Access Before logging in, I verified the credentials. Screenshot 2026-06-13 at 19-53-00 The credentials are valid. Connecting using Evil-WinRM: Success. We now have Administrator access on the Domain Controller. Root Flag The root flag is stored on Martin's desktop. And with that, we have successfully compromised the box. Final Thoughts StreamIO was a very enjoyable machine that required chaining together multiple attack vectors rather than relying on a single vulnerability. The box started with traditional web enumeration, where a discovered subdomain led to an SQL Injection vulnerability and eventually access to an administrative panel. From there, source code disclosure and Remote File Inclusion provided code execution on the target, opening the door for further internal enumeration. What I liked most about t