最近アプリのペネトレーションテストをOWASP ZAPで行っているのですが、
意図しないところでSQLインジェクションの脆弱性警告が出たり出なかったりと変な動きをしていました。
データ更新フォームでの検査で発生
データを更新するフォームに対して行った検査で検出されたのですが、
はて、更新処理も何もJPAで行っているのでSQLインジェクションなど起きそうにはないのですが…
気になったので、zap-extensionsのTestSQLInjection.javaを見てみました。
引っかかったのはAND 1 = 1などの付加
check 2にてboolean baseのチェックを行っています。検索条件に「AND 1 = 1」などの文字列を加えて、それが検索条件に影響するかを調べています。
見るべきところは764行目。
String resBodyANDFalseUnstripped = msg2_and_false.getResponseBody().toString(); String resBodyANDFalseStripped = this.stripOff(resBodyANDFalseUnstripped, sqlBooleanAndFalseValue); String andFalseBodyOutput[] = {resBodyANDFalseUnstripped, resBodyANDFalseStripped}; //which AND False output should we compare? the stripped or the unstripped version? //depends on which one we used to get to here.. use the same as that.. // build an always false AND query. Result should be different to prove the SQL works. if (andFalseBodyOutput[booleanStrippedUnstrippedIndex].compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) { if (this.debugEnabled) { log.debug("Check 2, " + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED") + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue + "] differed from (refreshed) original results for " + refreshedmessage.getRequestHeader().getURI()); }
AND 1 = 1を付与して実行した際のレスポンスが付与しなかった際のレスポンスと同一ではなかった場合エラーとしています。
更新処理後のレスポンス自体が変化すると…
これを更新処理に実行しているのですが、今回検査したアプリでは処理実行後のレスポンスには更新後のデータが含まれています。
例えば名前を「太郎」に更新した場合、更新後のレスポンスは「太郎 AND 1 = 2」のように文字列が付与された状態で表示されています。
比較の際には付与された文字を削除してから比較しているので、付与している場合、していない場合で結果はおなじになるはず、と想定していいるようです。
しかし、更新後に表示するデータには他にもいくつかあって、その中でも問題になるのが「更新日時」です。
これは更新するごとにデータを現在時刻で書き換えておき、最終更新時間を把握しておくための項目です。
これが存在するため、付与ありの更新が付与なしのものから1秒でも遅れてしまうとレスポンスが変わってしまうのです。
正常な更新作業でもレスポンスが変わってしまうのですから、これがSQLインジェクションによるものかどうなのかはOWASP ZAPには判断がつかず、
とりあえず脆弱性ありと表示せざるを得なくなっているのです。
検出された部分は目検
Scan Policyをいじればなんとかなるのかもしれませんが、見たところそれほど高度に設定できるようでもありませんし、
検出されないようにいじると今度は本当の脆弱性が見つからなくなる可能性も出てきてしまうのでいじりたくはありません。
結局機械が自動でやっていることなので、この結果を確認するところくらいは人間の目で行ってやりましょう。
何かいい回避策があれば教えていただけると嬉しいです。
コメント