Ubuntu 14.04およびDebian 8でApacheにModSecurityを設定する方法

前書き

ModSecurityは、Apache、Nginx、およびIISで動作する無料のWebアプリケーションファイアウォール(WAF)です。 シンプルで複雑な操作を実行するための柔軟なルールエンジンをサポートし、SQLインジェクション、クロスサイトスクリプティング、トロイの木馬、悪意のあるユーザーエージェント、セッションハイジャック、その他の多くのエクスプロイトのルールを持つコアルールセット(CRS)が付属しています。 Apacheの場合、追加モジュールとしてロードされるため、インストールと設定が簡単になります。

前提条件

このチュートリアルを実行するには、次のものが必要です。

ステップ1-ModSecurityのインストール

このステップでは、ModSecurityをインストールします。

まず、パッケージインデックスファイルを更新します。

sudo apt-get update

次に、ModSecurityをインストールします。

sudo apt-get install libapache2-mod-security2 -y

ModSecurityモジュールがロードされたことを確認するには、次のコマンドを使用します。

sudo apachectl -M | grep --color security2

出力に「+ security2_module(shared)+」と表示されている場合、これはモジュールがロードされたことを示します。

ModSecurityのインストールには、名前を変更する必要がある推奨構成ファイルが含まれています。

sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

最後に、Apacheをリロードします。

sudo service apache2 reload

ModSecurityの新しいログファイルは、 `+ / var / log / apache2 / modsec_audit.log +`のApacheログディレクトリに作成されます。

ステップ2-ModSecurityの構成

すぐに使用できるModSecurityは、動作するルールが必要なため、何もしません。 このステップでは、まずいくつかの設定ディレクティブを有効にします。

このステップで設定ディレクティブを見つけて置き換えるには、ストリームエディタである + sed +`を使用します。 ツールの詳細については、https://www.digitalocean.com/community/tutorial_series/using-sed [+ sed +`チュートリアルシリーズ]を参照してください。

有効にする基本的なディレクティブ

デフォルトのModSecurity設定ファイルは `+ DetectionOnly `に設定されます。これは、ルールの一致に応じてリクエストを記録し、何もブロックしません。 これは、 ` modsecurity.conf `ファイルを編集し、 ` SecRuleEngine +`ディレクティブを変更することで変更できます。 実稼働サーバーでこれを試行する場合は、すべてのルールをテストした後にのみ、このディレクティブを変更してください。

sudo sed -i "s/SecRuleEngine DetectionOnly/SecRuleEngine On/" /etc/modsecurity/modsecurity.conf

`+ SecResponseBodyAccess +`ディレクティブは、応答本文がバッファリングされるかどうかを設定します(つまり、 ModSecurityによって読み取られます)。 これは、データ漏洩の検出と保護が必要な場合にのみ必要です。 したがって、オンのままにすると、Dropletリソースが消費され、ログファイルのサイズも大きくなるため、オフにします。

sudo sed -i "s/SecResponseBodyAccess On/SecResponseBodyAccess Off/" /etc/modsecurity/modsecurity.conf

変更するオプションのディレクティブ

`+ / etc / modsecurity / modsecurity.conf `を編集してカスタマイズしたい他のディレクティブがあります。 ` SecRequestBodyLimit `および ` SecRequestBodyNoFilesLimit +`ディレクティブは、Webアプリケーションに投稿できる最大データを制限します。

特に、 `+ SecRequestBodyLimit `ディレクティブは最大POSTデータサイズを指定します。 クライアントからより大きなものが送信されると、サーバーはhttp://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413[413 Request Entity Too Large]エラーで応答します。 Webアプリケーションにファイルのアップロードがない場合、この値はそのままにしておくことができます。 構成ファイルで指定される事前構成値は、13107200バイト(12.5MB)です。 この値を変更したい場合は、次の行 ` modsecurity.conf +`を探してください:

オプションの `modsecurity.conf`ディレクティブの変更

SecRequestBodyLimit

同様に、 `+ SecRequestBodyNoFilesLimit `は、POSTデータからファイルのアップロードを差し引いたサイズを制限します。 この値は、誰かが非常に大きなサイズのリクエストボディを送信している場合に、サービス拒否(DoS)攻撃を受けやすくするために、できるだけ低く設定する必要があります。 構成ファイルの事前構成値は131072バイト(128KB)です。 この値を変更したい場合は、次の行 ` modsecurity.conf +`を探してください:

オプションの `modsecurity.conf`ディレクティブの変更

SecRequestBodyNoFilesLimit

