SQLインジェクションを回避するために準備されたステートメントなどが必要であることは知っています。SELECT、INSERT、UPDATEの注入可能なクエリの悪用についてはさまざまな質問があることを確認しました。
しかし、USE
ステートメントのエクスプロイトサンプルを思いつくことはできませんでした。次のような挿入可能な単一のステートメントがあるとします。
USE `data_from_attacker`;
攻撃者がdata_from_attacker
の代わりに何かを置くことができる場合、攻撃者はどのデータを使用できますか。私は単にDBを選択していないエクスプロイトの例を探しています(つまり、information_schemaまたはmysql DBを選択しても害がないようです。テーブルが存在しないため、次のクエリは機能しません。また、存在しないDBを選択しても問題はありません)。
また、mysqlは最初のクエリのみを解釈するため、攻撃者が挿入できないことを考慮してください。
mysql`; SELECT * FROM `users
MySQLのそのようなエクスプロイトを見つけることができますか? USE
構文 は、そのような注入では非常に「悪い」ようです...
Xenosの見積もり
MySQLのそのようなエクスプロイトを見つけることができますか? USE構文は、このようなインジェクションには非常に「貧弱」のようです
MySQLでのUSE
の動作と、ソースコード内のMySQLがアクセスする必要があるファイルを追跡します。
_---
**Query #1**
SET PROFILING = 1;
There are no results to be displayed.
---
**Query #2**
USE test;
There are no results to be displayed.
---
**Query #3**
SHOW PROFILES;
| Query_ID | Duration | Query |
| -------- | ---------- | -------- |
| 1 | 0.00006425 | USE test |
---
**Query #4**
SHOW PROFILE ALL FOR QUERY 1;
| Status | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out | Messages_sent | Messages_received | Page_faults_major | Page_faults_minor | Swaps | Source_function | Source_file | Source_line |
| -------------- | -------- | -------- | ---------- | ----------------- | ------------------- | ------------ | ------------- | ------------- | ----------------- | ----------------- | ----------------- | ----- | --------------------- | ------------ | ----------- |
| starting | 0.000038 | 0.000019 | 0.000012 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | |
| query end | 0.000003 | 0.000002 | 0.000001 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_execute_command | sql_parse.cc | 4310 |
| closing tables | 0.000003 | 0.000001 | 0.000001 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_execute_command | sql_parse.cc | 4356 |
| freeing items | 0.000009 | 0.000006 | 0.000003 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_parse | sql_parse.cc | 4968 |
| cleaning up | 0.000012 | 0.000007 | 0.000005 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | dispatch_command | sql_parse.cc | 1978 |
---
_
参照 デモ
MySQL基本レクサーはyaccで動作するため、最初にファイル sql_yacc.yy を確認します。
以下はUSE
キーワードが定義されています。
_/* change database */
use:
USE_SYM ident
{
Lex *Lex=Lex;
Lex->sql_command=SQLCOM_CHANGE_DB;
Lex->select_Lex->db= $2.str;
}
;
_
sql_parse.cc をチェックすると、関数mysql_execute_command()
内で
_case SQLCOM_CHANGE_DB: {
const Lex_CSTRING db_str = {select_Lex->db, strlen(select_Lex->db)};
if (!mysql_change_db(thd, db_str, false)) my_ok(thd);
break;
}
_
質問に答える。
いいえ、ソースコードで_<database>
_ステートメントの_USE <database>
_部分が「文字列」を期待し、さらにSQLステートメント。
文字列を使用すると、_USE database_name
_の形式またはバックティックを使用したdatabase_nameを意味します。
データベースのスキーマの要素のいずれかに、SQLエンジン上の他のデータベースと共通の名前がある場合、クエリをクロスして望ましくない結果を生成する可能性があります。
想定されるデータベースの名前は「PROD _DB」ですが、開発者は同じSQLサーバー上に「TEST_DB」という名前の別のデータベースを持っているとします。彼らはアプリのテストにテストデータベースを使用するため、スキーマは同じですが、テストにのみ使用され、誰も気にしないジャンクデータで満たされています。 UserName == 'test1'、PassWord == 'abc'、AdminFlag == 1.のようなもの。USEステートメントを意のままにPROD_DBからTEST_DBに変更し、再度戻すことにより、 'test1'資格情報を使用して認証し、ステータスを設定できます。管理者に戻り、管理者ステータスを使用して、本番アプリケーション内で必要なことをすべて実行します。