基本的なXPathインジェクション
まず前回で作成したauth.
[yohgaki@dev tmp]$ php auth.php user1 password1 OK to login [yohgaki@dev tmp]$ php auth.php user1 password2 Not OK to login
auth.
$nodelist = $xpath->query('/account/user[name="'.$argv[1].'" and password="'.$argv[2].'"]');
注意:このクエリは省略形です。name/
このXPathクエリには必要なエスケープ処理を怠る致命的な欠陥があるので、
" or 1=1 or ""="
をパラメータとして与えると、
[yohgaki@dev tmp]$ php auth.php '" or 1=1 or ""="' password2 OK to login
これは不正なパラメータによりXPathクエリの意味が変わってしまったために発生する問題です。
/account/user[name="" or 1=1 or ""="" and password="password2"]
プログラマが意図しない形で文字列を終了させクエリの意味を変えてしまう、
ブラインドXPathインジェクション
ブラインドSQLインジェクションとは、
先ほどのXPathインジェクションの例では、
詳しいブランドXPathインジェクションの解説は長くなるので省略します。英文ですが非常にわかりやすい文書が公開されているので、
- Watchfire : Blind XPath Injection
- https://
secureitalliance. org/ blogs/ watchfire/ archive/ 2006/ 02/ 10/ 660. aspx
XPathインジェクション対策
XPathインジェクション対策もSQLインジェクション対策と同じです。XPathのリテラルはSQLと同様に文字リテラルと数値リテラルに大別できます。
[42] Literal ::= NumericLiteral | StringLiteral
[43] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral
[71] IntegerLiteral ::= Digits
[72] DecimalLiteral ::= ("." Digits) | (Digits "." [0-9]*)
[73] DoubleLiteral ::= (("." Digits) | (Digits ("." [0-9]*)?)) [eE] [+-]? Digits
[74] StringLiteral ::= ('"' (EscapeQuot | [^"])* '"') | ("'" (EscapeApos | [^'])* "'")
[75] EscapeQuot ::= '""'
[76] EscapeApos ::= "''"
[81] Digits ::= [0-9]+
この定義から、
"文字列"
または
'文字列'
と定義され、
つまり、
mb_regex_encoding('UTF-8');
$escaped = mb_ereg_replace('\'', '\'\'', $input);
XPath実装によりますが、
PHPのXPath
"10.0" = 5*2
注意:浮動小数点の演算には誤差がつきものなので、
は等価と評価されます。
XML文書自体がテキスト形式なので当然です。数値リテラルの場合、
前々回で紹介したPostgreSQL 8.
$escaped = pg_escape_string($connection, $input);
ただし、
MySQL 5.
まとめ
XPathインジェクションはSQLインジェクションと似たような攻撃手法であり、
SQLインジェクション対策には便利なプリペアードクエリも利用可能ですが、
XPathインジェクション対策はSQLインジェクション対策と同様、