バグハンターに憧れた人間の日記

バグハンターに憧れた学生がバグハンターになるためにやってきたことについて、書いていくブログです。もし、筆者がバグを見つけれるようになった時にこれからバグハンターになってみたいと思う人の道導になればと思います。

SSI Injection

概要

先日Writeupの記事を書いたのですが、SSI Injectionという攻撃手法が出てきたのですが、筆者はそもそもSSIを知りませんでした。なので今回は実際にSSI Injectionの検証結果をブログに残したいと思いました。

SSIとは?

そもそもSSIとは何かということから今回の検証は始まりました。 SSIとはServer side Includesの略でHTMLに動きをつけるために使われるようです。 最近ではあまり使われることがないらしく今更感もあるのですが、過去にもSSI Injectionの事例があるようなので知識として入れておきたいと思い検証しました。

tech.nikkeibp.co.jp

SSIの導入

今回SSIの導入はこちらの記事を参考にしました。

環境

Virtual Box 5.2.22

OS:Ubuntu18.04

Apache:2.4.29

導入

SSIを動かすためにはモジュールを読み込まなければいけないらしいのでapache2.confに以下の内容を付け足しました。

LoadModule include_module modules/mod_include.so
LoadModule cgid_module modules/mod_cgid.so 

f:id:wa1m3im:20190206093026p:plain /etc/apache2にはもともとmoduleというディレクトリは存在しないのでmod_include.soをコピーしてくる必要がありました。 mod_include.soファイルの検索を行い

sudo find / -name mod_include.so 

f:id:wa1m3im:20190204132117p:plain

/usr/lib/apache2/modules/mod_include.so

このような検索結果が返ってきたので/usr/lib/apache2/modules/をそのまま/etc/apache2/modulesにコピーしました。

sudo cp -r /usr/lib/apache2/modules/mod_include.so /etc/apache2/modules/

f:id:wa1m3im:20190204131735p:plain

今回は/var/www/html下でSSIを使うのでapache2.confの設定ファイルに書き足しました。

<Directory /var/www/html>
Options Includes
AllowOverride None
Require all granted
AddType text/html .php .html
AddOutputFilter INCLUDES .php .html
</Directory>

f:id:wa1m3im:20190204205122p:plain

Directoryの後には設定を適用するディレクトリのパスを指定します。
Optionはincludesを指定することによってSSIの使用を許可します。
AllowOverRideは.htaccessで使用できるディレクトリを指定する為のディレクティブです。今回は設定する必要がないのでNoneにしています。
Requireはアクセス制御の設定です。今回は全てのアクセスを許可します。
AddTypeディレクティブは与えられた拡張子を指定されたコンテントマップにマップしてくれます。今回は.phpと.htmlをで動くように指定しました。 AddOutputFilterは同じく.phpと.htmlを指定します。 ここでフィルタについて少し調べたのですが、この機能はApache2.0以降の機能であり、クライアントとサーバー間で送受信されるデータへの処理プロセスのことを言うようです。クライアントからサーバーに送られるデータを入力フィルタ、サーバーからクライアントへのデータは出力フィルタによって処理することによりApacheに入出力されるデータを加工する為の機能を提供しているようです。 また、Apache1.3まではSSIをハンドラとして実装していたらしいのですが、2.0からはフィルタとして提供されているようです。 よってApache1.3でSSIを有効にするにはAddHandlerディレクティブに設定しなければいけなかったようです。しかし、Apache2.0からはSSIをフィルタとして提供されるようになったのでAddOutputFilterディレクティブを使用します。

設定ファイルの編集が終わったので次に実際にSSIが動作するかテストをしてみました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>SSI Test</title>
</head>
<body>

    <!--#echo var="DATE_LOCAL" -->
    
</body>
</html>

/var/www/htmlに移動してtest.htmlを作成しました。 SSIの現在の時刻を表示コードを記述してブラウザからアクセスしてみると

f:id:wa1m3im:20190205121800p:plain

問題なく動作していました。

次にphpファイルでテストをしてみました。

    <!--#echo var="DATE_LOCAL" -->

test.phpというファイルを作成して先ほどと同じように時刻を表示させようとすると

f:id:wa1m3im:20190205122356p:plain

問題なく動きました。

検証

ユーザーから入力値を受け取るform.htmlと入力値をそのまま表示するview.phpを作成しました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>form.html</title>
</head>
<body>

    <form action="view.php" method="post">
        <input type="text" name="text" size="40">入力フォーム
        
        <input type="submit" value="submit">
    </form>

    
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>view.php</title>
</head>
<body>

<?php

$value = $_POST["value"];
echo "入力値は".$value."です。";

?>
    
</body>
</html>

エスケープは行っていないのでもちろんXSSは発火します。

f:id:wa1m3im:20190205124010p:plain

f:id:wa1m3im:20190205124311p:plain

入力値に先ほどの時間を表示するコードを入力すると

f:id:wa1m3im:20190205124806p:plain

f:id:wa1m3im:20190205124821p:plain

SSIのコードが問題なく動いてしましました。

また、SSIはOSコマンドの実行が可能な為、lsコマンドを実行してみると

f:id:wa1m3im:20190206093745p:plain

<!--#exec cmd="ls" -->

f:id:wa1m3im:20190206093856p:plain

ディレクトリの中身が見れてしまいました。

他にも

<!--#exec cmd="echo '<?php phpinfo();?>' > info.php" -->

f:id:wa1m3im:20190207093439p:plain

ファイルの出力も行える為、webshellなどのバックドアの設置も可能でした。 f:id:wa1m3im:20190207093651p:plain

対策

SSI Injectionの対策はXSSの対策と同様で特殊文字エスケープによって対策することが可能になるそうです view.phpの$valueの値を直接代入するのではなくhtmlspecialchars関数に渡してから代入するようにすると

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>view.php</title>
</head>
<body>

<?php

$value = htmlspecialchars($_POST["value"]);
echo "入力値は".$value."です。";

?>
    
</body>
</html>

f:id:wa1m3im:20190207094821p:plain

SSIが動作せず、文字列としてペイロードが表示されました。

おわりに

今回はSSI Injectionを検証してみました。 SSIはApacheの設定次第で動くので過去に動くように設定していて現在は使用していないものの設定をそのままにしている可能性も考えられますね。もしかしたら発火する可能性もあるかもしれませんね。

参考資料

www.hizlab.net

bashalog.c-brains.jp

ch.nicovideo.jp