ApacheでTRACEメソッドを受付けなくする | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

WebサーバーのTRACメソッドを何故受付けなくしなければならないのかについては、XST(Cross Site Tracing)について、説明する必要があります。

XSTについては、以前に書いた「セキュリティ診断ツール「Nikto」を使ってサイトをチェックしよう 」の中で紹介した用語「Cross Site Tracing」@鳩丸ぐろっさり (用語集) に書かれています。


簡単に言ってしまうと、HTTPのTRACEメソッドのリクエストを通して、Basic認証のパスワードが盗まれてしまう恐れがありますよ、というものです。
余談ですがBasic認証のパスワードは、サーバー上のファイルに暗号化して保存されていますが、認証する際の通信には平分で流れます。

HTTPヘッダを見ると暗号化しているように見えるのですが、単にBase64で符号化しているだけなので、簡単に元に戻すことが出来ます。


例) HTTPヘッダ情報の中身

Authorization: Basic aG9nZTpmb28=

上記をPHPを通して、元に戻してみます。


# php -r 'echo base64_decode("aG9nZTpmb28=");'
hoge:foo

「hoge」ユーザーを使い、パスワードは「foo」である事がわかりました。

TRACEメソッドのリクエストを行えば、そのBasic認証時のパスワードを取得できてしまうわけです。


何故、TRACEメソッドがまずいのかというと、TRACEメソッドのその振る舞いです。

TRACEメソッドは、HTTPステータス200(OK)のレスポンスの内容をそのままクライアントに返します。

つまり、Basic認証が済んだ後(HTTPステータス200を受け取った後)に、TRACEメソッドのリクエストを発行すればそのBasic認証時の内容(IDとパスワードが含んだもの)が取得できてしまいます。


セキュリティ診断ツール「Nikto」を使ってサイトをチェックしよう 」の中で、HTTPのTRACEメソッドのリクエストが許可されている事にアラートが出たのはそういう理由からです。


ここでは、Apacheに対してTRACEメソッドのリクエストを受付けない設定を行ってみます。

まずは、本当にTRACEメソッドを受付けているのかどうか、チェックしてみます。

PHPのスクリプトを使って、該当のWebサイトにTRACEメソッドのリクエストを発行してみます。

PEARのHTTP_Request を使って、Basic認証を行うサンプルスクリプトです。


<?php
require_once "HTTP/Request.php";

// 対象のWebサイト(Basic認証がかけられている)
$req =& new HTTP_Request("http://192.168.0.100/login");

// Basic認証のIDとパスワード
$req->setBasicAuth("hoge", "foo");

// TRACEメソッドのリクエストを発行
$response = $req->setMethod(HTTP_REQUEST_METHOD_TRACE);

$response = $req->sendRequest();

if (PEAR::isError($response)) {
    echo $response->getMessage();
} else {
    echo $req->getResponseBody();
}
?>

上記コードを実行してみると・・・


# php auth.php
TRACE /trac/trac-test/login HTTP/1.1
Host: 192.168.0.100
User-Agent: PEAR HTTP_Request class ( http://pear.php.net/ )
Connection: close
Accept-Encoding: gzip
Authorization: Basic aG9nZTpmb28=


リクエストが返ってきましたね。


では、具体的にApacheのTRACEメソッドのリクエストを受付けなく設定します。

Apacheのバージョン2.0.44以降であれば、設定ファイル(httpd.conf)に下記の1行を書けば、それで済むようになっています。


TraceEnable off

しかし、バージョンがそれより古い場合、またはApacheの1系を使っている場合は、下記のようにmod_rewriteモジュールを使った記述をする必要があります。


RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^TRACE$
RewriteRule .* - [F]

当然、mod_rewriteモジュールをApacheに組み込んでおく必要があります。

この場合、厳密にTRACEのリクエストを受付けなくしているわけではありません。

TRACEのリクエストがあった場合、mod_rewriteで排除しているという動きになります。


TRACEメソッドの受付を無効にした後に(要Apache再起動)、もう一度先ほどのPHPスクリプトを実行してみます。


# php auth.php
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /login on this server.</p>
</body></html>

HTTPステータスコード403の画面のレスポンスが返ってきており、Apache側で受付けていない事がわかります。

管理するWebサーバーがあるのであれば、一度チェックしてみてはいかがでしょうか。