Category Archives: CTF Writeups

Collection of posts related to CTF writeups

PicoCTF 2013 – Injection

Challenge And another PicoCTF writeup…..i do play other ones honest! ¬† Just a lot easier to do writeups after the fact, and seen as Pico keeps their running, it’s great ūüôā

This’ll be a quick one, and it’s for the Injection challenge, which is worth 110 points.

<<CHALLENGE.jpg>>

When we click the “Problem” link, we are taken to the following page.

LoadingBayControl

“Please input username to retrieve a key”…….hmmn, wonder what happens if i try “username” seen as thats what it’s asking me todo….but nothing happens, and it bounces me back to the login page again.

OK…lets try “admin”.

NotAllowed

Ahhh, so we now know that “admin” is at least a legit user, but it can’t tell us the password…..dunno why we’d need it anyway, as there’s no password field.

OK OK OK….stop (Hammertime!) ¬†Lets get basic here people. ¬†The challenge is called “Injection” and it’s a web based authentication page. ¬†Chances are this is some kind of SQL Injection¬†challenge, and we need to be able to bypass the authentication, as we don’t know a valid username.

So…a quick Google of “sql injection bypass authentication” gives us a top link with a “Cheat Sheet” of some common SQLi commands used to bypass authentication, including the classic…”‘ OR 1=1 #” (Which even appears on the SQLi page for Wikipedia)

Entering this into the Username field gives a long list of users, their hashes, and right at the end we find….

SQLiBottom

Including the bottom entry of:

Username: admin Hash: bad_code_and_databases_is_no_fun

So theres our key.

 

For those who don’t know, here’s whats happening.

We have no idea what the PHP code in the background is doing, but we can guess it’s running some sort of SQL database query, using the value we enter into the username field. ¬†Maybe something like:

select * from users where user = '$usernamefield';

So if we enter the name “bob” it will likely fail, as bob doesn’t exist in the database, but by using the “‘ OR 1=1 # ” trick, we don’t even care what the first part of the username is (e.g donkeymagic), as long as we close off the statement with a (TICK) then append it with something that WILL return true…such as¬†OR 1=1, then finally a¬†# or a¬† to comment out any remaining part of the SQL statement.

So an entry like :

donkeymagic' OR 1=1 #

Will let us in too ūüôā

-dook

PicoCTF 2013 – PHP4 Writeup

Another post for an old CTF (but still active), and mainly just for my own reference.

This writeup is for the PHP4 challenge from PicoCTF 2013 which is still available to play!

php1-challenge

When you click the link, you get to a login page.

SecureLoginPage2

Which also has a link to the source code for the page, if you click this link, you can see the HTML code as well as the PHP code. ¬†For this explanation, i’m just going to pull out and focus on the PHP code (as it’s this that does the work for the page)

<?php
if($_POST[user] && $_POST[pass]) {
  mysql_connect("localhost","php3","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  mysql_select_db("php3");

  $user = $_POST[user];
  $pass = md5($_POST[pass]);
  $query = @mysql_fetch_array(mysql_query("select pw from php3 where user='$user'"));

  if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
    echo "<p>Logged in! Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx </p>";
  }
  else {
    echo("<p>Log in failure!</p>");
  }
}

?>

So…whats the code doing, lets break it down, line by line:

