「個人情報漏えいを防ぎたい・・・」
「SQLインジェクション対策を簡単に実施したい・・・」
このような場合には、この記事の内容が参考になります。
この記事では、無料WAFによるSQLインジェクション対策の方法を解説しています。
本記事の内容
- WAFによるSQLインジェクション対策
- SQLインジェクション対策(初級)の検証
それでは、上記に沿って解説していきます。
WAFによるSQLインジェクション対策
SQLインジェクションへの対策には、様々な方法があります。
この記事では、手っ取り早く対策する方法としてWAFを用います。
WAFを利用すれば、PHPやJavaなどのコードを修正する必要はありません。
その意味で言えば、非常に簡単で早く打てる対策と言えます。
しかし、WAFは有償であることが基本です。
それだけ需要があるということなのでしょう。
お金を払ってでも、WAFを導入したいということです。
クラウド型であれば、比較的容易に導入することもできますからね。
では、そんな余裕のない企業・個人はどうすればよいのでしょうか?
無料で使えるオープンソースのWAFを利用しましょう。
ModSecurityをインストールすれば、SQLインジェクション対策になります。
しかし、どのレベルまで対策できるのか不明です。
攻撃にもレベルがありますからね。
そこで、実際にどのレベルまでの攻撃を防げるのかを検証しましょう。
そのためには、SQLインジェクションを実行できる環境が必要です。
つまり、脆弱性を持ったWebアプリケーションが必要になります。
そのような場合には、DVWAが役に立ちます。
DVWAのインストールについては、次の記事で説明しています。
DVWAとModSecurityは、同じサーバーにインストールすることになります。
ここまで準備ができれば、SQLインジェクション対策(初級)の検証が可能です。
以上、WAFによるSQLインジェクション対策を説明しました。
次は、SQLインジェクション対策(初級)の検証を説明します。
SQLインジェクション対策(初級)の検証
SQLインジェクション対策(初級)の検証は、次の項目に分けて説明します。
- セキュリティレベルの変更(low)
- SQLインジェクション(初級)による攻撃
- ModSecurityによるSQLインジェクション(初級)の防御
セキュリティレベルの変更(low)
DVWAにログインして、「DVWA Security」メニューへ移動します。
DVWAのセキュリティレベルを設定する画面です。
「Low」を選んで、「Submit」ボタンをクリック。
処理が成功すると、画面下部の情報が変更されます。
SQLインジェクション(初級)による攻撃
メニューから「SQL Injection」をクリック。
この画面の機能としては、ID入力によるユーザー照会です。
この機能に対して、SQLインジェクションを実行します。
攻撃を行う前に、脆弱性を含んだプログラム(PHP)を確認します。
画面下部にある「View Source」ボタンをクリック。
別ウィンドウで対象プログラムのソースを確認できます。
vulnerabilities/sqli/source/low.php
<?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } mysqli_close($GLOBALS["___mysqli_ston"]); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } } else { echo "Error in fetch ".$sqlite_db->lastErrorMsg(); } break; } } ?>
このコードに攻撃を与えます。
次の値を入力して、「Submit」ボタンをクリックするだけです。
1' OR ""='
ModSecurityでSQLインジェクション対策をしていない場合は、次のような結果となります。
このようにして、個人情報漏えいの事件が発生しているわけです。
ModSecurityによるSQLインジェクション(初級)の防御
ModSecurityで対策していれば、上記のような悲劇は生まれません。
攻撃すると、403ページに飛ばされます。
異なる結果になる場合は、ModSecurityの設定ファイルを確認しましょう。
/etc/modsecurity/modsecurity.conf
「SecRuleEngine」が、「On」であることを確認してください。
「DetectionOnly」だと攻撃を認識するだけで403ページには飛ばしません。
つまり、防御しません。
攻撃を防御した際には、エラーログに次のようなログが残ります。
/var/log/apache2/error.log
[Sat Jul 02 13:20:42.926134 2022] [:error] [pid 93855] [client 192.168.33.1:61261] [client 192.168.33.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/etc/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "184"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 8)"] [ver "OWASP_CRS/4.0.0-rc1"] [tag "anomaly-evaluation"] [hostname "192.168.33.200"] [uri "/DVWA/vulnerabilities/sqli/"] [unique_id "Yr_HmuQyisuvMdspq4pyWQAAAAQ"], referer: http://192.168.33.200/DVWA/vulnerabilities/sqli/
「ModSecurity: Access denied with code 403 (phase 2)」
アクセスを拒否したことが、ログからわかります。
以上、SQLインジェクション対策(初級)の検証を説明しました。