2012年1月23日月曜日

ModSecurityをソースからビルドしてhashdos対策に活用する

このエントリではModSecurityをソースからビルドする方法を説明した後、hashdos専用のチューニングを施す流れを説明します。

はじめに

既にModSecurityについては、CentOS+yumおよびUbuntu+apt-getにより導入する方法を説明しています。このエントリでは、ModSecurityをソースからビルドする方法を説明します。
ModSecurityのビルドは依存関係が複雑であり、バージョンによってビルド方法が変わるなど、面倒な面があります。このエントリでは、CentOSとUbuntuの場合について、実際的なビルド方法を説明します。

準備するもの

ModSecurityは以下のプロダクトに依存しています(ModSecurity HandbookP27)。ビルドに先立って準備しておく必要があります。
  • Apache Portable Runtime(APR)
  • APR-UTIL
  • mod_unique_id
  • libcurl
  • libxml2
  • Lua5.1 (オプション)
  • PCRE

PCRE、libcurl、libxml2、Lua5.1の準備

これらはパッケージを用いて導入するとよいでしょう。

(1)CentOSの場合
Lua5.1以外は、yumで導入できます。
$ sudo yum -y install pcre-devel libxml2-devel curl-devel
CentOS6の場合、Luaもyumで導入できます。
$ sudo yum install lua-devel
CentOS5の場合、標準パッケージにLuaが用意されていません。Luaは必須ではないし、まだLuaを活用した事例はほとんどないので、通常はLuaなしでよいでしょう。
Luaを使いたい場合は、EPELリポジトリを使えばLuaを導入できます。hashdos攻撃をmod_securityで防御する(CentOS+yum編)を参照して、EPELパッケージを設定した後、以下でLuaを導入して下さい。
$ sudo yum --enablerepo=epel install lua-devel

(2)Ubuntuの場合
Luaも含めて、apt-getで導入できます。
$ sudo apt-get install libpcre3-dev libxml2-dev libcurl3-dev liblua5.1-dev

Apacheの再構築

次に、Apacheの再構築です。Apacheを再構築する理由は、ApacheにバンドルされるPCREが古く、ModSecurityの前提とするPCREのバージョンが異なるからです。このため、Apacheからも外部のPCREを呼び出すようにします(ModSecurity HandbookP30)。また、mod_unique_idが必要になるため、必要に応じてコンパイルします。
パッケージからApacheを導入している場合は、APRとAPR-UTILが入っていないので、開発版のApacheを導入します。

(1)ソースからApacheをビルドしている場合
デフォルトでAPR、ARP-UTILは元々入っています。mod_uniquie_idはコンパイルオプションのチェックをしてください。PCREも先のステップで導入ししたものをApacheからも利用します。
最小限のconfigureのオプションは下記となります。
$ ./configure --with-pcre --enable-so --enable-mods-shared="unique_id"

(2)CentOS+yumでAapcheを導入している場合
開発版のApacheを追加導入します。
$ sudo yum install httpd-devel

(3)Ubuntu+apt-getでApacheを導入している場合
開発版のApacheを追加導入します。
$ sudo apt-get install apache2-dev

mod_securityのビルド

次に、mod_securityのビルドです。configureの際に、以下のように前提モジュールのパスを明示してやるとトラブルの可能性が少ないようです。パスは適宜調整してください。
以下の例では、/usr/local/apache2にApacheが導入されていて、そこにModSecurityも導入する前提で説明しています。
$ cd
$ wget http://www.modsecurity.org/download/modsecurity-apache_2.6.3.tar.gz
$ tar xf modsecurity-apache_2.6.3.tar.gz
$ cd modsecurity-apache_2.6.3
$ ./configure \
  --prefix=/usr/local/apache2 \
  --with-apxs=/usr/local/apache2/bin/apxs \
  --with-apr=/usr/local/apache2/bin/apr-1-config \
  --with-apu=/usr/local/apache2/bin/apu-1-config \
  --with-pcre=/usr/bin/pcre-config \
  --with-libxml=/usr/bin/xml2-config \
  LDFLAGS=-L/usr/local/apache2/lib
$ make
$ sudo make install
ブログなどでは、--enable-performance-measurementを指定している例も見かけますが、これを指定するとModSecurityが遅くなり、ModSecurity自身がhashdos攻撃を受けるような挙動になります。このオプションは指定しないで下さい。

