LoginSignup
16
16

More than 5 years have passed since last update.

ModSecurityによるStruts脆弱性対策

Posted at

日本のStruts1の脆弱性(CVE-2014-0114)対応は素早く粛々と行われているようで、なによりです。

こちらの記事で

  1. BeanUtilsのResolverを差し替える方法
  2. RequestProcessorを差し替える方法

について書きました。

どちらもJavaアプリケーションレイヤでの対策ですが、ModSecurityを使ってもキチンと穴塞げるようなのでやってみました。これはAPサーバの前にApacheがいることが前提になりますが、対策は非常に簡単です。

ModSecurityのセットアップ

Ubuntu系は、aptでインストールできます。

% sudo apt-get install libapache2-modsecurity

そうすると、/etc/modsecurity/modsecurity.conf-recommendedにコンフィグのexampleが置かれているはずなので、これをコピーして編集します。

% sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

ファイル最後尾にでも、

SecRule ARGS_NAMES "(^|\.)[cC]lass\." "deny,log,status:403"

を追加します。これはclass,Classを含むネストしたパラメータの場合、そのリクエストを拒否し、ログを書き、403でレスポンスを返すというルールです。詳しくはリファレンスマニュアルをみてください。
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual

/etc/apache2/mods-available\mod-security.conf中に、Include "/etc/modsecurity/*.conf"の記述があるので、後はモジュールを有効化して、再起動するだけです。

% sudo a2enmod mod-security
% sudo apache2ctl restart

テスト

それではこのルールが有効かどうか試してみます。あとでマルチパートのリクエストもテストするので、そういうときはJMeterを使うと便利です。

スレッドグループにHTTPリクエストのサンプラーを追加し、パスやパラメータを設定します。

SnapCrab_NoName_2014-5-3_0-16-59_No-00.png

これを"結果をツリーで表示"のリスナーを追加して実行すると、実行結果が見れます。

SnapCrab_NoName_2014-5-3_0-17-34_No-00.png

ちゃんと、403で弾かれてますね!

さて、問題はServletFilterでは難しかったMultipartのパラメータもチェックできるか、です。mod_securityはMultipartも一度パースして、再構成して後ろのフックに回す機能があります。JMeterでマルチパートのリクエストを作るのはチョー簡単です。以下のようにメソッドをPOSTにしてMultipartのチェックボックスにチェックつけるだけです。

SnapCrab_NoName_2014-5-3_0-22-48_No-00.png

さて、こちらも実行してみます。

SnapCrab_NoName_2014-5-3_0-25-54_No-00.png

ヤリました!マルチパートでもちゃんと403が返りルールにしたがってチェックかかっていることが分かります。

正しくModSecurityが動いた結果かどうかは、auditログが出力されているので、そちらで確認できます。

/var/log/apache2/modsec_audit.log
[03/May/2014:00:25:06 +0900] U2O40n8AAQEAADImF4IAAAAB 127.0.0.1 32834 127.0.0.1 80
--de079d50-B--
POST / HTTP/1.1
Connection: keep-alive
Content-Length: 238
Content-Type: multipart/form-data; boundary=ioU4y3E5yzasxHc7HgXGrFwUCF9AKmWVKAHv5Zh
Host: localhost
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)

--de079d50-I--
class%2eclassLoader%2ehoge=hehehe
--de079d50-F--
HTTP/1.1 403 Forbidden
Vary: Accept-Encoding
Content-Length: 277
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--de079d50-E--
<!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 /
on this server.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at localhost Port 80</address>
</body></html>

--de079d50-H--
Message: Access denied with code 403 (phase 2). Pattern match "(^|\\.)[cC]lass\\." at ARGS_NAMES:class.classLoader.hoge. [file "/etc/modsecurity/modsecurity.conf"] [line "207"]
Action: Intercepted (phase 2)
Stopwatch: 1399044306059830 1099 (- - -)
Stopwatch2: 1399044306059830 1099; combined=91, p1=34, p2=44, p3=0, p4=0, p5=13, sr=0, sw=0, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.6.3 (http://www.modsecurity.org/).
Server: Apache/2.2.22 (Ubuntu)

--de079d50-J--
Total,0

--de079d50-Z--

こんな感じでログが出力されています。大丈夫そうですね。

ModSecurityによるオーバーヘッド

さて、既存の環境にModSecurityを適用する場合、気になるのはその性能オーバーヘッドです。
せっかくのJMeterなのでスループットを測ってみます。サーバサイドの処理はなく普通のApacheのエラーを返すだけの処理です。

添付ファイル(500kb)あり (100スレッド/無限ループ)

ModSecurity スループット(/sec) 90%ライン (msec)
有(正常リクエスト) 527 297
有(正常リクエスト) 504 335
1147 6

添付ファイルなし (100スレッド/無限ループ)

ModSecurity スループット(/sec) 90%ライン (msec)
有(正常リクエスト) 6415 8
有(攻撃リクエスト) 4444 37
7199 1

マルチパートをパースして再構成するので、やはりマルチパートでのリクエストが多い場合は、結構なオーバーヘッドになるようです。が、Apacheに余裕があってファイルアップロードのリクエストがそんなに殺到するものでない場合においては、90%ラインは実用的な数値なので、ModSecurityの導入検討の価値はあるかと思います。

16
16
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16