簡単な質問が1つあります。次のようなクエリを持つサイトがあるとします。
SELECT id, name, message FROM messages WHERE id = $_GET['q']
。
データベース(MySQL)で何かを更新/削除する方法はありますか?これまで、SELECT queryを使用して削除/更新できるインジェクションを見たことがないので、それも可能ですか?
複数のクエリをサポートしない_mysql_query
_を使用している場合、DELETE
/UPDATE
/INSERT
を直接追加することはできませんが、下のデータを変更することはできます。いくつかの状況。たとえば、次の関数があるとします。
_DELIMITER //
CREATE DEFINER=`root`@`localhost` FUNCTION `testP`()
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DELETE FROM test2;
return 1;
END //
_
これで、この関数をSELECT
で呼び出すことができます。SELECT id, name, message FROM messages WHERE id = NULL OR testP()
(_id = NULL
_-常にNULL(FALSE)であるため、testP()は常に実行されます。
質問に直接答える前に、攻撃者ができるのはreadデータであり、攻撃者ができないはずのデータであるとしても、それは通常まだ本当に悪いです。システムテーブル(mysql.innodb_table_stats
など)からJOIN
sとSELECT
ingを使用することにより、攻撃者はSELECT
インジェクションで開始し、他の知識がないことを考慮してください。 databaseは、スキーマをマップしてから、MySQLにあるデータ全体を盗み出すことができます。大多数のデータベースとアプリケーションにとって、そのalreadyは壊滅的なセキュリティホールを表しています。
しかし、質問に直接答えるには、MySQL SELECT
へのインジェクションを使用してデータを変更できる方法がいくつかあります。幸いなことに、それらはすべて、可能であるために合理的に異常な状況を必要とします。以下のすべての注入例は、質問からの注入可能なクエリの例に関連して示されています。
SELECT id, name, message FROM messages WHERE id = $_GET['q']
注入されたステートメントの後に他のステートメント全体を配置するだけの古典的な注入手法。 ここでの別の回答 で提案されているように、クエリが連続して実行される2つのステートメントを形成し、2番目のステートメントがusers
テーブル内のすべてを削除するように、$_GET['q']
を1; DELETE FROM users; --
に設定できます。
ほとんどのMySQLコネクタ(特にPHPの(非推奨)mysql_*
関数と(非推奨)mysqli_*
関数を含む)は、スタッククエリまたはバッチクエリをまったくサポートしていないため、この種の攻撃は単純に機能しません。ただし、一部のdo-特にPHPのPDOコネクタが含まれています(ただし、サポート セキュリティを強化するために無効にすることができます )。
関数はSELECT
から呼び出すことができ、データを変更できます。データベースにデータ変更関数が作成されている場合は、たとえば0 OR SOME_FUNCTION_NAME()
を$_GET['q']
の値として渡すことにより、SELECT
に呼び出すことができます。
ほとんどのデータベースには、データを変更する関数はもちろんのこと、ユーザー定義関数が含まれていないため、この種のエクスプロイトを実行する機会はまったくありません。
Muhaimin Dzulfakarの(やや推測の名前が付けられた)論文 Advanced MySQL Exploitation で説明されているように、MySQLselectでINTO OUTFILE
またはINTO DUMPFILE
句を使用して結果をファイルにダンプできます。 UNION
を使用すると、任意の結果をSELECT
edできるため、mysqld
を実行しているユーザーがアクセスできる任意の場所に任意のコンテンツを含む新しいファイルを書き込むことができます。おそらく、これは、MySQLデータベースのデータを変更するだけでなく、それが実行されているサーバーへのシェルアクセスを取得するために悪用される可能性があります。たとえば、PHPスクリプトをWebルートに記述し、次に、MySQLサーバーがPHPサーバーと共同ホストされている場合は、要求を行います。
多くの要因が、この印象的なサウンドの攻撃の実際的な悪用可能性を低下させます。
INTO OUTFILE
またはINTO DUMPFILE
を使用して既存のファイルを上書きしたり、存在しないフォルダーに書き込んだりすることはできません。これにより、mysql
ユーザーのホームディレクトリに秘密鍵を使用して.ssh
フォルダーを作成し、SSHで接続したり、mysqld
バイナリ自体を悪意のあるバージョンで上書きしてサーバーの再起動を待機したりするなどの攻撃を防ぎます。mysql
を実行する特別なユーザー(通常はmysqld
という名前)を設定し、そのユーザーに非常に限られた権限のみを付与します。そのため、ファイルシステム上のほとんどの場所に書き込むことができないはずです。また、通常、WebアプリケーションのWebルートに書き込むようなこともできないはずです。--secure-file-priv
が設定されており、MySQLが指定されたデータのインポート/エクスポートディレクトリ以外の場所に書き込むことを防ぎ、サーバーの所有者でない限り、この攻撃をほぼ完全に無力にします。意図的に無効にしました。幸いなことに、そのようなセキュリティ機能を完全に無効にすることは決してありません。それは明らかに- oh wait never mind だからです。lib_mysqludf_sys
からsys_exec()
関数を呼び出して、任意のシェルコマンドを実行しますlib_mysqludf_sys
と呼ばれるMySQL拡張機能があります。これは-星から判断すると GitHub上 および スタックオーバーフローのクイック検索 -少なくとも数百人のユーザーがいます。シェルコマンドを実行するsys_exec
という関数を追加します。 #2で述べたように、関数はSELECT
内から呼び出すことができます。意味はうまくいけば明白です。 ソース から引用すると、この関数は「セキュリティ上の問題になる可能性があります」。
ほとんどのシステムには、この拡張機能がインストールされていません。
使用しているDBMSコネクタによって異なります。ほとんどの場合、シナリオは不可能であるはずですが、特定の状況下では機能する可能性があります。詳細については、 Blackhat-Paper Advanced MySQL Exploitation の第4章と第5章を参照してください。