サーバーのパフォーマンスに影響するディレクティブは、 `+ SecRequestBodyInMemoryLimit `です。 このディレクティブはほとんど自明です。メモリ(RAM)に保持する「リクエストボディ」データ(POSTしたデータ)の量を指定します。それ以上はハードディスクに配置されます(スワッピングと同様)。 DropletsはSSDを使用するため、これはそれほど大きな問題ではありません。 ただし、RAMに余裕がある場合は、これを変更できます。 このディレクティブの事前構成値は128KBです。 この値を変更したい場合は、次の行 ` modsecurity.conf +`を探してください:

オプションの `modsecurity.conf`ディレクティブの変更

SecRequestBodyInMemoryLimit

ステップ3-SQLインジェクションのテスト

いくつかのルールを設定する前に、SQLインジェクションに対して脆弱なPHPスクリプトを作成して、ModSecurityの保護をテストします。

まず、MySQLプロンプトにアクセスします。

mysql -u root -p

ここで、* sample *というMySQLデータベースを作成して接続します。

create database ;
connect ;

次に、ユーザー名* sammy とパスワード password *の資格情報を含むテーブルを作成します。

create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('sammy','password');

最後に、MySQLプロンプトを終了します。

quit;

次に、Apacheのドキュメントルートにログインスクリプトを作成します。

sudo nano /var/www/html/login.php

次のPHPスクリプトをファイルに貼り付けます。 スクリプトがデータベースに接続できるように、以下のスクリプトのMySQLパスワードを以前に設定したものに変更してください。

/var/www/html/login.php

<html>
<body>
<?php
   if(isset($_POST['login']))
   {
       $username = $_POST['username'];
       $password = $_POST['password'];
       $con = mysqli_connect('localhost','root','','sample');
       $result = mysqli_query($con, "SELECT * FROM `users` WHERE username='$username' AND password='$password'");
       if(mysqli_num_rows($result) == 0)
           echo 'Invalid username or password';
       else
           echo '<h1>Logged in</h1><p>This is text that should only be displayed when logged in with valid credentials.</p>';
   }
   else
   {
?>
       <form action="" method="post">
           Username: <input type="text" name="username"/><br />
           Password: <input type="password" name="password"/><br />
           <input type="submit" name="login" value="Login"/>
       </form>
<?php
   }
?>
</body>
</html>

このスクリプトは、ログインフォームを表示します。 ブラウザを開き、 `+ http:/// login.php +`に移動して表示します。 資格情報の正しいペアを入力した場合、例えば * Username フィールドのsammyと Password フィールドのパスワードには、メッセージが表示されます*これは、有効な資格情報でログインしたときにのみ表示されるテキストです。 ログイン画面に戻り、間違った資格情報を使用すると、* Invalid username or password *というメッセージが表示されます。

次の仕事は、SQLインジェクションを試行してログインページをバイパスすることです。 ユーザー名フィールドに次を入力します。

SQLインジェクションのユーザー名

' or true --

このインジェクションが機能するためには、「-」の後にスペースが必要です。 パスワードフィールドを空のままにして、ログインボタンを押します。 スクリプトは、認証されたユーザー向けのメッセージを表示します! 次のステップでは、これを防ぎます。

ステップ4-ルールの設定

このステップでは、いくつかのModSecurityルールを設定します。

CRSの有効化

物事を簡単にするために、ModSecurityとともにすでにインストールされている多くのルールがあります。 これらはCRS(コアルールセット)と呼ばれ、 `+ / usr / share / modsecurity-crs `ディレクトリにあります。 これらのルールをロードするには、これらのディレクトリの ` .conf `ファイルを読み取るようにApacheを設定する必要があります。そのため、編集のために ` security2.conf +`ファイルを開きます。

sudo nano /etc/apache2/mods-enabled/security2.conf

ファイル内の最後の行( + </ IfModule> +)の前に、赤で強調表示された次の2つのディレクティブを追加します。

更新されたsecurity2.conf

       IncludeOptional /etc/modsecurity/*.conf


</IfModule>

ファイルを保存して閉じます。

ディレクトリ/ドメインの除外(オプション)

ModSecurityがSQLクエリをブロックするため、phpMyAdminなどのアプリケーションを実行している場合、特定のディレクトリまたはドメイン名を除外することが理にかなっている場合があります。 また、WordPressなどのCMSアプリケーションの管理バックエンドを除外することをお勧めします。 新しいサーバーでこのチュートリアルを実行している場合は、この手順をスキップできます。

完全なVirtualHostのModSecurityを無効にするには、その仮想ホストファイルの `+ <VirtualHost> […​] </ VirtualHost> +`ブロック内に次のディレクティブを配置します。

<IfModule security2_module>
   SecRuleEngine Off
</IfModule>

特定のディレクトリ(たとえば、「+ / var / www / wp-admin」)を省略する場合:

<Directory "">
   <IfModule security2_module>
       SecRuleEngine Off
   </IfModule>
</Directory>

ディレクトリでModSecurityを完全に無効にしたくない場合は、 `+ SecRuleRemoveById +`ディレクティブを使用して、IDを指定して特定のルールまたはルールチェーンを削除します。

<LocationMatch "">
   <IfModule security2_module>
       SecRuleRemoveById
   </IfModule>
</LocationMatch>

SQLインジェクションルールのアクティブ化

次に、SQLインジェクションルールファイルをアクティブにします。 必要なルールファイルは、Apacheの `+ mods-enabled `ディレクトリに似た ` activated_rules `ディレクトリにシンボリックリンクする必要があります。 ` activated_rules +`ディレクトリに移動します。

cd /usr/share/modsecurity-crs/activated_rules/

次に、 `+ modsecurity crs_41_sql_injection_attacks.conf`ファイルからシンボリックリンクを作成します。

sudo ln -s ../base_rules/modsecurity_crs_41_sql_injection_attacks.conf .

最後に、ルールを有効にするためにApacheをリロードします。

sudo service apache2 reload

ここで、以前に作成したログインページを開き、ユーザー名フィールドで同じSQLインジェクションクエリを使用してみます。 ステップ2で `+ SecRuleEngine `ディレクティブを ` On `に変更したため、* 403 Forbidden *エラーが表示されます。 ( ` SecRuleEngine `が ` DetectionOnly `オプションに任されている場合、インジェクションは成功しますが、試行は ` modsec_audit.log +`ファイルに記録されます。)

このPHPログインスクリプトはModSecurityのテストのみを目的としているため、テストが完了したら削除する必要があります。

sudo rm /var/www/html/login.php

ステップ5-独自のルールの作成

このセクションでは、スパムに一般的に関連付けられている特定の単語がHTMLフォームに入力された場合にリクエストをブロックするルールチェーンを作成します。

最初に、テキストボックスから入力を取得してユーザーに表示するサンプルPHPスクリプトを作成します。 編集のために `+ from.php`というファイルを開きます。

sudo nano /var/www/html/form.php

次のコードを貼り付けます。

/var/www/html/form.php

<html>
   <body>
       <?php
           if(isset($_POST['data']))
               echo $_POST['data'];
           else
           {
       ?>
               <form method="post" action="">
                       Enter something here:<textarea name="data"></textarea>
                       <input type="submit"/>
               </form>
       <?php
           }
       ?>
   </body>
</html>

カスタムルールは、任意の構成ファイルに追加するか、ModSecurityディレクトリに配置できます。 `+ modsecurity_custom_rules.conf +`という別の新しいファイルにルールを配置します。

sudo nano /etc/modsecurity/.conf

このファイルに次を貼り付けます。 ブロックしている2つの単語は、* blockedword1 blockedword2 *です。

modsecurity_custom_rules.conf

SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_BODY "@rx (?i:(|))"

+ SecRule +`の構文は `+ SecRule VARIABLES OPERATOR [ACTIONS] +`です。 ここでは、チェーンアクションを使用して、変数 `+ REQUEST_FILENAME +`と `+ form.php ++ REQUEST_METHOD +`と `+ POST +、および + REQUEST_BODY +`と正規表現 `+(@ rx)+ string ` (blockedword1 | blockedword2) `。 `?i:`は、大文字と小文字を区別しないマッチングを行います。 これらの3つのルールすべてが正常に一致すると、 `+ ACTION `は拒否され、 ` msg" Spam detected。 "+`でログに記録されます。チェーンアクションは3つのルールすべてに一致する論理ANDをシミュレートします。

ファイルを保存し、Apacheをリロードします。

sudo service apache2 reload

ブラウザで `+ http:/// form.php +`を開きます。 blockedword1またはblockedword2を含むテキストを入力すると、403ページが表示されます。

このPHPフォームスクリプトはModSecurityのテストのみを目的としているため、テストが完了したら削除する必要があります。

sudo rm /var/www/html/form.php

結論

このチュートリアルでは、ModSecurityをインストールおよび構成し、カスタムルールを追加する方法を学習しました。 詳細については、https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual [ModSecurityの公式ドキュメント]をご覧ください。