web-dev-qa-db-ja.com

MySQLインジェクション-SELECTクエリを使用して更新/削除します

簡単な質問が1つあります。次のようなクエリを持つサイトがあるとします。

SELECT id, name, message FROM messages WHERE id = $_GET['q']

データベース(MySQL)で何かを更新/削除する方法はありますか?これまで、SELECT queryを使用して削除/更新できるインジェクションを見たことがないので、それも可能ですか?

11
Simon

複数のクエリをサポートしない_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()は常に実行されます。

6
a1ex07

質問に直接答える前に、攻撃者ができるのはreadデータであり、攻撃者ができないはずのデータであるとしても、それは通常まだ本当に悪いです。システムテーブル(mysql.innodb_table_statsなど)からJOINsとSELECTingを使用することにより、攻撃者はSELECTインジェクションで開始し、他の知識がないことを考慮してください。 databaseは、スキーマをマップしてから、MySQLにあるデータ全体を盗み出すことができます。大多数のデータベースとアプリケーションにとって、そのalreadyは壊滅的なセキュリティホールを表しています。

しかし、質問に直接答えるには、MySQL SELECTへのインジェクションを使用してデータを変更できる方法がいくつかあります。幸いなことに、それらはすべて、可能であるために合理的に異常な状況を必要とします。以下のすべての注入例は、質問からの注入可能なクエリの例に関連して示されています。

SELECT id, name, message FROM messages WHERE id = $_GET['q']

1.「スタック」または「バッチ」クエリ。

注入されたステートメントの後に他のステートメント全体を配置するだけの古典的な注入手法。 ここでの別の回答 で提案されているように、クエリが連続して実行される2つのステートメントを形成し、2番目のステートメントがusersテーブル内のすべてを削除するように、$_GET['q']1; DELETE FROM users; --に設定できます。

緩和策として

ほとんどのMySQLコネクタ(特にPHPの(非推奨)mysql_*関数と(非推奨)mysqli_*関数を含む)は、スタッククエリまたはバッチクエリをまったくサポートしていないため、この種の攻撃は単純に機能しません。ただし、一部のdo-特にPHPのPDOコネクタが含まれています(ただし、サポート セキュリティを強化するために無効にすることができます )。

2.ユーザー定義関数の活用

関数はSELECTから呼び出すことができ、データを変更できます。データベースにデータ変更関数が作成されている場合は、たとえば0 OR SOME_FUNCTION_NAME()$_GET['q']の値として渡すことにより、SELECTに呼び出すことができます。

緩和策として

ほとんどのデータベースには、データを変更する関数はもちろんのこと、ユーザー定義関数が含まれていないため、この種のエクスプロイトを実行する機会はまったくありません。

3.ファイルへの書き込み

Muhaimin Dzulfakarの(やや推測の名前が付けられた)論文 Advanced MySQL Exploitation で説明されているように、MySQLselectでINTO OUTFILEまたはINTO DUMPFILE句を使用して結果をファイルにダンプできます。 UNIONを使用すると、任意の結果をSELECTedできるため、mysqldを実行しているユーザーがアクセスできる任意の場所に任意のコンテンツを含む新しいファイルを書き込むことができます。おそらく、これは、MySQLデータベースのデータを変更するだけでなく、それが実行されているサーバーへのシェルアクセスを取得するために悪用される可能性があります。たとえば、PHPスクリプトをWebルートに記述し、次に、MySQLサーバーがPHPサーバーと共同ホストされている場合は、要求を行います。

緩和策として

多くの要因が、この印象的なサウンドの攻撃の実際的な悪用可能性を低下させます。

  • MySQLは決してINTO OUTFILEまたはINTO DUMPFILEを使用して既存のファイルを上書きしたり、存在しないフォルダーに書き込んだりすることはできません。これにより、mysqlユーザーのホームディレクトリに秘密鍵を使用して.sshフォルダーを作成し、SSHで接続したり、mysqldバイナリ自体を悪意のあるバージョンで上書きしてサーバーの再起動を待機したりするなどの攻撃を防ぎます。
  • 中途半端なインストールパッケージは、mysqlを実行する特別なユーザー(通常はmysqldという名前)を設定し、そのユーザーに非常に限られた権限のみを付与します。そのため、ファイルシステム上のほとんどの場所に書き込むことができないはずです。また、通常、WebアプリケーションのWebルートに書き込むようなこともできないはずです。
  • MySQLの最新のインストールには、デフォルトで --secure-file-priv が設定されており、MySQLが指定されたデータのインポート/エクスポートディレクトリ以外の場所に書き込むことを防ぎ、サーバーの所有者でない限り、この攻撃をほぼ完全に無力にします。意図的に無効にしました。幸いなことに、そのようなセキュリティ機能を完全に無効にすることは決してありません。それは明らかに- oh wait never mind だからです。

4 .lib_mysqludf_sysからsys_exec()関数を呼び出して、任意のシェルコマンドを実行します

lib_mysqludf_sysと呼ばれるMySQL拡張機能があります。これは-星から判断すると GitHub上 および スタックオーバーフローのクイック検索 -少なくとも数百人のユーザーがいます。シェルコマンドを実行するsys_execという関数を追加します。 #2で述べたように、関数はSELECT内から呼び出すことができます。意味はうまくいけば明白です。 ソース から引用すると、この関数は「セキュリティ上の問題になる可能性があります」

緩和策として

ほとんどのシステムには、この拡張機能がインストールされていません。

6
Mark Amery

使用しているDBMSコネクタによって異なります。ほとんどの場合、シナリオは不可能であるはずですが、特定の状況下では機能する可能性があります。詳細については、 Blackhat-Paper Advanced MySQL Exploitation の第4章と第5章を参照してください。

2
Demento