経験を要約します。私の考えでは、SQL インジェクション攻撃の主な原因は次の 2 つの理由です:
1. PHP 設定ファイル php.ini の magic_quotes_gpc オプションがオンになっておらず、オフに設定されている
2. 開発者がデータを設定していないtype 検査とエスケープ
しかし、実際には 2 番目の点が最も重要です。ユーザーが入力したデータ型をチェックし、正しいデータ型を MYSQL に送信することは、Web プログラマーの最も基本的な資質であるべきだと思います。しかし実際には、多くの初心者 Web 開発者はこれを忘れて、バックドアが大きく開いたままになっていることがよくあります。
なぜ2番目の点が最も重要なのでしょうか? 2 番目の保証がないと、magic_quotes_gpc オプションがオンかオフかに関係なく、SQL インジェクション攻撃を引き起こす可能性があるためです。技術的な実装を見てみましょう:
1. magic_quotes_gpc = Off の場合のインジェクション攻撃
magic_quotes_gpc = Off は、php の非常に安全でないオプションです。新しいバージョンの PHP では、デフォルト値が On に変更されました。しかし、オプションがオフになっているサーバーがまだかなりの数あります。結局のところ、サーバーがどんなに古いものであっても、まだそれを使用している人がいます。
magic_quotes_gpc = On の場合、送信された変数の前にあるすべての '(一重引用符)、"(二重記号)、(バックスラッシュ)、空白文字が自動的に追加されます。 以下は PHP 公式の説明です:
Copy code コードは次のとおりです:
magic_quotes_gpc boolean
magic_quotes がオンの場合、すべての ' (一重引用符)、" (二重引用符)、 (バックスラッシュ) と NUL はバックスラッシュで自動的にエスケープされます
エスケープがない場合、つまりオフの場合、攻撃者に機会を与えてしまいます。次のテスト スクリプトを例に挙げます:
コードをコピーします コードは次のとおりです:
if ( isset($_POST["f_login"] ) )
{
// Connectデータベースへ...
/ /...コードは省略されています...
// ユーザーが存在するかどうかを確認します
$t_strUname = $_POST["f_uname"];
$t_strPwd = $_POST["f_pwd" ];
$t_strSQL = "SELECT * FROM tbl_users WHERE ユーザー名='$t_strUname' AND パスワード = '$t_strPwd' LIMIT 0,1";
if ( $t_hRes = mysql_query($t_strSQL) )
{
// 処理中クエリが成功した後...
}
?>
サンプルテスト
コードは次のとおりです:
SELECT * FROM tbl_users WHERE username= 'zhang3' AND パスワード = 'abc123' LIMIT 0,1
If 攻撃者がユーザー名フィールドに zhang3' OR 1=1 # を入力し、パスワード フィールドに abc123 を入力すると、送信される SQL ステートメントは次のようになります:
コードをコピー
コードは次のとおりです:
SELECT * FROM tbl_users WHERE username='zhang3' OR 1=1 #' AND Password = 'abc123' LIMIT 0,1
#はコメントなのでmysql の # 以降のステートメントは実行されません。この行のステートメントを実装するには、次のようになります。
コードをコピーします
コードは次のとおりです:
SELECT * FROM tbl_users WHERE username=' zhang3' OR 1=1
こうすることで攻撃者は認証を回避できます。攻撃者がデータベース構造を知っている場合、UNION SELECT を構築しますが、これはさらに危険です:
ユーザー名を入力するとします: zhang3 ' OR 1 =1 UNION select cola,colb,cold FROM tbl_b #
パスワードを入力: abc123,
送信された SQL ステートメントは次のようになります:
Copy code
コードは次のとおりです:
SELECT * FROM tbl_users WHERE username='zhang3 ' OR 1 =1 UNION select cola,colb,cold FROM tbl_b #' AND password = 'abc123' LIMIT 0,1
これはかなり危険です。 agic_quotes_gpc オプションがオンで引用符がエスケープされている場合、上記の攻撃者が作成した攻撃ステートメントは次のようになり、その目的を達成できません:
コードをコピーします コードは次のとおりです:
SELECT * FROM tbl_users
WHERE username='zhang3' OR 1=1 #'
AND password = 'abc123'
LIMIT 0,1
SELECT * FROM tbl_users
WHERE username='zhang3 ' OR 1 =1 UNION コーラを選択、 Colb,cold FROM tbl_b #'
AND パスワード = 'abc123' LIMIT 0,1
2. magic_quotes_gpc = On の場合のインジェクション攻撃
magic_quotes_gpc = On の場合、攻撃者は文字フィールドに対して SQL インジェクションを実行できません。だからといって安全というわけではありません。現時点では、SQL インジェクションは数値フィールドを通じて実行できます。
最新バージョンのMYSQL 5.xでは、データ型の入力が厳格化され、自動型変換がデフォルトでオフになっています。数値フィールドを引用符でマークされた文字タイプにすることはできません。つまり、以前の mysql バージョンでは、uid が数値であると仮定すると、このようなステートメントは正当です:
コードをコピー コードは次のとおりです:
INSERT INTO tbl_user SET uid="1";
SELECT * FROM tbl_user WHERE uid="1";
最新の MYSQL 5.x では、上記のステートメントは次のように記述する必要があります:
コードをコピー コードは次のとおりです:
INSERT INTO tbl_user SET uid=1;
SELECT * FROM tbl_user WHERE uid=1;
これは正しいと思います。開発者として、ルールに準拠した正しいデータ型をデータベースに送信することが最も基本的な要件だからです。
では、magic_quotes_gpc = Onの場合、攻撃者はどのように攻撃するのでしょうか?非常に簡単で、数値フィールドに対して SQL インジェクションを実行するだけです。次の php スクリプトを例に挙げます:
コードをコピーします コードは次のとおりです:
if ( isset($_POST["f_login"] ) )
{
// Connectデータベースへ...
// ...コードは省略されています...
// ユーザーが存在するかどうかを確認します
$t_strUid = $_POST["f_uid"];
$t_strPwd = $_POST["f_pwd" ];
$t_strSQL = "SELECT * FROM tbl_users WHERE uid=$t_strUid AND パスワード = '$t_strPwd' LIMIT 0,1";
if ( $t_hRes = mysql_query($t_strSQL) )
{
// クエリ成功後の処理省略しました...
}
}
サンプルテスト