- 2010-04-03 土 01:16:36
- PHP
PHPプログラミングを扱ってるからでしょうが
毎日なにかしらの攻撃的なリクエストがあります。
特定のURLに誘導するものとか、サーバーのコマンドを実行するものとか
SQLインジェクションとか、アプリケーションの脆弱性をつくものとか・・・
まあ、アクセスログにはいろいろと記録されてます。
攻撃者が、任意のコードやコマンドをうちのサーバーで
なんとか実行させようと試みてるのがみてとれます。
うちのサイトでこのようなリクエストは全部 Error404 ってことになり、
レスポンスにボディーは無し、コマンドも実行されることもありません。
今日は攻撃的なリクエストのフィルタリングについて書いてみます。
URLに含まれる文字を検証してるわけですが
出現頻度の高い文字としてはこんなところだろうと思います。
- 演算子や記号
- 制御コード
- URL
- 相対パス
演算子や記号から、URLにあまり使わないものに絞るとこんなところ。
" ' ( ) * , : ; |
さらに、制御コードは正規表現のキャラクタークラスを使うと。
[:cntrl:]
URLはプロトコルの区切りになる連続するスラッシュ2つを。
//
相対パスはドットとスラッシュの組み合わせを。
./
..
これらの文字にURLエンコードを重ねてる場合もあるので
それも加え、正規表現関数で $_SERVER[‘REQUEST_URI’] を
チェックするスクリプトがこれです。
urlFilter.php
<?php $AttackRegx = '/(' .'["\'()*,:;|[:cntrl:]]' .'|\/\/|\.\.|\.\/' .'|%(22|27|28|29|2A|2C|3A|3B|7C|[01][0-9A-F]|7F)' .'|%2F%2F|%2E%2E|%2E%2F' .')/i'; if (preg_match($AttackRegx, $_SERVER['REQUEST_URI'])) { header('HTTP/1.0 404 Not Found'); header('X-Powered-By: AntiAttacker'); exit('So Bad!'); }
攻撃的なリクエストに対して、ご丁寧にエラーページを返す必要も無いので
チェックに引っ掛かった場合、本文無し+強制終了で十分です。
不要なトラフィックも減らせまます。
さて、これをスクリプト毎にincludeしてもいいんですが
auto_prepend_fileで役割分担
の方法でこのスクリプトを読み込めば
個々のPHPスクリプトに手を加えることなく
全てのスクリプトでチェックが行われます。
もちろん個々のPHPスクリプトが使ってるパラメータの
バリデーションは欠かせませんが最小限の検証だけで済みます。
これはうちの場合なので、判定に使う文字は
管理してるサイトにあわせ適切に選び直してください。
PHPの基礎体力は、今のところURLに使う文字を
ドット(.)、アンダーバー(_)、マイナス(-)、スラッシュ(/)、
それと英数字だけに絞ってます。
将来的にマルチバイトを含んだURLも見込んでるのでやってはいませんが
URLエンコードしても変わらない文字だけなので
‘%’ を含んでいるだけでアウトというフィルタリングでもいいわけです。
設計段階でURLに使う文字を絞り込んでおけば
もっと簡単なフィルタリングで、未知の攻撃も防げるかもしれません。
じっくりアクセスログを見てみると新たな発見があるもんです。
- 新しい: spamp:掲示板スパムバリデータ出来ました
- 古い: 掲示板スパムを5秒でノックアウト