My latest project will make you a hacker💻

Photo by Andrew Neel on Unsplash

My latest project will make you a hacker💻

Trigger warning: Betrayal 😔

Engineering drawing was a subject I despised back in my first year of engineering. It was:

  • a compulsory course

  • way out of my comfort zone, and unfortunately,

  • I missed the theory lectures, making it super hard for me to turn in my end-of-semester subject assignment.

Fortunately, a friend decided to help me out with the final assignment, so I could finish it on time. My friend gave this assignment to a mutual friend of ours, assuming that he'll pass it on to me. In a surprising turn of events, said mutual friend decided to go all Brutus on me and just stole my assignment. I was devastated😭.

Why do I tell you this? Because for situations like these, I bring you: ShitExpress! ShitExpress is the leading (because no competition) online store to send a box of shit to the people you (do not) love. Simply choose your animal, send the receiver's address, and make the payment. Your recipient will get a box of literal poo, home delivered, completely anonymously!

Now I wish I could tell you that I made ShitExpress, but no, that's not why I introduced you to them. Recently, the website got hacked by a prominent hacker, who leaked the information of the customers of the website, by using a well-known vulnerability, known as SQL Injection. What is SQL injection, you ask? Let me use my project to demonstrate.

Our journey starts in the planes of localhost:5000, where we stumble upon a humble account creation page. Standard stuff nowadays, so let's create an account for ourselves. We'll set our username as Hashnode, and our password will be incredibly strong "ilovekittens"✨. Let's log into our accounts and see what we get.

image.png

After logging in using the same details, we stumble upon this:

image.png

Hmm. An e-commerce website. Let's check if they have apples in stock. image.png

Cool. Since I've recently studied databases in college, there's a theory that I'd like to test. Let's see if we can have a little fun with the application.

Chapter 1: Give me everything tonight 🎉

In the back-end of the application, there is likely some type of pattern matching query which goes something like this:

SELECT [some discerning information of the product] 
FROM [the name of the table] 
WHERE [name of the product] 
LIKE ‘[input_string]’;

For eg, when we searched for apples, it queried something along the lines of:

SELECT name, price, quantity FROM  product_table WHERE name LIKE 'Apple' ;

This is neat, but what if we sent an SQL query as a parameter into the search bar? How will the backend of the application react? That is, what if we could inject our own SQL into the database?

We know that, when we look up 'Apples' in the search bar, the backend basically asks the database: "Hey, do we have any products which have the text 'Apples' in them?" and the database responds with a table of information on that subject. Like in this case, if we look up "Pro", it gives us both the products with the word Pro in them:

image.png

Well let us inject ';-- as our search parameter and see what we get:

image.png

The backend spits out the entire product table. Why did it do that? That's because of the query that we ran. When we inject ';-- into the database, the query becomes:

SELECT name, price, quantity FROM  product_table WHERE name LIKE '';--' ;

Our little snippet has 3 parts, ', ;, and --.

  • -- : Is a comment. Basically, it tells the backend that whatever you find written after this is not code to execute on the database, instead it's written for documentation purpose
  • ; : Is a termination character. In English we use a full stop to denote the end of a sentence. In programming, a semicolon is often used as a termination character, to denote the end of a programming statement.
  • ': Is used to end the quotation marks which are used in conjunction with the LIKE keyword.

Do you get what we did here? We tricked the backend in running a search parameter which is '' , i.e., an empty string. Simply put this triggers the following conversation between the backend and the database.

  • Backend: Hey umm, database, could you give me the details of products that match a particular pattern?
  • DB: Yeah sure. What is the pattern?
  • Backend: Well, it's an empty string.
  • DB: Well, since an empty string is a substring of every string, all the products in the database will match the criteria that you're setting. I'll be sending you the entire product table then.
  • Backend: Okay I guess?

This is how we end up with the entire product table. Although, if you think about it, the product table is hardly anything useful, considering that this information is meant to be seen anyway. Let's move on to something more useful

Chapter 2: The lion sleeps tonight 💤

Just like we have different programming languages for different purposes, we also have different database languages such as MySQL, PostgreSQL, MSSQL, and others. All of these will have different syntax, and we need to know which language the database is running since it'll affect the approach we take from here on.

Lucky for us, we can use the fact that the syntax is different for them all will benefit us. The idea is that, we'll ask the database to send us the output of the search query "Apples", and along with that, we'll ask it to sleep for 2 seconds. If there is a match between the language of the query that we're executing (say MySQL) and the language of the database (i.e., it also runs MySQL) it will go to sleep for 2 seconds, and return the results after the two seconds have elapsed. The search term for MySQL will be Apples' AND 0 = SLEEP(2);--.

