SQL Injection
Last updated
Last updated
SQL Injection is a vulnerability that occurs when a parameter used to execute a SQL query is maliciously injected with data that alters the query or appends additional statements or commands to the original query. This generally occurs due to mishandling of the user submitted parameter on the backend. The most common reason this arises in my experience is due to the developers using string concatenation to form a query instead of parameterized queries, object relation mapping or stored procedures.
Depending on the situation, SQLI's can reveal data from the database, allow and adversary to inject data, or be used to compromise the backend server(s), or DDoS.
SQLI's can be categorized as In-Band, Blind, and Out-of-Band.
The following example is from Appsecco's DVNA.
There is a SQL Injection on the route http://127.0.0.1:9090/app/usersearch. The page contains functionality for searching for users by their login name. Upon clicking the submit button, the front-end sends an HTTP POST request to the backend with a body parameter login.
The source code that handles this functionality is in core/appHandler.js in the userSearch function. In line 2 the SQL query is formed using string concatenation to append the user input " + req.body.login + "
. This is where the vulnerability exists, the query string is formed using unvalidated user input with string concatenation. This allows for escaping the query using a single ' then appending a query after that.
Entering the payload ' or 1 = 1--
in the login parameter will escape the SQL Where clause quotation with the first apostrophe, then the SQL statement will be evaluated or 1=1
which is always TRUE and will return all rows from the Users table. The SQL engine will ignore everything after the 1 since the --
after the 1 is a comment. Thus the query variable with the user input data turns into SELECT name,id FROM Users WHERE login='' OR 1=1 --
.
The fix for this removes the query in line 2 and replaces it with a MongoDB model's find function which utilizes built in input sanitization. In MongoDB the Find function is used to find data in a collection, db.collection.find(
query
,
projection
)
. The query parameter is where the query is placed.
Although it is best practice to explicitly validate/sanitize all user input.
It is best practice to set the SQL user the app is using to a low privilege role. If the SQL user has high privileges such as an Admin, it can allow certain functionality to be used that would allow an adversary to turn a SQLI into a shell.
For example, many SQL servers allow support functions such as xp_cmdshell which allows for arbitrary command execution. Thus if a SQLI occurs and the SQL user has high privileges the xp_cmdshell could be used to pop a shell onto the web server. SQLMap can be used to check if xp_cmdshell is available by passing the --sql-shell or --os-cmd flags.
SQLMap
[16:32:19] [INFO] testing if xp_cmdshell extended procedure is usable
[16:33:19] [INFO] xp_cmdshell extended procedure is usable
Now if we are able to execute commands we can launch a C2 (Command and Control) Beacon and begin infiltrating the targets network.
If the database contains plaintext passwords or crackable hashes you can retrieve the password of the highest privilege user(s) and escalate privileges that way.
For database hardening and exploitation tips see OWASP's Cheatsheet:
Start with these resources then head to the other resources page:
Reference guide for MySQL, MSSQL and Oracle SQL Injection