Curly fries

TCPサーバの接続情報と、サーバのファイル一式が与えられた。
与えられたファイルのうち app.c を読むと、以下の処理をしていることが読み取れた。

  1. URLの入力を受け付ける。
  2. mallocで1024バイトの領域を確保する。
  3. 確保した領域に./flag.txtの内容を読み込む。
  4. 確保した領域を開放する。
  5. 読み込んだURLにリクエストを送る。
  6. Content-Length または content-length で始まるヘッダが送られてきたら、mallocで指定された数値+1バイトの領域をレスポンス用に確保する。
  7. レスポンスが送られてきたら、確保したレスポンス用の領域に書き込む。
  8. リクエストに成功したら、レスポンス用の領域の内容を出力する。

mallocで同じサイズの領域を確保すると、バッファが使いまわしされることが期待できる。
そこで、1024バイトの領域を確保させるヘッダを送り、ボディはそれより少ないデータを渡すことで、バッファに残ったflagが出力される可能性があると考えた。

これを実行するため、AWSにAMI「Ubuntu Server 20.04 LTS (HVM), SSD Volume Type」(ami-03d5c68bab01f3496) を使用して t2.micro のEC2インスタンスを立て、そこでサーバのプログラムを動かすことにした。
このとき、サーバにアクセスできるように、セキュリティグループの設定でソース 0.0.0.0/0 からTCPの7777番ポートへのアクセスを許可した。

Content-Length で指定した長さより少ないデータしか送らずに接続を閉じると、エラーになってしまった。
そこで、Content-Length-Fake ヘッダで領域を確保させ、データのサイズは(小文字のlを使った) Content-length ヘッダで指定することにした。
最終的に、以下のサーバプログラムを用いることで、flagが得られた。
hello, world 1個ではバッファに領域を開放した時に書き込まれるナル文字が残っているようでflagが得られなかったので、hello, world を2個にした。

Information to connect to a TCP server and the files for the server were given.
Reading app.c in the given files, I found it doing these process:

  1. Accept an input of an URL.
  2. Allocate a 1024-byte buffer using malloc.
  3. Read the contents of ./flag.txt to the allocated buffer.
  4. Free the allocated buffer.
  5. Send a request to the URL read.
  6. Allocate (the number specified plus one)-byte buffer for storing response when it receives headers that begins with Content-Length or content-length.
  7. Store response to the allocated buffer on receiving that.
  8. Output what in the buffer for storing response after a successful request.

When allocating same-sized buffers via malloc, there is a high chance that the buffer is reused.
Threfore, I thought that the flag remaining in the buffer can be printed if a header to have it allocate a 1024-byte buffer is sent and the body is shorter than that.

To achieve this, I created a t2.micro EC2 instance with the AMI "Ubuntu Server 20.04 LTS (HVM), SSD Volume Type" (ami-03d5c68bab01f3496) on AWS to run my server program.
I configured the security group to accept accesses to TCP port 7777 from the source 0.0.0.0/0 to make the server available.

Closing the connection with sending less data than specified in the Content-Length resulted in an error.
Therefore, I decided to have it allocate the buffer using a Content-Length-Fake header and specify the data size using a Content-length (with small l) header.
In conclusion, I obtained the flag using this server program.
I put two hello, world because using only one didn't reveal the flag and I thought that is because there are null characters written on freeing the buffer remaining in the buffer.

server.pl

buckeye{https://secret.club/2021/05/13/source-engine-rce-join.html}

BuckeyeCTF 2021