(2)ディレクトリの作成
次に、ModSecurityの使用するワーク用のディレクトリを作成します(ModSecurity HandbookP34~)。apacheの実行ユーザをapacheと仮定しています。適宜変更してください。
$ sudo mkdir /var/modsecurity/
$ sudo mkdir /var/modsecurity/data
$ sudo mkdir /var/modsecurity/tmp
$ sudo mkdir /var/modsecurity/upload
$ sudo chown root:apache /var/modsecurity
$ sudo chown apache:root /var/modsecurity/data
$ sudo chown apache:apache /var/modsecurity/tmp
$ sudo chown apache:root /var/modsecurity/upload/
$ sudo chmod 750 /var/modsecurity
$ sudo chmod 700 /var/modsecurity/data
$ sudo chmod 750 /var/modsecurity/tmp
$ sudo chmod 700 /var/modsecurity/upload

CRS(Core Rule Set)の導入

ModSecurity用の標準ルールセットとしてCore Rule Set(CRS)を導入します。

(1)ダウンロード、展開
http://sourceforge.net/projects/mod-security/files/modsecurity-crs/0-CURRENT/ から最新版をダウンロードします
$ cd
$ wget http://sourceforge.net/projects/mod-security/files/modsecurity-crs/0-CURRENT/modsecurity-crs_2.2.3.tar.gz/download
$ mv download modsecurity-crs_2.2.3.tar.gz  # downloadというファイル名になったのでリネーム
$ tar xvf modsecurity-crs_2.2.3.tar.gz

