How do I SQL inject a Java Statement that uses JDBC? - sql

The following lines of code appear in my Java program:
stmt.executeQuery("SELECT * FROM metropolises WHERE metropolis =\"" + metropolis + "\" AND continent=\"" + continent + "\" AND population>" + population);
I can put anything in for metropolis, continent, and population via a GUI, but I can't seem to get it to work if I put metropolis = a, continent = b, and population is 2; DROP TABLE tablename;
Any suggestions? I'm trying to DROP a table named metropolises so I can better understand SQL injection.

Some database libraries don't allow to execute multiple queries per call (PHP's mysql binder for example). In those, this kind of injection is not possible. Unfortunately, I don't know whether this is true for JDBC, but it might be the reason.

You don't specify what brand of database you're using (unless the "sql" tag implies Microsoft SQL Server). So here's my experience w.r.t. MySQL:
By default, the MySQL JDBC driver will execute only a single SQL statement per call. This is a good idea for defending against some types of SQL injection.
The JDBC driver has an optional connection property allowMultiQueries that you must set to allow semicolon-separated statements. See http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html

Related

Mulesoft not able to pass dynamic SQL queries based on environments

Hello for demonstration purposes I trimmed out my actual sql query.
I have a SQL query
SELECT *
FROM dbdev.training.courses
where dbdev is my DEV database table name. When I migrate to TEST env, I want my query to dynamically change to
SELECT *
FROM dbtest.training.courses
I tried using input parameters like {env: p('db_name')} and using in the query as
SELECT * FROM :env.training.courses
or
SELECT * FROM (:env).training.courses
but none of them worked. I don't want my SQL query in properties file.
Can you please suggest a way to write my SQL query dynamically based on environment?
The only alternative way is to deploy separate jars for different environments with different code.
You can set the value of the property to a variable and then use the variable with string interpolation.
Warning: creating dynamic SQL queries using any kind of string manipulation may expose your application to SQL injection security vulnerabilities.
Example:
#['SELECT * FROM $(vars.database default "dbtest").training.courses']
Actually, you can do a completely dynamic or partially dynamic query using the MuleSoft DB connector.
Please see this repo:
https://github.com/TheComputerClassroom/dynamicSQLGETandPATCH
Also, I'm about to post an update that allows joins.
At a high level, this is a "Query Builder" where the code that builds the query is written in DataWeave 2. I'm working on another version that allows joins between entities, too.
If you have questions, feel free to reply.
One way to do it is :
Create a variable before DB Connector:
getTableName - ${env}.training.courses
Write SQL Query :
Select * from $(getTableName);

next:jdbc How to allow multiple statements for SQL Server

I want to run multiple statements on a single execution against SQL Server. I do it with Node.js but I cannot run the same query using next.jdbc
For example, if I run this:
(def db {:jdbcUrl "jdbc:jtds:sqlserver://localhost:1433/TESTDB;user=sa;password=passwd"})
(def ds (jdbc/get-datasource db))
(jdbc/execute! ds ["select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE;"])
I have also tried to wrap the statement within a transaction with the same result
(jdbc/execute! ds ["BEGIN TRANSACTION select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE; COMMIT"])
I always get the first query.
I have tried Microsoft's JDBC driver also.
Sean Corfield says that if the database supports it, then next.jdbc should support it. next-jdbc: execute multiple statements?
But I cannot make it work
Solution
As indicated by Sean Corfield
(jdbc/execute! ds ["BEGIN select * from EMPLOYEE;select FIRST_NAME from EMPLOYEE; END"] {:multi-rs true})
Yes, you can run multiple statements and multiple result sets back but you have to tell next.jdbc that's the behavior you want.
Take a look at the tests for MS SQL Server running multiple statements: https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc_test.clj#L560-L572
This is mentioned (briefly) in the Getting Started guide: "If you pass the :multi-rs true option to execute!, you will get back a vector of results sets, instead of just one result set: a vector of zero or more vectors."
As far as I know, SQL Server's JDBC driver does not support multiple statements. But, even if it did, you should probably not be using it, as it opens a potential security hole for injection type attacks. Instead, if you really need to execute multiple SQL statements, either refactor your current SQL into a single statement, or else use multiple statements wrapped in a single transaction.
For reference, some other JDBC drivers, such as MySQL, might support multiple statements.

Why do Parameterized queries allow for moving user data out of string to be interpreted?

From https://en.wikipedia.org/wiki/Code_injection#Preventing_problems
To prevent code injection problems, utilize secure input and output handling, such as:
Using APIs that, if used properly, are secure against all input characters. Parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted. Additionally Criteria API[7] and similar APIs move away from the concept of command strings to be created and interpreted.
I was wondering how and why "parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted" and prevent or mitigate code injection problems?
Can you also provide some examples in explanation?
Thanks.
Compiled queries use special syntax that the database understands. They usually add placeholders for parameters such as in:
select * from applicant where name = ?
select * from applicant where name = :name
The exact syntax depends on the specific technology: JDBC, ODBC, etc.
Now, once those queries are sent to the database (without the specific parameter values), the database "saves" them. Later on (usually in the same database session), you can run them many times, by just providing the parameter values each time.
SQL Injection Safety
They are also safe against SQL injection. For example, if in the previous query instead of a simple value such as Mary you used the value x'; delete from applicant; -- the database will work safely. It would run something like:
select * from applicant where name = 'x; delete from applicant; --'
This query won't probably find anything and will be safe.
If instead you didn't use compiled query, but just decided to concatenate the SQL as a string you would do something like:
String sql = "select * from applicant where name = '" + param1 + "'";
And would end up with the UNSAFE query:
select * from applicant where name = 'x'; delete from applicant; --
This one would run two queries. The second one will delete all the information from your table. Probably not what you want.

