Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Wargame: Challenge 1

Options
  • 25-03-2011 6:33pm
    #1
    Closed Accounts Posts: 20,759 ✭✭✭✭


    Hi guys,

    I've setup a virtual server and will host a few wargames over the coming weeks. The first game involves one of my own scripts "Briste".

    The object of the game is to gain admin control over the website, and simply posted your nickname or name onto the page. Bonus marks will be giving to anyone who can e-mail me the contents of a secret file. Do not post any clues on this page or on the website as to how you accomplished the attack.

    All details on the website: http://briste.dyndns.org

    Best of luck!

    Please do not abuse the server. There is no need for XSS, or brute-forcing. I'll be monitoring the logs, so any rampant abuse and I will take it offline. I will be hosting the server for a few days, but if it's offline - it just means I have restarted it, as I'm hosting off a laptop.


Comments

  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Also, if you gain admin access - you can change the password for the next hacker :) Just make sure it's not overly complex so that people have a chance to crack it.


  • Closed Accounts Posts: 2,267 ✭✭✭h57xiucj2z946q


    Ok looks like I got my name on there. Cheers for that. That was a fun challenge.


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Well done Damo. I got your e-mail, good man :)


  • Registered Users Posts: 367 ✭✭900913


    Fun challenge.


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Thanks for the entries. Interesting attempts in the access logs :) I've taken the server offline now.

    List of those who fully completed the challenge.
    -peann
    -earlgray
    -Damo2k
    -900913

    Also, procrastinator managed to gain admin access on the CMS, but didn't complete the second part.


  • Advertisement
  • Registered Users Posts: 1,311 ✭✭✭Procasinator


    dlofnep wrote: »
    Thanks for the entries. Interesting attempts in the access logs :) I've taken the server offline now.

    List of those who fully completed the challenge.



    Also, procrastinator managed to gain admin access on the CMS, but didn't complete the second part.

    Didn't get to try for too long, had work to do. :p


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    It's ok :) You got the most of it done.


  • Registered Users Posts: 495 ✭✭jakedixon2004


    Never mind, didn't read your post.


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Ok, I've started the server again for 24 hours to give a few more people a chance to complete it.

    http://briste.dyndns.org/

    Please don't abuse the server. No need for brute-forcing or XSS.


  • Registered Users Posts: 495 ✭✭jakedixon2004


    hacked and hacked


  • Advertisement
  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Well done :) Try the second part of the challenge now :)


  • Registered Users Posts: 495 ✭✭jakedixon2004


    dlofnep wrote: »
    Ok, I've started the server again for 24 hours to give a few more people a chance to complete it.

    http://briste.dyndns.org/

    Please don't abuse the server. No need for brute-forcing or XSS.
    dlofnep wrote: »
    Well done :) Try the second part of the challenge now :)

    I will finish it when I get back from work lol


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    I'm impressed at the amount of people who have partially completed the challenge or fully completed it :) Well done to all.

    Ifah & Procrastinator have completed it fully - with Redshift gaining admin access, along with jakedixon2004.


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Challenge is now over. Thanks to everyone who took part. Here is my solution.

    Wargame: Challenge 1 Solution

    To object of the game was to gain admin level privileges on the CMS, to allow you to post a new item. The second object of the game was to read a file in the /tmp directory. Both of these were accomplished via SQLi.

    The first thing to do was to check a few of the pages to see if parameters are being passed to the server, and if so - are they being filtered? After a bit of poking, we can see that the article.php page is insecure.

    article.php?id=1' produces an SQL error
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

    Therefore, we can assume that this page is vulnerable to SQLi. I did filter some other pages, as like most real world scenarios - you'll often have to search for one script out of many that the developer forgot to secure.

    The most logical way to attack the script is by using a UNION attack. This allows you to join the results of the original query, with your own query - providing that the columns of both queries match. This is mandatory for UNION SELECT statements. You can read more about the UNION operator here: http://www.w3schools.com/sql/sql_union.asp

    Before we can proceed with a UNION attack on the script, we need to know how many columns exist in the original query. Otherwise, we cannot perform a valid UNION SELECT query. To do this, we use an ORDER BY clause.

    If we ORDER BY with a column that does not exist, it will produce an error. Take the following example.

    briste1.png

    The object here is to try gradually increment or decrement the number until you no longer receive an error. In the case of Briste, we are looking at 6 columns. Note that the %20 is just an URL encoded value for a space, incase the URL looks messy.

    Now that we know the original query has 6 columns, we can perform our UNION SELECT query. It's important to point out that it's useful to use a null value in the original query, so that we only output our query. So you can either use NULL, or a non-existent ID, such as -1.

    article.php?id=null UNION SELECT 1,2,3,4,5,6--

    Here we will see that 2 columns are visible on the page. Remember, while all columns may be used in the query - the developer may not have a need to have them all on the page. ID for example would not be required to output to the page - it's just required to keep a sequential order for the posts.

    In the case of briste, we can see columns 3 and 4 being output. These are the columns that we will use to output any data from our own query.

    briste2.png

    @version, or version(). If one doesn't work, try the other.

    @version,5,6--

    Here we can see we've used the 4th column to output the SQL server version. In this case, it's MySQL 5.1.36-community-log on my local server. MySQL 5 is interesting in that it allows us to map out the entire database, by querying the information_schema database. You can read more about information_schema here: http://dev.mysql.com/doc/refman/5.0/en/information-schema.html

    There are a few other functions we can use, such as database() which will give us the name of the current database, or user() to give us the current user of the DB.

    With information_schema, we can query it's tables to find out the names of the tables and columns that exist in the Briste database. We can also find out other information, such as user permissions - but that's outside the scope of this walk-through. I'd recommend installing something like WAMP, and popping into phpmyadmin to have a look at the makeup of the information_schema database, to get an understanding of the information it contains.

    It's important to point out that when attacking web-applications, you won't always have the benefit of having the information_schema DB at your disposal, so you'll often have to guess table and column names. But in the case of Briste, it's MySQL 5 - so we don't :)

    The first thing to do is to list all the table names that exist in the database. To do this, we query information_schema.tables.

    article.php?id=null UNION SELECT 1,2,3,group_concat(table_name),5,6 FROM information_schema.tables WHERE table_schema=database()--

    This may look like alot to digest at first, but it's not alot. The group_concat() function allows us to join all the table names, so we don't have to list them all one by one with individual queries. We are specifying that the table_schema=database(), to only list the table names in the current database being used by the Briste script.

    So at a simple level, all it is doing is asking to SELECT all the table names in the information.tables table, WHERE the current database is in question.

    We should get 2 table names back - articles,users.

    We will want to next get the column names of the users' table, so that we can pull information like usernames and passwords. To do this, we just query the information_schema.columns table, where the table name is users. It's important to point out that you generally won't be able to use quotes to specify the users table - like WHERE table_name="users", so to overcome this - we use the CHAR() function, which will convert the integer values of letters and combine them into a string server-side.

    You can use this ASCII table to get the decimal values for the CHAR function, or you can use the hackbar addon for firefox which will automatically convert them for you.

    The value for users will be CHAR(117,115,101,114,115).

    So our full query should look like this:

    article.php?id=null UNION SELECT 1,2,3,group_concat(column_name),5,6 FROM information_schema.columns WHERE table_name=CHAR(117,115,101,114,115)--

    We should get the following column names in our response.

    id,username,password,email,realname

    Then, it is just a matter of querying the users table, to retrieve the username(s) and password(s).

    article.php?id=null UNION SELECT 1,2,3,concat(username,0x3a,password),5,6 FROM users--

    The concat function allows us to join two values together. This is useful where we might only have 1 column that's outputting data, or where we want data such as a username and it's corresponding password to be output side by side. 0x3a just represents a colon, it allows is to split the username and password visually on the page.

    In this case, we're returned with one username and password - the admin account :)

    admin:21232f297a57a5a743894a0e4a801fc3

    The password is encrypted with MD5, which you can use a password cracker, or an online service like http://www.md5decrypter.co.uk/ to crack it.

    Once we have cracked the password, we simply login as admin and submit a new article with our username. And that's the first part of the challenge over.

    The second part is relatively simply if you know what function to use. It just involves using the load_file() function, to load /tmp/secret.txt.

    article.php?id=null UNION SELECT 1,2,3,load_file("/tmp/secret.txt"),5,6--

    This will load a secret file, with a code on it which you had to e-mail to my challenge account. And that's the end of the challenge. It's important to note that the load_file function will only read a file where you have read level privileges. For example, to enumerate the users on a linux machine, just use load_file("/etc/passwd") - You'd be surprised what files and logs you may have access to.

    Sin é.


  • Registered Users Posts: 495 ✭✭jakedixon2004


    Well done on the tutorial and the challenge dude. Looking forward to the next one :)


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    I'll stick up the next one soon.

    I'm going to be running a series of wargames - from web-applications, to full on servers.


  • Registered Users Posts: 495 ✭✭jakedixon2004


    Good to hear. As I said before, if you need a hand hardware wise just give me a shout ;)


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    Sound dude :) Appreciated.


  • Registered Users Posts: 56 ✭✭PeterHughes


    Crap I missed it, bring on number 2.


  • Closed Accounts Posts: 20,759 ✭✭✭✭dlofnep


    sorry peter


  • Advertisement
Advertisement