If the database is NOT MySQL, the conversation will be as follows:

  • Backend: Hii! The query is : Apples' AND 0 = SLEEP(2);--
  • DB: Dude, I have no idea what this means. Show the user an error page.
  • Backend: Hmm. I'll do that.

But if the database is MySQL,

  • Backend: Hii! The query is : Apples' AND 0 = SLEEP(2);--
  • DB: 😴😴😴😴 (2 seconds later)
  • DB: Here is the search results of Apples, like you asked.
  • Backend: Thanks!

We'll keep changing the syntax of the query, till we find the language of the Database. Using this technique, we were able to figure out that the database of the application is MySQL.

On running the query:

image.png Notice how the page is loading. After two seconds, the output was as follows:

image.png

Chapter 3: Together We Can Change the World 💃

There is one crucial thing that we need to be aware of, which will dictate how badly the creator of the website (me) has messed up with the security of the website; whether or not the backend can send you data that is not meant to be sent to the user, i.e., can you get data which is never meant to be seen by the end user? Let's check that out.

For this, we'll use the Apples' UNION (SELECT 1,2,3) ;-- query. Here, we're asking the database to do two things. First, we're asking the database to send us the output of the 'Apples' query. Along with that, we're asking the database to append the values 1, 2, and 3 to the end of the result from the 'Apples' query. The conversation is as follows:

  • Backend: Hi Backend. Query is : Apples' UNION (SELECT 1,2,3) ;--
  • DB: So, you want me to tell you the details of products with Apples as a keyword in them, and along with that, you want me to append 1,2, and 3 to them? Sure. Here you go.
  • Backend: Thanks

image.png

This is BAD. Like really, really bad. While 1,2 and 3 is rather useless data, we can get more useful results using the query Apples' UNION (SELECT TABLE_NAME, TABLE_SCHEMA, 3 from information_schema.tables) ;--

information_schema provides access to database metadata, information about the MySQL server such as the name of a database or table, the data type of a column, or access privileges. Simply put, for our purpose, information_schema is a table that holds the information of tables. From this table, we can extract the table names, and the database to which they belong, for ALL the databases on the SQL server.

The skeleton of the query remains the same, but instead of appending 1,2,3 to the table, we append the name of the table, the name of the database, and 3. The 3 is required because you can only append if the structure of the two tables that you are unionizing is the same. Since the first query (Apples) returns 3 things: Name of product (apples), price (20), and quantity (1000), the table that we are appending to it (Table name, database name) also needs to have 3 fields. The '3' here acts as a dummy field so that tables can get unionized.

The output gives us a lot of table data, some of which is from a database of some other application. image.png

Here, the tables comments, product, product_review, and user closely match the features of our application, so these are most likely the tables associated with this application, and the name of the database is honours.

Chapter 4: Going down for real 😲🤯

Notice the user table? That is the holy grail. It's what every hacker is looking for. We're close to hitting gold now. We'll be using the same union query with the information_schema table in order to get the names of the columns in the user table. The query is Apples' UNION (SELECT COLUMN_NAME,2,3 FROM information_schema.columns WHERE TABLE_NAME='user') ;--.

We're using information_schema to print the columns of the table user. Here, the output is:

image.png

Look! The table now has three column names in it: ID, Password and username. Now all we have to do is extract these usernames and passwords using the query : Apples' UNION (SELECT username,password,id FROM honours.user );--, and we get:

image.png

Look! Hashnode is the username that we selected, and the long string of text is known as the hash of our password. Hashing is the process of taking your plaintext password (ilovekittens in our case) and passing it through a mathematical blender and turning it into meaningless sludge. We will then store this password in our database. When user wants to login, he will enter the password, which will go through the blender again. Then the sludge created is compared with the sludge stored in our database, and if it is same, then the user is given access. In this way, even if a hacker gets access to passwords, the hacker doesn't get the plaintext passwords, only this sludge. Along with this, the passwords also go through a process called salting, which further increases security. I'll be writing a full article on password authentication, and will be talking about salting in much more detail.

Chapter 5 : In the end ❣

So this is it! That's the project that I want to demonstrate. It's an intentionally vulnerable web application to demonstrate SQL Injection. As you saw today, SQL Injection is a method of interfering with the queries that an application makes with the database. OWASP has a cheatsheet that you can read to make your applications secure against SQL injection attacks.

There's also a part for practicing Cross site scripting (XSS) attacks on the Web app, but this article is pretty long already so I'll wrap it up here. If you want to read about XSS, you can check out my blog article on that topic. Lastly, I'd like you to thank Mike Pound's Computerphile video on SQL injection. This is where I got the idea to make this application. Also, if you're curious about what happened at ShitExpress, here's the link to that blog.

I hope you enjoyed this week's blog. Have fun and have a wonderful week ahead of you!

Did you find this article valuable?

Support Shaunak Deshpande by becoming a sponsor. Any amount is appreciated!