Boston Key Party CTF 2015 - pwn 275: Andrew

we have an EXPERIMENTAL CDN based on nginx. It can optimize html, javascript, leetify text and rehost images. It is up at flag is in /flag.txt : 275

We were given nginx binary and a config file. The config file wasn’t really interesting, it just mapped everything to a custom action:

server {
    listen 8080;
    server_name localhost;

    location / { hello; }

Due to the nature of nginx custom actions, we’re now looking for a method called ngx_http_hello_handler() in the provided nginx binary. And of course, there is one. Basically it just takes anything after the first / and passes it to a function named handle_url(), which looked like something along the lines of

char* handle_url(char *url, int *str_size)
    url_data data;

    data.size = 0; = calloc(0x1000, 0x01);

    if( != NULL)
        CURL *curl = curl_easy_init(0x1000, 0x01);
        if(curl != NULL)
            curl_easy_setopt(curl, CURLOPT_URL);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
            curl_easy_setopt(curl, CURLOPT_FILE, &data)

            CURLcode result = curl_easy_perform(curl);
            if(result != CURLE_OK)
                fprintf(stderr, curl_easy_strerror(result));
        *str_size = data.size;
        fprintf(stderr, "Failed to allocate memory.\n");
        return NULL;

As you can easily see, this just pipes anything it gets into curl and returns it.

Lo and behold, the file:// protocol

CURL supports a variety of protocols, including a windows network share protocol (starring in the “famous” SCP hack) or the file:// protocol which lets us access stuff on the local harddrive. Now, with the help of an educated guess, we assume the pwd of the nginx we run on is the web root. So we crafted the following, simple url:

But do we have the flag?

Loading the url gives us w3b 2.0 w4s 10 y34rs 4g0, h77p w4y 70 c47ch up n3rds which isn’t the flag. Damn! But it looks so flaggy, why is that? Remember the challenge can leetify text. And indeed, back in our handler routine, we see this little gem:

char *curl_out = handle_url(url, &data_size);


if(ends_with(url, ".txt"))
    r->headers_out.content_type.len = 0xA;
    r-> = "text/plain";

At this time, I had already skimmed over the minify js and minified html functions, which basically just stripped out comments. The minify js doesn’t even do it’s job properly as it only removes block comments. Try and pipe jquery into it ;-) Back to our flag - with another educated guess one easily sees the flag now:

web 2.0 was 10 years ago, http way to catch up nerds