誰の為の記事か
僕の備忘録としての記事ですw
一応4月から新入社員としてセキュリティの業務に関わっていくのでこれまで避けていたCTFを流石に「解いた事ないんですよテへへ//」じゃカッコ悪いので入門してみました。
選んだ問題について
よく分かりませんが今回はWebの問題で、なんとなく面白そうなものを選んで解いていきました。
解いた問題
[Cookie]
問題文↓
workspace↓
とりあえずデフォルトで設定されているsnickerdoodleを入力して送信しました。
結果↓
送信は成功したみたいです。
cookieの問題なので取りあえずChromeの拡張機能であるEditThisCookieでcookieを見てみることに...↓
試しに1に変えて更新してみました。↓
変化ありましたね。
当然ではありますがcookieによってサーバは返すデータを変えているみたいです。
おそらくこの問題の解法は、valueの値を変えていく事でflagを表示させるのだと思います。
メンドウですがどんどん値を変えていきます↓
18度目の正直です(笑)
flagはgetしました。
後はflagを送信して終了です。
このトレーニング問題の意図としては、案にcookieの情報だけでデータを返すような造りをするとクライアント側でcookieを意図的に変えるだけで,特定のユーザの情報にアクセスできてしまうという事だと思います。
[login]
問題文↓
workspace↓
ログイン系の問題だからソースコードに開発時にテストユーザのログイン情報でもコメントアウトして残してるんじゃないかと思ったので開発者モードでソースコードを覗いてみました。
ソースコード index.html(原文)↓
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
<script src="index.js"></script>
</head>
<body>
<div>
<h1>Login</h1>
<form method="POST">
<label for="username">Username</label>
<input name="username" type="text"/>
<label for="username">Password</label>
<input name="password" type="password"/>
<input type="submit" value="Submit"/>
</form>
</div>
</body>
</html>
htmlには何もないので、外部ファイルのindex.jsを読んでみる事に
ソースコード index.js(原文)↓
(async()=>{await new Promise((e=>window.addEventListener("load",e))),document.querySelector("form").addEventListener("submit",(e=>{e.preventDefault();const r={u:"input[name=username]",p:"input[name=password]"},t={};for(const e in r)t[e]=btoa(document.querySelector(r[e]).value).replace(/=/g,"");return"YWRtaW4"!==t.u?alert("Incorrect Username"):"cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ"!==t.p?alert("Incorrect Password"):void alert(`Correct Password! Your flag is ${atob(t.p)}.`)}))})();
コンパイルされて超見ずらいので、整形しました。
ソースコード index.js(整形後)↓
(async () => {
await new Promise((e => window.addEventListener("load", e))),
document.querySelector("form").addEventListener("submit", (
e => { e.preventDefault();
const r = { u: "input[name=username]", p: "input[name=password]" }, t = {};
for (const e in r) t[e] = btoa(document.querySelector(r[e]).value).replace(/=/g, "");
return "YWRtaW4" !== t.u ? alert("Incorrect Username") : "cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ" !== t.p ? alert("Incorrect Password") : void alert(`Correct Password! Your flag is ${atob(t.p)}.`)
}
))
})
();
あんまり綺麗じゃないですが、これで読めるようになりましたw
ざっと読んだ感じreturnで判定して想定した値じゃなかったらalertが出るみたいです。
alertを出してみた↓
もう少し詳しく読んでみるとbtoaという関数に通して本来のユーザ名とパスワードを変えているみたいです。なのでbtoaの逆関数的なモノに通せばおそらくログイン情報が手に入ります。
btoaとは↓
バイナリーデータの「文字列」から base64 で符号化された ASCII 文字列を生成します ("btoa" は >"binary to ASCII" と読んでください)。
base64でエンコードする為の関数みたいです。なのでbase64でデコードすればいいですね。
base64でデコード↓
今回はこのエンコード・デコード便利サイトを使って楽をしましたw
デコード結果↓
ユーザ名:admin
パスワード:picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r}
後はこれを入力するだけです。
結果↓
いけましたね。
終わりに
意外とCTF面白いなと感じました。
また暇を見つけて解いたらチョコチョコ更新していきます。
それでは、バイチャ!