Running multiple SQL statements in the one operation

I'm trying to use ADO to create several tables at once, into MS Access. Is it possible to do multiple statements in the one operation? For instance:
...
// I have omitted the field details
CString sQuery = "CREATE TABLE [Table1] (..., PRIMARY KEY ([ID])); \nCREATE TABLE [Table2] (..., PRIMARY KEY ([ID]));";
oRecordset.Open(oDatabase.m_pConnection, sQuery)
This fails due to a "Syntax Error in CREATE TABLE statement", although each of the create statements work on their own perfectly. Is there a way of doing this sort of thing? There will also be statements to add constraints, add indexing, etc., and I'd really like to be able to do it so that I don't have to split up the string into separate parts.
ADO isn't the issue: the ACE/Jet engine simply does not support multiple SQL statements within a single operation. In other words, ACE/JET SQL lacks procedural syntax found in most 'industrial-strength' SQL products. See #David-W-Fenton's answer for more detail.
Bottom line: You will need to issue a Connection.Execute for each CREATE TABLE statement i.e. client side procedural code. But they can (perhaps should) all be run in the same transaction, of course.
ADO to MS Access does not support batch SQL statements. You need to run each statement as a separate execution.
People who think you can send multiple SQL statements to Jet in a batch just aren't thinking.
Jet is a file-server database engine -- there is no centralized server process controlling interaction between clients and the actual data store. Instead, clients are all running individual instances of Jet and cooperatively editing a file in a way that is controlled by the Jet locking file (LDB). Without a centralized process to serialize and prioritize the SQL statements, you wouldn't want Jet to be able to process multiple statements in a batch.
Those who are offering the suggestion of using ADO and separating the statements with a CrLf should code it up and give it a try and then get back to us about how useful their speculative advice actually is.
If you're sample set of commands is typical, just do something like this in VBA or the language of your choice:
public sub ExeuteBatch(BatchString as String)
var s as string
var abatch as array
sbatch = replace(sbatch, "\n", "")
abatch = split(BatchString, ";")
for each s in abatch
** adodb execute s here **
next s
end sub
That's off the top of my head, but you should be able to take it from there I hope.
Crude but it works - create the necessary number of queries with one SQL statement each, then use a Macro to run the queries successively. That's about as good as can be done with ADO/Jet.
I don't know if ADO is constructed over JET OleDB Engine, which I suppose, if it is this way, The Jet Engine doesn't support execution of multiple statements in one single batch, we tryed separating with ; and with the GO reserved word, but it does not work.
I think you can run multiple commands in one ADO Command.
You just need proper line feeds between then. i.e. \n doesn't work.
Try something like this:
(Using VB Syntaxish)
MyQuery = "Select * from Whatever " & vbLf <br>
MyQuery = MyString & "Select * from SomethingElse " & vbLF
oRecordset.Open(oDatabase.m_pConnection, MyQuery )

tool for detecting non-parametrized sql in java jdbc code

I'm looking to inspect SQL statements in Java/jdbc code to ensure that the SQL to be executed is of acceptable quality. Neither PMD not Findbugs appears to have JDBC or sql rules. I could use p6spy to log the SQL and look at that way, but this is manual.
I'm wondering if the strategy of of using PMD/Findbugs/etc to create a rule that any string passed to PreparedStatement where there is an "=" or "in" has only parametrized vars on the compare side.
Has anyone done this? Or done this by other means?
This is a tricky problem. Comparison operators like = and IN() are some cases, but there's also: != <> < <= > >= LIKE.
How do you spot cases of interpolating application variables as literals in expressions?
String sql = "SELECT *, " + someJavaVar + " AS constant_column FROM mytable";
You could search for SQL containing string delimiters, but SQL injection doesn't come only from interpolating string literals.
How would you spot cases of interpolating application variables as things other than data values?
String sql = "SELECT * FROM mytable ORDER BY " + columnname;
I don't know any automatic way to detect SQL injection flaws. Code review is a more effective way to spot them. In every SQL statement that contains interpolated application variables, you have to confirm that the application variables are "safe" and that your app has explicitly validated them or transformed them so they don't contain dangerous payload.
Do you have the ability to completely test the application with a debugger connected to it?
Set a breakpoint in your JDBC driver's implementation of Connection.createStatement(), and run the app... (or if using a driver for which you don't have source code, write a fake driver that just delegates calls to the real one, and log all instances of createStatement())