I've got a web application with an SQL injection as part of an INSERT statement. It looks like this:
INSERT INTO table1 VALUES ('str1', 1, 'INJECTION HERE')
I can insert the regular multiple-query injections such as ');truncate table1;--
but due to the fact that Java + MySQL is used it does not allow stacking multiple queries so the above injection would result in an error from MySQL and the second query never gets executed.
So basically it seems that all one can achieve from such an injection in the aforementioned architecture is injecting "junk data", which is possible without an injection as well.
There are more techniques such as using load_file()
but that would still not allow me to manipulate the database to the extent I'm looking for.
Am I missing something here? Is there some other way to use this injection for gaining control over the database?
Of course, if you change your database/driver combination from your current implementation to something supporting multiple requests, then you'll activate a dormant security hole that (no doubt) people will have forgotten about!
Ignoring the nefarious, malicious scenarios, the above will cause you problems with inserting regular data, including quote characters etc. i.e. the above simply won't work for particular sets of data (unless cleansed/esaped etc.). I would correct it simply for functionality purposes.
You should have a look at PreparedStatement, and the data insertion methods for this (setString()) etc.
e.g.:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setString(2, "Insert what you like here")
The setString() method will support any string without escaping/injection issues.
SQL injection doesn't have to delete something from the database. The attacker might want to retrieve some valuable data that he's not supposed to have access to.
For example, consider the following post-injection form (I'm not familiar with MySQL syntax, but something like this should be possible in general - add casts as needed):
INSERT INTO table1 VALUES ('str1', 1,
-- injected stuff --
'' || (SELECT valuable_info FROM admin_only_table WHERE id=1) || ''
-- end injected stuff --
))
Now table1
- which can be, say, where some publicly accessible info is retrieved from, so anyone can see the values - contains a potentially sensitive value from a presumably secure table admin_only_table
.
Of course, this assumes that your server doesn't do any tricks such as user impersonation or otherwise limits permissions on SQL level for the queries, but rather performs them all with full privileges.
As explained in this post, there are more bad things that can happen to your application than the classic table DROP
:
- call a sleep function so that all your database connections will be busy, therefore making your application unavailable
- extracting sensitive data from the DB
- bypassing the user authentication
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose.