SQL Injection (CWE-89)

Overview

Description

SQL stands for Structured Query Language, which is used to store data in a structured format like a table with rows and columns. SQL is used by almost all websites to store data.

SQL Injection is the most common vulnerability in which attacker inject SQL code in a web application, which will be executed by the database server. The attacker will inject malfunctioning SQL code to access/modify sensitive data from the database.

Example

Consider a website www.site.com which has user login functionality.

When the user fill the form and click on submit button, THE following HTTP Request is generated.

POST /login.php HTTP/1.1
Host: site.com

username=rahul&password=mySecret

At backend, webserver handling this request as,

uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)

This code is vulneable to SQL Injection.

Attacker can use actual username and password as password' OR 1=1 which will result in,

SELECT id FROM users WHERE username='username' AND password='password' OR 1=1'

Then the attacker can log in even with the wrong password. Because OR 1=1 is always True, and the newly generated query is checking either password is correct OR 1=1 So, even though password is invalid, attacker will be able to login.

In the given source code, the password is at the end of the SQL query. Otherwise, the attacker has to comment out the remaining part of the query by using SQL Comment or Null character.

Impact

  • An attacker can read, modify, add, delete records in the database.
  • Can leak sensitive data such as account credentials, personal information of the user, business-critical data, credit card details, etc.
  • May lead to RCE (Remote Code Execution).
  • It can modify data on the website, which can damage the reputation of the organization.

Prevention

  • Use prepared statement (Parameterized query) instead of string concatenation in SQL Statement.

    • in our example , we used String concatenation sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'" Instead , we should use prepared statement as,
      ```
      PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");
      statement.setString(1, input);
      ResultSet resultSet = statement.executeQuery(); 
      ```
    
  • Never trust user input.

  • Filter user input based on whitelist instead of blacklist.

Tools

  • sqlmap : Automatic SQL injection and database takeover tool.