(2)CRSのコピー
CRSを定位置にコピーします。ここでは、Apacheホームディレクトリ下のcrsというディレクトリにコピーしています。
$ cd /usr/local/apache2/
$ sudo mkdir crs
$ sudo cp -r ~/modsecurity-crs_2.2.3/* crs

mod_securityの設定

modsecurity_crs_10_config.confという設定ファイルを作成します。exampleを元に修正します。
$ cd /usr/local/apache2/crs
$ sudo cp modsecurity_crs_10_config.conf.example modsecurity_crs_10_config.conf
$ sudo vi modsecurity_crs_10_config.conf
「#SecRuleEngine DetectionOnly」 という行を探し、その後ろに以下を追加します。
SecRuleEngine On
# SecRequestBodyAccess リクエストボディのチェックを有効にする(必須)
SecRequestBodyAccess On
SecResponseBodyAccess Off
# SecRequestBodyLimit はPOSTサイズの上限。できるだけ小さく設定する
SecRequestBodyLimit 5242880
# SecRequestBodyNoFilesLimit はファイルアップロード以外のPOSTサイズの上限。できるだけ小さく設定する
SecRequestBodyNoFilesLimit 51200
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType Serial
SecAuditLog logs/modsec_audit.log
SecAuditLogParts "ABIFHKZ"
SecDebugLog             logs/modsec_debug.log
SecDebugLogLevel        3
SecDataDir      /var/modsecurity/data/
SecTmpDir       /var/modsecurity/tmp/
SecUploadDir    /var/modsecurity/upload/

Apacheの設定

ModSecurity用のconfファイルを作成します。
$ sudo vi /usr/local/apache2/conf/extra/httpd-modsecurity.conf
以下の内容を入力します。
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule security2_module modules/mod_security2.so

Include crs/modsecurity_crs_10_config.conf
Include crs/base_rules/*.conf
httpd.confを編集します。
$ sudo vi /usr/local/apache2/conf/httpd.conf
最後の行に以下を追加します。
Include conf/extra/httpd-modsecurity.conf
Apacheを起動します。
$ sudo apachectl start
エラーログに以下が出力されていることを確認します。
[Sun Jan 22 23:21:56 2012] [notice] ModSecurity for Apache/2.6.3 (http://www.modsecurity.org/) configured.
[Sun Jan 22 23:21:56 2012] [notice] ModSecurity: APR compiled version="1.4.5"; loaded version="1.4.5"
[Sun Jan 22 23:21:56 2012] [notice] ModSecurity: PCRE compiled version="7.8"; loaded version="7.8 2008-09-05"
[Sun Jan 22 23:21:56 2012] [notice] ModSecurity: LUA compiled version="Lua 5.1"
[Sun Jan 22 23:21:56 2012] [notice] ModSecurity: LIBXML compiled version="2.7.6"
ModSecurityが起動して、APR、PCRE、LUA、LIBXMLがロードされていることを確認してください。LUAはオプションですので、設定していない場合はロードされていなくても構いません。
次に、正常系のアクセスを確認します。以下のURLはサンプルですので、既存コンテンツのURLを指定して下さい。
http://example.jp/index.php
次に、以下がmod_securityによりブロックされることを確認します。既存コンテンツの後ろに、「?union+select」をつけてアクセスします。
http://example.jp/index.php?union+select
403 Forbiddenのエラーが表示されれば、mod_securityが稼働していることになります。

hashdos向けのチューニング

次に、hashdos向けのカスタマイズです。modsecurity_crs_23_request_limits.confに、Cookie数の制限のルールを追加します(Cookieによるhashdos攻撃と対策参照)。
$ sudo vi /usr/local/apache2/crs/base_rules/modsecurity_crs_23_request_limits.conf
以下のルールを探します。
# Maximum number of arguments in request limited
SecRule &TX:MAX_NUM_ARGS "@eq 1" "chain,phase:2,t:none,block,msg:'Too many arguments in request',id:'960335',severity:'4',rev:'2.2.3'"
        SecRule &ARGS "@gt %{tx.max_num_args}" "t:none,setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.policy_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
このルールの次に、以下を追加します。Cookieの最大数が30にハードコードされているので適宜変更してください。
SecRule &REQUEST_COOKIES "@gt 30" "phase:2,t:none,deny,log,auditlog,ctl:auditLogParts=AFHZ,status:413,msg:'Too many cookies in request',id:'960336',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+20,setvar:tx.policy_score=+1,setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
次に、base_rulesから必要なルールのみを選択するために、activated_rulesというディレクトリに必要なルールのシンボリックリンクを作成します。以下のステップは、CRSを(SQLインジェクション対策など)フルに活用する場合は省略して下さい。
$ cd /usr/local/apache2/crs/activated_rules
$ sudo ln -s ../base_rules/modsecurity_crs_23_request_limits.conf .
$ sudo ln -s ../base_rules/modsecurity_crs_49_inbound_blocking.conf  .
$ sudo ln -s ../base_rules/modsecurity_crs_60_correlation.conf .
httpd-modsecurity.confを修正します。
$ sudo vi /usr/local/apache2/conf/extra/httpd-modsecurity.conf
最終行を以下のように変更します。
##Include crs/base_rules/*.conf
Include crs/activated_rules/*.conf
Apacheを再起動します。
$ sudo apachectl graceful
以上で、ModSecurityがhashdos専用にチューニングされました。

まとめ

ModSecurityをソースからビルドして、hashdos対策専用のチューニングを施す流れを説明しました。
ModSecurityは導入や設定がやっかいで、バージョンアップの際に互換性が損なわれる場合が多いので、大々的には推奨しにくい状況ですが、Apache Killerhashdosのように、あたらな脅威が発覚した際の緊急対処用のツールとしては有効だと思いました。フルのCRSは過剰検知が多くて使いにくい(チューニングが必須)と思いますが、上記のように特定の脅威向けに絞って活用することは有効だと思います。

追記

Apacheの設定の記述漏れがありましたので追記しました。


[PR]
hashdosApacheKillerその他、Webサイトのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

2012年1月19日木曜日

Cookieによるhashdos攻撃と対策

このエントリでは、Cookieを用いたhashdos攻撃の可能性について検討し、実証結果と対策について報告します。

はじめに

既に当ブログで報告の通り、hashdosと呼ばれる攻撃手法が公表されています。HTTPリクエストのパラメータ名に対するハッシュ値を故意に同一にした(衝突させた)ものを多数(数万程度)送信することにより、Webサーバーを数分程度過負荷にできるというDoS攻撃手法です。
先の記事でも説明しているようにPOSTパラメータ(HTTPリクエストボディ)に多数のパラメータを仕込む攻撃が典型的ですが、POSTパラメータ以外のパラメータを用いた攻撃についても検討しておかないと、防御漏れの可能性が生じます。
そこで、POSTパラメータ以外を用いた攻撃方法について検討します。

POST以外に多数のパラメータを仕込めるか

POST以外に多数のパラメータを仕込む場所があるでしょうか。候補となるのは、以下と考えられます。括弧内は、PHPの該当変数です。
  • URLのクエリ文字列($_GET)
  • HTTPリクエストヘッダ($_SERVER)
  • Cookie($_COOKIE)
クエリ文字列($_GET)については、URLの長さの条件、あるいはHTTPリクエストラインの制限に引っかかります。Apacheの場合リクエストラインの制限はLimitRequestLine ディレクティブにより定義され、デフォルト値は8190バイトです。PHPに対するhashdosのPoCのサイズは約1.4メガバイトですから、8190バイトの制約では攻撃には至らないと考えられます。hashdosによる演算時間は、ハッシュ値の一致するパラメータ数の自乗に比例するためです。
リクエストヘッダ($_SERVER)の最大数は、Apacheの場合、LimitRequestFields ディレクティブで定義され、デフォルト値は100です。前述のPoCのパラメータ数は65536ですから、100という制限ではまったく攻撃には至らないと考えられます。
ということで、攻撃の余地が残るパラメータはCookieに絞られました。

Cookieによるhashdosの可能性

多数のCookieを用いたhashdos攻撃の可能性はどうでしょうか? などと書くと、RFC上のCookie数の制限を思い浮かべる方がおられるかもしれませんが、hashdosは能動的攻撃ですので、WebサーバーがどれだけのCookieを受け入れる実装になっているかに依存します。ブラウザの制限やRFC上の制限は関係ありません。
通常、Cookieは単一のCookieヘッダにより送信するので、HTTPリクエストヘッダ一つあたりのバイト数に制約されます。Apacheの場合、LimitRequestFieldSize ディレクティブにより定義され、デフォルト値は8190です。クエリ文字列の場合と同じサイズですので、このままではhashdos攻撃はできません。
しかし、複数のCookieヘッダが使えるとしたら話は変わります。最大100のCookieヘッダが使えることになり、8190×100=約800Kバイトが攻撃に使えることになります。これは攻撃には十分なサイズです。

PHPは複数のCookieヘッダを受け入れる

PHPが複数のCookieヘッダをどのように処理するかを以下のPHPスクリプトcookie.phpにより検証します。このスクリプトにはXSS脆弱性があるので、検証環境で試してください。
<?php
  var_dump($_COOKIE);
?>
以下のリクエストに対して
GET /cookie.php HTTP/1.0
Cookie: a=1;
Cookie: b=2;
以下のレスポンスが返ります。
array(2) {
  ["a"]=>
  string(1) "1"
  [",_b"]=>
  string(1) "2"
}
Cookie bも受け入れられてはいますが、改行のところでbの前にゴミの文字列が入っています。これは、hashdos攻撃に悪影響があります。
以下のリクエストではどうでしょうか。セミコロンを先頭に持ってきています。
GET /cookie.php HTTP/1.0
Cookie:;a=1
Cookie:;b=2
以下のレスポンスが返ります。
array(2) {
  ["a"]=>
  string(3) "1, "
  ["b"]=>
  string(1) "2"
}
こんどは、a, bともに名前の方にゴミはありませんが、aの値側にゴミが入りました。しかし、hashdos攻撃ではキー(パラメータ名)のみが問題になるので、攻撃には支障ありません。すなわち、PHPは複数のCookieヘッダを受け入れ、hashdos攻撃に悪用可能であると予想されます。
また、前述のPoCは、パラメータ名がパーセントエンコードされています。Cookieの場合、パーセントエンコードは必須ではありませんが、PHPの場合、名前・値とも受け取ったCookieをパーセントデコードします。すなわち、既存のPoCがCookieにも流用できることになります。

Cookieを用いたhahsdos攻撃ようのリクエストを作成する

ここまで検討したので、Cookieを用いたhashdos攻撃が成立するか、実際に試してみましょう。
POSTパラメータ用のPoCデータは、a=&b=&c=...という形式になっています。これを;a=;b=;c=...という形に変形した上で、8190バイトの制限内で、複数のCookieヘッダに切り分ける必要があります。
この処理をPerlスクリプトとして作成しました。以下に主要部分を示します。変数$aにPOSTパラメータ用のPoCデータが入っている想定です。
1: $a =~ s/&/;/g;
2: for (my $i = 0; $i < 100 && length($a) > 0; $i++) {
3:   $a =~ s/^(.{1,8180}\;)//;
4:   print "Cookie:;$1\n";
5: }
1行目で、&をセミコロン「;」に全て変換します。その上で、先頭から8180文字以内のセミコロンで終わる部分文字列を探して切り出します(3行目)。切り出した文字列は、Cookieヘッダして出力しています(4行目)。Apacheのデフォルトの制限に従い、Cookieヘッダは100個以下となるように制限しています。

試してみる

このようにして作成したCookie用PoCをPHPスクリプトにリクエストしてhashdos攻撃をしてみました。リクエストの送信には、Burp Suiteに含まれるRepeaterというツールを用いました。
結果は以下の通りです。
  • Cookie数:38166個
  • 実行時間:約4分半
hashdos攻撃の最中はCPU使用率は99%以上となりました。DoS攻撃の成功です。

対策

hashdos攻撃に対する従来の対策のうち、リクエストボディのサイズやPOSTパラメータの個数を制限する回避策は、Cookieによるhashdos攻撃には効果がありません。一方、以下は効果があります。
  • hashdos対策版のパッチを適用する(PHPの場合は5.3.9にバージョンアップしてmax_input_varsを設定する。デフォルト=1000のままでもよいが、小さいほど影響を受けにくい)
  • リクエストの処理時間を制限する(PHPの場合はmax_input_timeを小さな値にする)
  • suhosinパッチによりCookieの個数を制限する(デフォルトの最大数は100)
また、WAFによりCookieの個数を制限できれば、攻撃を回避できます。先のエントリで紹介した方法では、Cookieの個数は制限されないため、以下のエントリに追記をしておきましたので参照ください。


まとめ

Cookieによるhashdos攻撃について検討しました。理論的にCookieによるhashdos攻撃が可能であることを示した後、PoCを作成して攻撃が成立することを確認しました。
POSTパラメータを用いた攻撃への対処が、Cookieによる攻撃にも有効とは限らないので注意が必要です。



[PR]
hashdosApacheKillerその他、Webサイトのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。


2012年1月5日木曜日

hashdos攻撃をmod_securityで防御する(Ubuntu+apt-get編)

このエントリでは、hashdos対策としてのmod_securityの導入と設定の方法を説明します。Ubuntu環境でapt-getによりApacheを導入しているサイトに対して、apt-getによりmod_securityを導入するというシナリオで説明します。

はじめに

背景などについては昨日のブログを参照してください。
このエントリでは、hashdos対策を目的として、Ubuntu環境にapt-getによりmod_securityを導入する方法を説明しますが、mod_securityに対する情報があまりないため、いったんフルのmod_securityを導入した後、hashdos専用のカスタマイズを施すという流れで説明します。

Ubuntuにapt-getでmod_securityを導入する

ModSecurity Handbookによると、DebianおよびUbuntuに対して、mod_security用のパッケージが用意されている(同書P31)ということですので、試してみましょう。
# apt-get install libapache-mod-security
これでmod_securityのインストールは終わりです。簡単ですね。

mod_securityの設定

CentOSの場合と異なり、上記の状態では、mod_securityの設定はされていないようです。そこで、手動で設定する方法を説明します。
/usr/share/doc/mod-security-common にドキュメントとサンプルルール(実体はCRS2.0.3)がコピーされていますので、これを使います。最新のCRSはバージョン2.2.3ですので、サンプルとして導入されるCRSはかなり古いものですが、hashdos対策をする観点からは十分です。また、mod_securityとCRSはバージョン依存があるため、CRSのみ最新のものを入れてもエラーになる可能性が高いのです。最新のCRSを使いたい場合は、最新のmod_securityをソースからビルドしてください。その方法は次回説明します。

まず、/usr/share/doc/mod-security-common/examples/rules 以下のルールを/etc/apache2/modsecurity にコピーします。
# cd /etc/apache2/
# cp -R /usr/share/doc/mod-security-common/examples/rules modsecurity
ルールから logs というディレクトリをログ書き出し用に参照しているので、シンボリックリンクで /var/log/apache2 を指すようにしておきます。
# ln -s /var/log/apache2 logs
Ubuntuの習慣に従い、/etc/apache2/mods-available にmod_securityのconfファイルを作成します。
# vi /etc/apache2/mods-available/mod-security.conf
内容は以下の通りです。
Include modsecurity/*.conf
Include modsecurity/base_rules/*conf
保存した後、a2enmodコマンドでこの設定を反映します。
# a2enmod mod-security
modsecurity_crs_10_config.confというファイルを変更します。
# vi /etc/apache2/modsecurity/modsecurity_crs_10_config.conf
変更内容は以下の通りです。
SecResponseBodyAccess Off ← On から Off にする
これは、レスポンスの中身のチェックをしないという設定です。以上でmod_securityの通常設定は終わりです。

mod_securityの動作確認

次に、mod_securityの動作確認をします。apacheを起動してください。/var/log/apache2以下に、modsec_audit.log と modsec_debug.log ができていれば、正常に起動されています。
まず正常系のアクセスを確認します。以下のURLはサンプルですので、既存コンテンツのURLを指定して下さい。
http://example.jp/index.php
次に、以下がmod_securityによりブロックされることを確認します。既存コンテンツの後ろに、「?union+select」をつけてアクセスします。
http://example.jp/index.php?union+select
403 Forbiddenのエラーが表示されれば、mod_securityが稼働していることになります。

mod_securityのカスタマイズ

次に、hashdos向けのカスタマイズです。再び、modsecurity_crs_10_config.confを変更します。
# vi /etc/apache2/modsecurity/modsecurity_crs_10_config.conf
変更内容は以下の通りです。
SecRequestBodyInMemoryLimit 131072 の後ろに以下を追加する
# 追加
SecRequestBodyLimit 5242880
SecRequestBodyNoFilesLimit 51200
この例では、リクエストボディサイズを5Mバイトに増やし、SecRequestBodyNoFilesLimitを50Kに設定しています。SecRequestBodyNoFilesLimitは、ファイルアップロード以外のPOSTサイズの制限(application/x-www-form-urlencoded形式の場合に有効)なので、hashdosに効果があります。5Mと50Kは、Webサイトの要件にあわせて調整して下さい。

次に、/etc/apache2/modsecurity/base_rules/modsecurity_crs_23_request_limits.conf を修正します。以下の部分を修正します。
# Maximum number of arguments in request limited
SecRule &ARGS "@gt 255" "phase:2,t:none,block,nolog,auditlog,status:403,msg:'Too many arguments in request',id:'960335',severity:'4',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+5,setvar:tx.policy_score=+1,setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
変更後の内容は以下の通りです。
# Maximum number of arguments in request limited
SecRule &ARGS "@gt 255" "phase:2,t:none,deny,nolog,auditlog,ctl:auditLogParts=ABDFGH,status:413,msg:'Too many arguments in request',id:'960335',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+20,setvar:tx.policy_score=+1,setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
主な変更点は以下の通りです。
  • パラメータ数が255を超えたら直ちに遮断する
  • ログを取得するが、リクエストボディは出力しない(昨日の記事参照)
パラメータ数上限値255がハードコーディングされているので、Webアプリケーションの正常系のパラメータ数が255を超える場合は、この値を変更してください。
以上でhashdos向けのカスタマイズは終わりですが、昨日の記事同様、hashdos以外のルールを無効にします。本格的にmod_securityを使う(SQLインジェクションやXSS等の対策にも用いる)場合は、以下の作業は省略しますが、その代わりmod_securityの過剰検知を検出して該当するルールを無効化するというチューニングが必要です。

*追記(2012/1/18)
Cookieによるhashdos攻撃が可能であり、上記のルールではCookieによる攻撃を防御できませんので、以下のルールを追加するとよいでしょう。
SecRule &REQUEST_COOKIES "@gt 30" "phase:2,t:none,deny,nolog,auditlog,ctl:auditLogParts=AF
HZ,status:413,msg:'Too many cookies in request',id:'960336',severity:'2',setvar:'tx.msg=%{
rule.msg}',setvar:tx.anomaly_score=+20,setvar:tx.policy_score=+1,setvar:tx.%{rule.id}-POLI
CY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
"@gt 30"がCookie数の上限でハードコーディングされています。適宜変更してください。
(追記終わり)

mod-security.confを修正します。
# vi /etc/apache2/mods-available/mod-security.conf

Include modsecurity/*.conf
### Include modsecurity/base_rules/*conf ← 削除またはコメントアウト
# 以下を追加
Include modsecurity/base_rules/modsecurity_crs_23_request_limits.conf
Include modsecurity/base_rules/modsecurity_crs_49_enforcement.conf
Include modsecurity/base_rules/modsecurity_crs_60_correlation.conf
昨日の記事では、49と60のルールも無効化していましたが、CRSの仕組みをきちんと動かすにはこれらのルールがあった方が良いようですので、残しています。なくてもhashdosに対する保護はできます。

以上の修正の後、apacheを再起動してください。
昨日も書きましたが、mod_securityの副作用の可能性があるので、一通りのアプリケーションのチェックをしておくべきです。とくに、ファイルアップロードが影響を受けやすいので、ファイルアップロード機能がある場合(このエントリが想定しているサイトですが)は、必ずファイルアップロードが正常に動作することを確認してください。

まとめ

Ubuntにapt-get環境でApacheを導入している環境向けに、mod_securityによるhashdos対策の方法を説明しました。
次回は、mod_securityをソースからビルドする方法について説明します。


[PR]
hashdosApacheKillerその他、Webサイトのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

2012年1月4日水曜日

hashdos攻撃をmod_securityで防御する(CentOS+yum編)

このエントリでは、hashdos対策としてのmod_securityの導入と設定の方法を説明します。CentOS環境でyumによりApacheを導入しているサイトに対して、yumによりmod_securityを導入するというシナリオで説明します。

はじめに

既に当ブログで報告の通り、hashdosと呼ばれる攻撃手法が公表されています。HTTPリクエストのパラメータ名に対するハッシュ値を故意に同一にした(衝突させた)ものを多数(数万程度)送信することにより、Webサーバーを数分程度過負荷にできるというDoS攻撃手法です。まだhashdosによる攻撃事例は報告されていないようですが、既に攻撃コード(PoC)が公表されているため、いつ攻撃が起こっても不思議ではない状況です。
PHPも影響を受けるプラットフォームであり、PHP5.3.9で対処予定となっていますが、まだPHP5.3.9はリリースされていません。また、PHP5.3.9にすぐに移行できないWebサイトも多いことと思います。
PHP5.3.9に移行する以外の対処方法としては以下が考えられます。

  • HTTPリクエストボディ(POST変数)のサイズを数十KB以下に制限する
  • suhosinパッチを導入する。suhosin.post.max_vars(デフォルトは1000)をさらに制限するとなお良し

しかし、利用者に画像などのアップロード機能を提供しているWebサイトなど、上記を実行できないWebサイトも多いと予想します。

そこで対策案として浮上するのがWAFの導入です。WAFでパラメータ数の制限ができる場合、hashdos攻撃を有効に緩和できます。その例として、mod_securityをCentOSにyumで導入し、hashdos対策用に設定する例を紹介します。

CentOSにyumでmod_securityを導入する

CentOSのデフォルトのリポジトリでは、mod_securityはサポートされていません。このため、リポジトリを追加する必要があります。mod_securityの本家では、utterramblingsリポジトリを紹介していますが、CentOS6の対応が不明確でしたので、このエントリでは、CentOS5とCentOS6の両方に対応しているEPELリポジトリを使った導入方法を説明します。
まず、EPELリポジトリを設定します。
# rpm -Uvh http://download.fedora.redhat.com/pub/epel/6/i386/epel-release-6-5.noarch.rpm
CentOS5系とCentOS6および32ビットと64ビットでリポジトリ設定用のURLが異なるので、以下に示します。

CentOS6用
32ビット: http://download.fedora.redhat.com/pub/epel/6/i386/epel-release-6-5.noarch.rpm
64ビット: http://download.fedora.redhat.com/pub/epel/6/x86_64/epel-release-6-5.noarch.rpm

CentOS5用
32ビット: http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
64ビット: http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm

EPELリポジトリは普段使わないので、デフォルトでは使用しない設定にしておきます。/etc/yum.repos.d/epel.repo というファイルを編集して、[epel]グループの enabled=1 の行を enabled=0 に変更します。
[epel]
...
enabled=0
以上で準備ができましたので、yumでmod_securityをインストールします。先にEPELリポジトリを無効化しているので、以下のようにepelリポジトリを明示してインストールします。
# yum --enablerepo=epel install mod_security
これでmod_securityのインストールは終わりです。CRS(Core Rule Set)も同時にインストールされます。

mod_securityの動作確認

ここで、いったんmod_securityの動作確認をします。apacheを起動し、まずは正常系のアクセスを確認します。以下のURLはサンプルですので、既存コンテンツのURLを指定して下さい。
http://example.jp/index.php
次に、以下がmod_securityによりブロックされることを確認します。既存コンテンツの後ろに、「?union+select」をつけてアクセスします。
http://example.jp/index.php?union+select
403 Forbiddenのエラーが表示されれば、mod_securityが稼働していることになります。監査ログが /var/log/httpd/modsec_audit.log というファイル名で生成されているはずなので、確認しておきます。

ルールのカスタマイズ

次に、mod_securityのルールをカスタマイズします。上記の例(「union select」をブロックする)でもわかりますが、mod_securityに付属するCRS(Core Rule Set)は、やや過剰気味のチューニングになっています。mod_securityにじっくり付き合うのであれば、CRSをまじめにチューニングすればよいのですが、取り急ぎhashdos攻撃だけに対処するのであれば、思い切って他のルールは削除してしまいましょう。
そのためには、以下のようにします。/etc/httpd/conf.d/mod_security.conf を編集します。
Include modsecurity.d/*.conf
Include modsecurity.d/base_rules/*.conf
上記の部分を以下のように変更します(2行目のみ)。
Include modsecurity.d/*.conf
Include modsecurity.d/base_rules/modsecurity_crs_23_request_limits.conf
これにより、HTTPリクエストのサイズ制限のみのルールとなります。XSSやSQLインジェクションは防御できくなくなりますが、目をつぶることにします。

次に、同じファイルの以下の部分を修正します。
SecRequestBodyLimit 131072
リクエストボディの上限が131072バイト(128KB)に制限されています。これを以下のように変更します。
SecRequestBodyLimit 5242880
# 追加
SecRequestBodyNoFilesLimit 51200
上記例では、リクエストボディサイズを5Mバイトに増やし、新たにSecRequestBodyNoFilesLimitを50Kに設定しています。SecRequestBodyNoFilesLimitは、ファイルアップロード以外のPOSTサイズの制限(application/x-www-form-urlencoded形式の場合に有効)なので、hashdosに効果があります。5Mと50Kは、Webサイトの要件にあわせて調整して下さい。

次に、/etc/httpd/modsecurity.d/modsecurity_crs_10_config.conf というファイルを確認します。
## Maximum number of arguments in request limited
SecAction "phase:1,t:none,nolog,pass,setvar:tx.max_num_args=255"
tx.max_num_args=255 は、Webアプリケーションが受け取るパラメータの個数の上限値です。通常はこのままでよいと思いますが、パラメータ数が特に多いアプリケーションの場合は、この値を要件に合わせて増やします。

次に、/etc/httpd/modsecurity.d/base_rules/modsecurity_crs_23_request_limits.conf を修正します。
# Maximum number of arguments in request limited
SecRule &TX:MAX_NUM_ARGS "@eq 1" "chain,phase:2,t:none,pass,nolog,auditlog,msg:'Too ma
ny arguments in request',id:'960335',severity:'4',rev:'2.0.5'"
        SecRule &ARGS "@gt %{tx.max_num_args}" "t:none,setvar:'tx.msg=%{rule.msg}',setvar:
tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.policy_score=+%{tx.notice_anomaly_s
core},setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"
このルールでパラメータ数をチェックしていますが、こままでは単なる警告でブロックしてくれません。このため、1番目のSecRuleにあるpassをdenyに修正しましょう。
SecRule &TX:MAX_NUM_ARGS "@eq 1" "chain,phase:2,t:none,deny,log,ctl:auditLogParts=ABDFGH,m
sg:'Too many arguments in request',id:'960335',severity:'2',rev:'2.0.5'"
上記では、「log,ctl:auditLogParts=ABDFGH」も追加しました。これは、ログを出力するが、POSTパラメータは出力しないと言う意味です。hashdosのPOSTパラメータは大きくなるので、ログを保存するとディスク容量が圧迫され、一種のDoS攻撃を受けることになるのでPOSTパラメータを除外しています。しかし、研究目的などでPOSTパラメータを保存したい場合は、「ctl:auditLogParts=ABDFGH」の部分を削除して下さい。

現実には、SecRequestBodyNoFilesLimitの方でブロックされるケースが大半だと思いますが、multipart/form-data形式(ファイルアップロードに使われる)でhashdos攻撃される可能性もあるので、上記は必要です。

*追記(2012/1/18)
Cookieによるhashdos攻撃が可能ですので、以下のルールを追加するとよいでしょう。

# Maximum number of Cookies
SecRule &TX:MAX_NUM_ARGS "@eq 1" "chain,phase:2,t:none,deny,log,ctl:auditLogParts=AFHZ,msg
:'Too many cookies in request',id:'960336',severity:'2',rev:'2.0.5'"
        SecRule &REQUEST_COOKIES "@gt %{tx.max_num_args}" "t:none,setvar:'tx.msg=%{rule.ms
g}',setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.policy_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"

Cookie数の上限はtx:max_num_argsを流用しています。255はCookie数の上限としては大きすぎますが、それほど問題にはならないと思います。しかし、さらに安全を期するには、30などとハードコーディングするか、Cookie数の最大値として別の変数を定義するとよいでしょう。
(追記終わり)


ルールのカスタマイズが終わったので、Apacheを再起動して下さい。
mod_securityの副作用の可能性があるので、一通りのチェックをしておくべきです。とくに、ファイルアップロードが影響を受けやすいので、ファイルアップロード機能がある場合(このエントリが想定しているサイトですが)は、必ずファイルアップロードが正常に動作することを確認してください。

まとめ

CentOSにyum環境でApacheを導入している環境向けに、mod_securityによるhashdos対策の方法を説明しました。
yumを使わないでソースからビルドしている場合や、Ubuntu向けの設定方法も予定しております。

[PR]
hashdosApacheKillerその他、Webサイトのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。
安全なWebアプリケーションの作り方DRMフリーのPDFによる電子版もあります。

フォロワー