SQL queries are often used retrieve or update data on a database server, which means that if attackers could in any way manipulate such query, they could access or alter data which could lead to a loss in confidentiality and integrity of data. In certain cases, it could even lead to remote code execution on the underlying systems. For this reason, it is important to defend against SQL injections.
SQL injections tend to occur when user input is not properly filtered when entered into SQL queries.
Here is a short snippet of vulnerable python code:
query = f"SELECT * FROM products WHERE name LIKE '%{user_input}%'"
The vulnerability is present in the sense that user_input is directly inserted into the String of the query. In other words, the input is inserted directly into the query. This means that input such as a quote ' could interfere with the original intended query.
For example, if the query were to be ' OR '1'='1 then the query would be changed to the following:
SELECT * FROM products WHERE name LIKE '%' OR '1'='1'%';
In this case, 1=1 would equal true and thus return all the data in that particular table. This is a simplification of the vulnerability, simply to illustrate the issue in itself. However, attackers will often perform more context-based injections to achieve more impactful results.
Generally, a layered approach is preferred. Yet, at the core of the issue the usage of “parameterised queries”, which tends to be available in most programming languages. Observe a snippet of python code with such protections:
query = "SELECT * FROM products WHERE name LIKE ?"
cursor.execute(query, ('%' + user_input + '%',))
The ‘?’ becomes a placeholder for the input that indicates to the code that this input should be taken as text and not a literal String. In other words, it prevents user input from interfering with the actual query format. Thus, protecting from injections. This tends to be the best solution, yet it may still fail due to a vulnerability within the code itself of the parameterisation function. For this reason, it is advised to add various layers of defence against SQL injections.
Below are a few examples of considerations when implementing defensive layers against SQL injections:
Frameworks that include ORMs can be used as they often provide the following benefits:
As observed above, ORMs can be a great addition to mitigating against SQL injections, yet as with any piece of code, it may have vulnerabilities. Therefore, it is also important to monitor the ORMs, or any software, for updates and CVEs.
There are a variety of steps that can be taken to prevent SQL injections and minimise its impact. It is important to take these steps as SQL injections if left unresolved can certainly lead to a compromise of confidentiality and integrity of data with potential to also leading to access of underlying systems.