Emojibook

IPv4アドレスとポート番号、そしてサーバのファイル一式が与えられた。
指定のアドレスとポート番号をFirefoxのアドレスバーに入れてアクセスすると、 ログインしてノートを投稿できるサービスが動いていた。

投稿したノートは、まずnotes/forms.pyで以下の処理などをされる。

A pair of an IPv4 address and a port number, and the files on ther server were given.
Accessing to the site by putting the address and the port number to the address bar of Firefox, a service on which we can log in and submit notes was running.

Submitted notes are firstly processed with this code in notes/forms.py:

instance.body = instance.body.replace("{{", "").replace("}}", "").replace("..", "")

その後、notes/views.pyで以下の処理をされる。

After that, it is processed in notes/views.py with this code:

for include in re.findall("({{.*?}})", text): print(include) file_name = os.path.join("emoji", re.sub("[{}]", "", include)) with open(file_name, "rb") as file: text = text.replace(include, f"<img src=\"data:image/png;base64,{base64.b64encode(file.read()).decode('latin1')}\" width=\"25\" height=\"25\" />")

すなわち、以下の順で処理が行われる。

  1. {{を削除する
  2. }}を削除する
  3. ..を削除する
  4. {{}}で囲まれた部分から{}を削除したものをファイル名として読み込み、内容をBase64エンコードして埋め込む

{{}}を削除した後に..を削除するので、 {..{/flag.txt}..}を投稿すると{{/flag.txt}}となり、/flag.txtの内容が埋め込まれる。
/flag.txtの内容はflagだった。

In other words, notes are processed in this order:

  1. Remove {{
  2. Remove }}
  3. Remove ..
  4. Remove { and } from what is surrounded by {{ and }}, read a file whose name is the result, and put the contents of the file with Base64-encoding.

Since .. is removed after removing {{ and }}, {..{/flag.txt}..} becomes {{/flag.txt}} and the contents of /flag.txt is embed.
The contents of /flag.txt was the flag.

ractf{dj4ng0_lfi}

RACTF 2021