This seventh challenge aims to demonstrate a more than 20 years old bug: the infamous SQL injection. A perfect challenge for beginners.
Despite being the source a numerous data breach and exploitation every years, this vulnerability is still commonly found in a lot of web apps.
Tl;Dr: Exploiting a SQL Injection on the shop website allows to retrieve a table entry containing the flag.
Alright! Let’s get into the details now!
Opening the challenge display the following website:
A simple e-commerce website, you can browse through products, add items to card and place an order. Nothing more.
Let’s dig a bit.
Browsing through the product pages we notice the
elements parameter in the URL, probably used for pagination ?
Let’s see if we can make any type of injection through this parameter before moving to the cart and order function.
Inputing random value as parameter returns the following message:
When appending a classical AND 1=1 SQL injection to the elements parameters, the page don’t display errors but load the results normally:
To make sure we have a valid SQL Injection let’s try a sleep function injection:
Good since the request took 5 seconds to proceed, we now are 100% sure we have a valid SQL injection here. Let’s see what we can retrieve from the database using this vulnerability.
Getting to know the current database
To start off let’s see how to we can manually exploit the SQL injection vulnerability to exfiltrate data. In a second part we will see how to ease the task with automated exploitation tools.
To retrieve informations from the database we are going to use an
UNION attack . Here is a nice explanation of the process:
The UNION keyword lets you execute one or more additional SELECT queries and append the results to the original query. For example:
SELECT a, b FROM table1 UNION SELECT c, d FROM table2
This SQL query will return a single result set with two columns, containing values from columns a and b in table1 and columns c and d in table2.
The first thing we need to do to perform an
UNION attack is to determine the number of columns returned from the original query (the products listing query).
You can do so using two different methods:
ORDER BYclauses injection
This method consist in injecting an
ORDER BY clauses with incremental column index until an error is returned. The advantage of
ORDER BY is that we can specify columns index number. This way we don’t have to know the exact column name.
Let’s give it a try.
ORDER BY 1:
Looks alright, no error. Let’s do the same for
ORDER BY 2,
ORDER BY 3, and so on…
ORDER BY 4 we finally get the error:
Behind the scene, the database returns an error, such as:
The ORDER BY position number 4 is out of range of the number of items in the select list.
We now gained the knowledge that the current table contains 3 columns (
price maybe ?)
This second method involves submitting a series of
UNION SELECT payloads specifying a different number of
null values every-times.
If the number of nulls does not match the number of columns, the database returns an error, such as:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
Again let’s give it a try:
UNION SELECT NULL:
We get an error, meaning the table have more than one column.
Let’s do the same for
UNION SELECT NULL,NULL,
UNION SELECT NULL,NULL,NULL, and so on…
UNION SELECT NULL,NULL,NULL we don’t get any errors:
We now confirmed in a different way that the current table contains 3 columns.
Extracting data using SQL Injection
Alright we now have all the informations we need to start extracting actual data from the database.
Let’s see how we can use
UNION attack to do so.
First, we are going to use the following query to get all the databases and tables used by the website:
SELECT table_schema, table_name FROM INFORMATION_SCHEMA.TABLES
Embed it inside our
UNION query gives the following payload:
UNION SELECT table_schema,table_name,NULL FROM INFORMATION_SCHEMA.TABLES
This query should now be able to retrieve all the databases and its table name.
Let’s give it a try:
Well… This surely looks broken but looking in the details we have all the informations we need, check the source code :
See what’s going here ? The “normal” shop SQL query request for the product
price, using the
<div> identifier and showing
In our union query, the store SQL query gets replaced by our
UNION query. The chop
id is replaced by
While this is not very readable we still gets all the informations we need. We now know that the only database is
ctf and contains one table:
Let’s continue our enumeration to get a list of each columns name in the
chop table. We can do so using:
SELECT column_type,column_name,NULL FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='chop'--
Let’s give it a try:
Awesome, we were close with our guessing. Here is all the informations we collected so far:
With that in mind let’s list all the lines in this
chop database to see if we can find juicy informations:
UNION SELECT id,price,image_url FROM chop--
Hey what’s this last product with price to $0 and broken image ?
Let’s check the source code:
<div id="chop-109" data-id="109" data-price="0" onclick="addToCart(this)">
You noticed it. The manual way is not really easy nor fast to operate.
Thankfully (or unfortunately depending on the point of view)
[SQLMap](https://github.com/sqlmapproject/sqlmap), an open source tools, allows to automate all step of a SQL Injection.
Let’s have a look at what it is capable on our Chop Shop:
Well that took only a bit more than 30 seconds. SQLMap can also extract all databases and tables:
$ sqlmap -u "http://192.168.1.21:8080/?elements=9" --tables
And extract databases content:
SQLMap also features:
- Support to enumerate users, password hashes, privileges, roles, databases, tables and columns.
- Automatic recognition of password hash formats and support for cracking them using a dictionary-based attack.
- Dump database tables entirely.
- Download and upload any file from the database server underlying file system when the database software is MySQL, PostgreSQL or Microsoft SQL Server.
- Execute arbitrary commands and retrieve their standard output.
- And the list continue…
As you can see SQLMap is an extremely complete and powerful tool, allowing anyone with little to no real knowledge to perform advanced SQL injection attacks.
That’s why it’s very important to be aware of the risks of SQL Injection and why it’s still one of the most common and dangerous vulnerability.
Primary defenses against SQL Injections:
- Use of Prepared Statements (with Parameterized Queries)
- Use of Stored Procedures
- Whitelist Input Validation
- Escaping All User Supplied Input
- Enforcing Least Privilege
- Performing Whitelist Input Validation as a Secondary Defense
- SQL Injection Software Attack | OWASP Foundation
- SQL Injection Prevention Cheat Sheet | OWASP
- Query Parameterization Cheat Sheet | OWASP
- What is SQL Injection? Tutorial & Examples | Web Security Academy
- SQL injection UNION attacks | Web Security Academy
- SQL injection in labs.data.gov via User-agent | HackerOne
- SQL injection on U.S. Dept Of Defense | HackerOne
- SQL Injection Extracts Starbucks Enterprise Accounting, Financial, Payroll Database | HackerOne
That’s it folks! As always do not hesitate to contact me for any questions or feedbacks!
See you next time ;)