mod_rewrite を用いた様々なアクセス制御


インターネットに公開されているWebアプリケーションは絶えず様々な攻撃にさらされています。このような攻撃を防ぐためには、Webアプリケーションに攻撃対象となるセキュリティホールを作らないことが大切ですが、Webアプリケーションは様々なライブラリやプラグインが複雑に絡み合っており、セキュリティホールを完全に無くすことは極めて困難となっております。またゼロデイ攻撃のようにセキュリティホールの発見、対策が行われる前に攻撃にさらされることも近年、とても増加しています。そこで今回、Webサーバに対する不必要なアクセスを可能な限りブロックするために、mod_rewrite を簡易的なWebアプリケーションファイヤーウォールとして用いることを試みました。

mod_rewrite は Apache 用のモジュールで、URLの書き換えを行うことを目的に古くから使用されてきました。しかしながら mod_rewrite はURLの書き換えだけではなく、クライアントやリクエスト、ブラウザの情報を元に条件を設定することで様々なアクセスを制御を行うことが可能です。

具体的には以下のようなアクセス制御が可能です。

  • 特定のIPアドレスからのアクセスを拒否、もしくは特定のIPアドレスからのアクセスのみを許可
  • 特定のホスト名からのアクセスを拒否、もしくは許可
  • 特定のURLへのアクセスを拒否、もしくは許可
  • 特定の文字列を含むユーザエージェントのアクセスを拒否、もしくは許可
  • 特定の文字列を含むリファラーからのアクセスを拒否、もしくは許可
  • 特定の文字列を含むクッキーがある場合のみアクセスを拒否、もしくは許可
  • 特定の言語のブラウザのみアクセスを拒否、もしくは許可
  • 特定のクエリ文字列を含むアクセスを拒否、もしくは許可
  • 特定のリクエストメソッドを拒否、もしくは許可
  • 特定の日時、時間帯のみアクセスを拒否、もしくは許可

上記の条件は全て組み合わせることが可能です。mod_rewrite をWebアプリケーション ファイヤーウォールとして利用する場合のメリット、デメリットは以下のようなものがあります。

メリット

  • 汎用性が高い。OSやフレームワーク、Webアプリケーションに依存せずに設定が可能。
  • 様々なアクセス制限のルールを1つのファイル(.htaccess)で簡潔に書くことができる。

デメリット

  • 動的なルールの作成が難しい。(例えば一定回数アクセスした場合に拒否する等)
  • 通信内容(POSTデータ等)によるルールの作成ができない。
  • 正規表現や独自の記述方法を理解する必要がある。

mod_rewrite の利用方法

mod_rewrite を利用するには事前に Apache の設定ファイル(httpd.conf)にて以下のような形式で rewrite_module モジュールをロードする必要があります。

LoadModule rewrite_module modules/mod_rewrite.so

ディレクトリごとの設定を有効するために、以下のように <Directory /> 内で AllowOverride All と設定されていることを確認します。実際の mod_rewrite の設定については、対象となるディレクトリに .htaccess ファイル を作成し、そのファイルに記述します。

<Directory "/var/www/html/xxx">
AllowOverride All
</Directory>

.htaccess ファイルの作成方法

基本構文

アクセス制御をする対象のディレクトリに .htaccess ファイル を作成し、アクセス制御の設定を記述します。基本構文は以下の通りです。

# 条件1を満たす場合にアクセス拒否
RewriteCond 条件1
RewriteRule ^.*$ - [F,L]

# 条件1と条件2を満たす場合にアクセス拒否 (AND条件)
RewriteCond 条件1
RewriteCond 条件2
RewriteRule ^.*$ - [F,L]

# 条件1もしくは条件2を満たす場合にアクセス拒否 (OR条件)
RewriteCond 条件1 [OR]
RewriteCond 条件2
RewriteRule ^.*$ - [F,L]

RewriteCond の行に条件を、 RewriteRule に条件に一致する場合に適用するURLの書き換えルールを記述します。条件は正規表現を使用します。

^  ・・・ 先頭とマッチ
$  ・・・ 末尾とマッチ
.* ・・・ 任意の文字列(ワイルドカード)
\. ・・・ ドット
.  ・・・ 半角空白
!  ・・・ マッチしない場合

また以下のような独自フラグを使用します。

[OR] ・・・ OR条件とする
[NC] ・・・大文字小文字を区別しない
[F] ・・・ 403-Forbidden(アクセス禁止)
[L] ・・・ 終了

特定のIPアドレスからのアクセスを拒否、もしくは特定のIPアドレスからのアクセスのみを許可

例えばIPアドレス、12.12.12.12 からのアクセスを拒否する場合は、以下のように記述します。

RewriteEngine On
RewriteCond   %{REMOTE_ADDR} ^12\.12\.12\.12$
RewriteRule ^.*$ - [F,L]

