IBM Appscan Security Vulnerability SQL injection - java

I have App scan through which i scan my projects but at statements like
preparedStatement = conn.prepareStatement(sql);
there is SQL.Injection Vulnerability , i am using esapi api for setting the value in prepared statement e.g.
preparedStatement.setString(1 , OracleEncoder.encode(code) );
OracleEncoder is doing This
ESAPI.encoder().encodeForSQL( ORACLE_CODEC,param);
Any idea how can i fix this Vulnerability?

Assuming you are doing static analysis, appscan does not have a mark up for your ESAPI API, you should create a SQLi validator mark up for your encodeForSQL method in appscan. That way the next time you scan, the scan engine will pick up the new mark up and understand the SQLi threat is neutralized by the esapi call.

You don't need to encode bind parameters to preparedStatement,
// preparedStatement.setString(1 , OracleEncoder.encode(code) );
preparedStatement.setString(1 , code );
The relevant part of the PreparedStatement.setString() JavaDoc says,
The driver converts this to an SQL VARCHAR or LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends it to the database.

If you are using ESAPI library function and prepared statement in your code,then you can mark this issues Not an issue.
Prepared statement is one of the mitigation technique to a avoid SQL injection .
preparedStatement = conn.prepareStatement(sql);

Related

MariaDB JDBC chokes on column name containing curly brackets

I have a very simple SQL query I need to run
SELECT `id`, `{Document id}` FROM `test`.`test` LIMIT 10;
where {Document id} is a column name. Whenever I run it through MariaDB JDBC, it fails with error unknown escape sequence. From my understanding {CALL ...} is used to call stored procedure with a JDBC CallableStatement.
How do I escape it? I want JDBC to treat it as literal string without special meaning. \ didn't work for me.
As mentioned in deleted answer by #a_horse_with_no_name, there is setEscapeProcessing. But it's not supported by a lot of connectors (example MariaDB).
I have confirmed this issue using mariadb-java-client-2.2.5. It is not an issue with mysql-connector-java-5.1.44 so you might want to report this issue to MariaDB.
Following the suggestion by #JoopEggen in the comments above, I got it to work with MariaDB JDBC by adding sessionVariables=sql_mode=ANSI_QUOTES to the connection string and using
ResultSet rs = st.executeQuery("SELECT \"{Document id}\" FROM test.test");

Appscan source edition - SQL Injection

I am using Appscan source edition for Java Secure Coding. It is reporting an SQL injection in my application. The issue is that we are generating the query dynamically in code so I cannot use a prepared statement. Instead I have to us e Esapi.encoder().encodeForSql(new OracleCodec(), query). AppScan does not consider this to mitigate the SQL injection issue.
final String s = "SELECT name FROM users WHERE id = " +
Esapi.encoder().encodeForSql(new OracleCodec(), userId);
statement = connection.prepareStatement(s);
This code additionally does not work for ESAPI.encoder()
How can I resolve this issue?
what you should do is
final String s = "SELECT name FROM users WHERE id = ?"
statement = connection.prepareStatement(s);
statement.setString(1, userId);
The documentation for encodeForSQL recommends a PreparedStatement which you can still use which dynamically generated queries:
Encode input for use in a SQL query, according to the selected codec
(appropriate codecs include the MySQLCodec and OracleCodec). This
method is not recommended. The use of the PreparedStatement interface
is the preferred approach. However, if for some reason this is
impossible, then this method is provided as a weaker alternative. The
best approach is to make sure any single-quotes are double-quoted.
Another possible approach is to use the {escape} syntax described in
the JDBC specification in section 1.5.6. However, this syntax does not
work with all drivers, and requires modification of all queries.
Let's check what the encoder is doing to see why your code have an injection vulnerability. The encoder calls encodeCharacter in the oracle codec which simply replaces single quotes with two single quotes:
public String encodeCharacter( char[] immune, Character c ) {
if ( c.charValue() == '\'' )
return "\'\'";
return ""+c;
}
This only makes sense if the value is inside single quotes, which string values would be. If id is actually an integer and you wanted to concatenate it with the query, then you would convert it to an int type first instead of using this encoder.

create a user on mysql database through java gui

I am coding an interface which manages a database with all DML and some DDL features. One feature should be, that an admin can add users to the database with specified priviledges.
I know how to grant priviledges in sql i only need it done via a java application.
So is there a way to get this done safely? It probably will work with a simple executeUpdate
String cu = "create user"+userName+" identified by "+pw+";";
Statement stmt;
stmt = con.createStatement();
stmt.executeUpdate(query);
but this opens my ass for injections. Is there a way to get this done safely by a preexisting method ?
Please help me out, mighty stackoverflow community :)
Yes, there is a better way of doing this. Use PrepredStatement instead of Statement.
You need gap and quation ' for password,
String cu = "create user "+userName+" identified by '"+pw+"';";
|
|_put gap here

Standard library to escape strings (without prepared statements)

I'm searching for a Java standard library to escape strings before using them in a SQL statement. This is mainly to prevent errors and to prevent SQL injection, too.
Unfortunately, I will not be able to use prepared statements as is is suggested in a lot of other threads.
Is there any standard library I can use?
I've seen StringEscapeUtils at Apache Commons but I really don't know if this is state of the art.
Thank you very much in advance!
This is a non-trivial problem and a critical one because of SQL injection security issues. I would instead consider using SQL ? type arguments instead of escaping. For example, to search for a particular string:
Instead of doing:
SELECT * FROM accounts
WHERE name = 'escapedstring1' AND password = 'escapedstring2'
I'd use:
SELECT * FROM accounts WHERE name = ? AND password = ?
You will then need to pass in the injected strings (without any escaping needed) as arguments to your SQL methods. Here's how to do it using JDBC. Not sure if that would apply to you.
Something like:
String statement = "SELECT * FROM accounts WHERE name = ? AND password = ?";
try {
PreparedStatement stmt = databaseConnection.prepareStatement(updateString);
// notice that it is 1 based, not 0 (ick)
stmt.setString(1, name);
stmt.setString(2, password);
ResultSet results = stmt.executeQuery();
Here's how ORMLite, my ORM library, does it as an example using a select argument.
Hope this helps.
You can use Apache Commons, it's the very mature project.

What is the best way to 'ping' a database via JDBC?

I'm trying to determine the best way to ping a database via JDBC. By 'best' I mean fast and low overhead. For example, I've considered executing this:
"SELECT 1 FROM DUAL"
but I believe the DUAL table is Oracle-specific, and I need something more generic.
Note that Connection has an isClosed() method, but the javadoc states that this cannot be used to test the validity of the connection.
With JDBC 4 you can use isValid(int) (JavaDoc) from the Connection Interface. This basically does the trial statement for you.
Some driver implement this by sending the correct dummy SQL to the database and some directly uses low level operations which reduces the parsing overhead.
However beware of the timeout, some drivers (DB/400 and Oracle Thin) do spawn a new time thread for each invocation, which is not really acceptable for most Pool validation scenarios). And Oracle also does not seem to use a prepared statement, so it’s kind of relying on the implicit cache.
Yes, that would be Oracle-only, but there is no generic way to do this in JDBC.
Most connection pool implementations have a configuration parameter where you can specify the SQL that will be used for ping, thus pushing the responsiblity to figure out how to do it to the user.
That seems like the best approach unless someone comes up with a little helper tool for this (of course, it precludes using potentially even faster non-SQL-based methods like Oracle's internal ping function)
MySQL has a nice mechanism, documented in this SO answer. From the answer:
"/* ping */ SELECT 1"
This will actually cause the driver send a ping to the server and return a fake, light-weight, result set.
Having said that, #eckes answer is the best (using JDBC 4's Connection.isValid(int)).
I'm not aware of a generic solution, either. For IBM's UDB on iSeries (and perhaps other DB2 systems) it would be
select 1 from SYSIBM.SYSDUMMY1;
You could try to get the db name from the connection meta data and execute a matching sql staement. E.g.
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
con = dataSource.getConnection();
String dbProductName = con.getMetaData().getDatabaseProductName();
Statement st = con.createStatement();
if ( "PostgreSQL".equalsIgnoreCase(dbProductName) ) {
rs = st.executeQuery("select version();");
} else if ( "Oracle".equalsIgnoreCase(dbProductName) ) {
rs = st.executeQuery("select 1 from dual");
} else {
...
}
} catch ( Exception ex ) {
System.out.prinln("DB not reachable");
} finally {
// close statement, connection etc.
...
}
I may be out to lunch on this one, but could you simply execute some non-sense query, such as:
SELECT * FROM donkey_giraffe_87
I don't know very much about JDBC's error handling, but perhaps you could check to see if the database is at least telling you that the table does not exist. If JDBC's error codes are vendor-specific, the Spring Framework has some utilities for mapping these codes to more meaningful exceptions.

Categories

Resources