if($_POST[user] && $_POST[pass]) {

This is a basic IF statement, which checks to see if something was entered into the username and password fields in the login page form. ¬†If nothing exists in either, it doesn’t continue…if it does then the next line is…

mysql_connect("localhost","php3","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

This creates the connection to the backend MySQL database, running on the server localhost using the username php3 and the password whateverpasswordtheyused.

mysql_select_db("php3");

The next line, then specify’s the database to be used, in this case it is also named¬†php3.

On a side note, this PHP¬†code uses the older mysql_connect command, rather than the newer¬†mysqli_connect,¬†which can specify the database as well as the server, user and password….all in one command.

  $user = $_POST[user];
  $pass = md5($_POST[pass]);

The next 2 lines, sets the value of variable $user to the value entered from the login page form for the username.  It then sets the MD5 value of the entered password from the login page form to the variable $pass.

So if the entered password was “password¬†the MD5 value set into the¬†$pass variable would be¬†5f4dcc3b5aa765d61d8327deb882cf99

Now we get into the meaty bits, first up is the query that is performed against the database.

$query = @mysql_fetch_array(mysql_query("select pw from php3 where user='$user'"));

So this sets the variable $query with the value (in the form of an array) of the result of the query:

select pw from php3 where user='$user'

What this query does is selects the field pw from the php3 table where the field user equals the value in the $user variable.  So the database table MAY look something like this:

DB

I’ve added an “id” field to be the primary key in this example, and there maybe other fields, but we DO know for a fact that there is a¬†pw and a¬†user field, and we can guess at what the values might be.

Now for the IF statement that allows access…or not.

  if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
    echo "<p>Logged in! Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx </p>";
  }
  else {
    echo("<p>Log in failure!</p>");
  }

Here’s where it checks the value in the¬†$query variable (As previously mentioned, the variable format is an array, so using¬†$query[pw]¬†means that the value of¬†would be that from the¬†pw field in the database.

So..IF a value exists in the¬†$query[pw] variable AND the value in the¬†$pass variable¬†and the¬†$query[pw]¬†variable match…..then be logged in and print the key, otherwise give an error.

 

So lets assume we know a username/password for this system, which exists in the database, such as “admin” and “adminpass“.

Back upto the query, it would select the value in the¬†pw field in the¬†php3 table where the field¬†user equals “admin“, and sets the value into the variable¬†$query ($query[pw] in it’s array format)

Then it checks to see that the variable¬†$query[pw] contains a value, and that value matches the value entered into the login page form…if it does, we’re in.

 

OK, so thats how it’s SUPPOSED to work…but obviously we don’t know a valid username/password, so how can we bypass this.

Looking at the IF statement that would display the key if correct, we need to match the following:

  • Have a value in the¬†$query[pw] variable (Anything!)
  • Have a value in the $pass variable.
  • Make sure the value in¬†$pass matches the value in¬†$query[pw].

Now the¬†$pass variable we control by entering it’s value into the HTML login form.

The¬†$query[pw] variable is set from the database query, which¬†normally¬†is the password from the query, but we can get the query not get anything from the database, and instead set our own value in the variable. ¬†In this case, we will¬†set it’s value to the same as in the¬†$pass¬†variable.

The only entry point available is the $user variable, so in here we are going to start by entering the following:

‘ AND 0=1

What this does is puts a¬†‘¬†(TICK) first, which closes the value in the query, then also includes the statement AND 0=1….which means the statement will be false.

After this we also add on:

UNION SELECT “an_md5_encoded_string”

The UNION statement allows you to add a statement to an existing statement. ¬†Then the¬†SELECT “an_md5_encoded_string” specifies the value we want to be returned by the query. ¬†So basically….we aren’t doing a query against the database at all, but instead we are specifying the value we want returned by the query.

#

Finally we throw a¬†# on the end so it cancels out any further parts of the SQL query (such as any additional¬†‘s (TICK).

So the full line being entered into the Username login form field is:

‘ AND 0=1¬†UNION SELECT “an_md5_encoded_string” #

Now obviously, i need to create a MD5 encoded string, so in this example i’m using the string “picoctf“, the MD5 value of this being¬†f00257ea8eb46567aa270e1fc1b14cd0. So we’d end up with..

‘ AND 0=1¬†UNION SELECT “f00257ea8eb46567aa270e1fc1b14cd0” #

So….we enter that into the Username field, and in the Password field we enter the UN-encoded string (e.g¬†picoctf)

Hit login and…..

Success

Bingo! ūüôā

-dook

PicoCTF 2014 – Function Address Writeup

Hi folks.¬† OK this is a short and easy Reverse Engineering challenge from PicoCTF 2014. (I say easy, but it’s only easy if you know what you’re doing…so if you found the challenge difficult, hopefully this may help you to understand it.)

OK, so the challenge was Function Address and was a 60 point “Reverse Engineering” challenge.Challenge

We are provided with a link to a “program file”, which i downloaded onto a Linux VM (Kali in this case)

The first thing i always do with an unknown file, is find out what kind of file it is.  This is easily done on Linux by using the file command.File

Cool, so it’s a 32bit “ELF” file..basically a Linux executable file.

So now we know that, lets try running it (My Kali VM is setup with VM snapshots, as well as occasionally being disconnected from my network, so it’s safe to run programs, then revert back…just in case they are little nasties)

First things first, lets allow this file to be executed, using chmod.chmod

After the execute attribute has been set, our file is now a nice green colour.

Now lets run it.run

Bet you can’t find the address of find_string!

OK…if you run the program again, it prints the same message.¬† Now if we look back to the challenge it reads “we need the address of the ‘find_string’ function to do anything useful!”.

So all we need todo, is provide the address of the “find_string” function.¬† What address?¬† Well in terms of programs and Reverse Engineering challenges, it usually involves debugging the program to see whats going on “under the hood”.¬† So in this case, it’s likely going to me the address in memory where the “find_string” function is located.

Now this post isn’t going to delve into debugging, and GDB etc, but just cover how to get the address you need to complete the challenge.

Time to fire up GDB.opengdb

Now it’s loaded up….what now?¬† Well, we know we are looking¬† for a function, so lets view functions using info functions.infofunctions

This will display all the functions associated with the program we are using GDB to debug.  And if we scroll down the list we find:

0x08048444 find_string

Theres the name of the function we are after, along with the memory address of it!

Not too sure if the PicoCTF site would accept the full string format, as i just stripped off the first 0x part, and entered 08048444 which worked fine.

There we go, nice and simple.  To exit GDB just type quit.

Cheers

dook