逆に IPアドレス、12.12.12.12 からのみアクセスを許可する場合には以下のように記述します。

RewriteEngine On
RewriteCond   %{REMOTE_ADDR} !^12\.12\.12\.12$
RewriteRule ^.*$ - [F,L]

ただしIPアドレスによるアクセス制限は、Apache 自体の機能によって以下のように簡潔に記述することが可能です。

deny from 12.12.12.12
deny from all
allow from 12.12.12.12

特定のホスト名からのアクセスを拒否、もしくは許可

例えば xxx.com で終わるホスト名のアクセスを拒否する場合は、以下のように記述します。

RewriteEngine On
RewriteCond   %{HTTP_HOST} ^.*xxx\.com$
RewriteRule ^.*$ - [F,L]

特定のURLへのアクセスを拒否、もしくは許可

例えば /admin のURLへのアクセスを拒否する場合は、以下のように記述します。

RewriteCond %{REQUEST_URI} ^.*/admin.*$ [NC]
RewriteRule ^.*$ - [F,L]

IPアドレス 12.12.12.12 のみ /admin のURLへのアクセスを許可する場合は、以下のように記述します。 このように設定することで特定の場所からのみ管理画面へのアクセスを許可することが可能です。

RewriteCond %{REQUEST_URI} ^.*/admin.*$ [NC]
RewriteCond %{REMOTE_ADDR} !^12.12.12.12$
RewriteRule ^.*$ - [F,L]

特定の文字列を含むユーザエージェントのアクセスを拒否、もしくは許可

ユーザエージェンに特定の文字列(spider, bot, python いずれかの文字列)を含む場合のみアクセスを拒否する場合は、以下のように記述します。これによってシェルやボットによる無差別なアクセスを拒否することが可能です。

RewriteCond %{HTTP_USER_AGENT} ^.*(spider|bot|python).*$ [NC]
RewriteRule ^.*$ - [F,L]

特定のリファラーからのアクセスを拒否、もしくは許可

リファラーに特定の文字列( aaa, bbb のいずれかの文字列)を含む場合のみアクセスを拒否する場合は、以下のように記述します。

RewriteCond %{HTTP_REFERER} ^.*(aaa|bbb).*$ [NC,OR]
RewriteRule ^.*$ - [F,L]

特定の文字列を含むクッキーがある場合のみアクセスを拒否、もしくは許可

ユーザのブラウザに特定の文字列(SESSION_ID)を含むクッキーが存在する場合のみアクセスを許可する場合は、以下のように記述します。これによってログインしていないユーザは、特定のディレクトリのファイルへのアクセスを拒否するといったことが可能です。

RewriteCond %{HTTP_COOKIE} ^.*(SESSION_ID).*$ [NC]
RewriteRule ^.*$ - [F,L]

特定の言語のブラウザのみアクセスを拒否、もしくは許可

例えば日本語、英語のブラウザのみアクセスを許可する場合は、以下のように記述します。

RewriteCond %{HTTP:Accept-Language} !^(ja|en).*$ [NC]
RewriteRule ^.*$ - [F,L]

逆にロシア語のブラウザのアクセスを拒否する場合は、以下のように記述します。

RewriteCond %{HTTP:Accept-Language} ^(ru).*$ [NC]
RewriteRule ^.*$ - [F,L]

特定のクエリ文字列を含むアクセスを拒否、もしくは許可

クエリ文字列に特定の文字列(select, update, insert)を含む場合のみアクセスを拒否する場合は、以下のように記述します。これによってSQLインジェクションの一部や悪意のあるアクセスの一部を拒否することが可能かもしれません。

RewriteCond %{QUERY_STRING} ^.*(select|update|insert).*$ [NC]
RewriteRule ^.*$ - [F,L]

特定のリクエストメソッドを拒否、もしくは許可

例えば GET、POST 以外のアクセスを全て拒否する場合は、以下のように記述します。

RewriteCond %{REQUEST_METHOD} !^.*(GET|POST).*$ [NC]
RewriteRule ^.*$ - [F,L]

特定の日時、時間帯のみアクセスを拒否、もしくは許可

例えば2022年1月1日以降のアクセスを全て拒否する場合、以下のように記述します。

RewriteCond %{TIME} >20220101000000
RewriteRule ^.*$ - [F,L]

このように事前に外部からアクセスするディレクトリやスクリプトファイル、ブラウザの言語を限定し、特定のユーザエージェント、リファラー、クエリ文字列、リクエストメソッドを拒否することで、Webアプリケーションやプラグインの脆弱性を狙った無差別な攻撃もかなりの割合でブロックできるのではないかと思います。実際、試験的に運用中の Web サイトに適用し、アクセスログを観察したところ、1日数百件近くあった機械的な不正アクセスが数件程度に減少しました。

関連記事:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください