I am using PreparedStatement to execute queries for mysql database. I have written something like following:
String createQuery = "create table FEATURE(ID varchar(15) not null, ?, ?, ?)";
preparedStatement = connect.prepareStatement(createQuery);
//replacing question marks in prepared statement
int i =1;
for(Map.Entry<String,Boolean> entry: featureBool.entrySet()){
String col_final = "`"+entry.getKey()+"`"+" varchar(5)";
preparedStatement.setString(i, col_final);
}
The problem I am facing is when this query is being executed, the single quotes are being appended to the beginning and ending to the string which is replacing ? in createQuery. Can please someone help me out because I am stuck?
For e.g., if col_final = "Feature-1 varchar(5)" then in preparedStatement it is becoming 'Feature-1 varchar(5)'.
Prepared statements are meant to be used for DML (Insert, delete, update) or DQL (Select).
Create table is DDL, Prepared statement are not meant for that. Please use statement instead and dynamically create DDL statement in java.
Related
I have to add a statement to my java program to update a database table:
String insert =
"INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";
I heard that this can be exploited through an SQL injection like:
DROP TABLE customer;
My program has a Java GUI and all name, address and email values are retrieved from Jtextfields. I want to know how the following code (DROP TABLE customer;) could be added to my insert statement by a hacker and how I can prevent this.
You need to use PreparedStatement.
e.g.
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStatement ps = connection.prepareStatement(insert);
ps.setString(1, name);
ps.setString(2, addre);
ps.setString(3, email);
ResultSet rs = ps.executeQuery();
This will prevent injection attacks.
The way the hacker puts it in there is if the String you are inserting has come from input somewhere - e.g. an input field on a web page, or an input field on a form in an application or similar.
I want to know how this kind piece of code("DROP TABLE customer;") can
be added to my insert statement by a hacker
For example:
name = "'); DROP TABLE customer; --"
would yield this value into insert:
INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"');
I specially want to know how can I prevent this
Use prepared statements and SQL arguments (example "stolen" from Matt Fellows):
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStament ps = connection.prepareStatment(insert);
Also parse the values you have on such variables and make sure they don't contain any non-allowed characters (such as ";" in a name).
You can check THIS article for info on that! :)
I recommend Parameterized Queries:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
An attacker just has to enter something like 'foo#example.com"); DROP TABLE customer; into the field for email and you are done.
You can prevent this by using the proper escaping for JDBC Statements.
That's why you should be using question marks in your string statements:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
quoted from here
As explained in this post, the PreparedStatement alone does not help you if you are still concatenating Strings.
For instance, one rogue attacker can still do the following:
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
And it's not just SQL, but JPQL and HQL can be compromised if you are not using bind parameters:
PreparedStatement ps = connection.prepareStatement(
INSERT INTO customer(name,address,email) VALUES(?, ?, ?)
);
int index = 0;
ps.setString(++index, name);
ps.setString(++index, address);
ps.setString(++index, email);
ResultSet rs = ps.executeQuery();
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ
Go for PreparedStatement
Advantages of a PreparedStatement:
Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.
Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the value
You should also limit the privileges of the account that accesses the database as tightly as possible. For example, for searching, the account only needs to have read access to those tables and columns that are required. This will prevent any damaging SQL injection and limit access to sensitive data.
Even though all the other answers tell you as how can you fix SQL injections in Java, answer by Mukesh Kumar actually tells you as who is actually preventing these kind of attacks. Understand that its actually DB server which is preventing SQL injection attacks provided you as a programmer follow their recommendation of using parametrized queries.
Refer Here - Preventing SQL Injection Vulnerabilities
It wouldn't be possible for Java programmer to sanitize each & every input String so DB vendors have given us options of Prepared Statements and they tell us to prepare & execute queries by using that & rest of the things will be taken care of by the DB vendor.
Things as drastic as DROP TABLE customer; might not happen but basic premise of SQL injection is that nobody should be able to break your query by just providing invalid input ( either intentional or non - intentional ).
OWASP - SQL Injection Prevention Cheat Sheet
I have to add a statement to my java program to update a database table:
String insert =
"INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";
I heard that this can be exploited through an SQL injection like:
DROP TABLE customer;
My program has a Java GUI and all name, address and email values are retrieved from Jtextfields. I want to know how the following code (DROP TABLE customer;) could be added to my insert statement by a hacker and how I can prevent this.
You need to use PreparedStatement.
e.g.
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStatement ps = connection.prepareStatement(insert);
ps.setString(1, name);
ps.setString(2, addre);
ps.setString(3, email);
ResultSet rs = ps.executeQuery();
This will prevent injection attacks.
The way the hacker puts it in there is if the String you are inserting has come from input somewhere - e.g. an input field on a web page, or an input field on a form in an application or similar.
I want to know how this kind piece of code("DROP TABLE customer;") can
be added to my insert statement by a hacker
For example:
name = "'); DROP TABLE customer; --"
would yield this value into insert:
INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"');
I specially want to know how can I prevent this
Use prepared statements and SQL arguments (example "stolen" from Matt Fellows):
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStament ps = connection.prepareStatment(insert);
Also parse the values you have on such variables and make sure they don't contain any non-allowed characters (such as ";" in a name).
You can check THIS article for info on that! :)
I recommend Parameterized Queries:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
An attacker just has to enter something like 'foo#example.com"); DROP TABLE customer; into the field for email and you are done.
You can prevent this by using the proper escaping for JDBC Statements.
That's why you should be using question marks in your string statements:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
quoted from here
As explained in this post, the PreparedStatement alone does not help you if you are still concatenating Strings.
For instance, one rogue attacker can still do the following:
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
And it's not just SQL, but JPQL and HQL can be compromised if you are not using bind parameters:
PreparedStatement ps = connection.prepareStatement(
INSERT INTO customer(name,address,email) VALUES(?, ?, ?)
);
int index = 0;
ps.setString(++index, name);
ps.setString(++index, address);
ps.setString(++index, email);
ResultSet rs = ps.executeQuery();
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ
Go for PreparedStatement
Advantages of a PreparedStatement:
Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.
Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the value
You should also limit the privileges of the account that accesses the database as tightly as possible. For example, for searching, the account only needs to have read access to those tables and columns that are required. This will prevent any damaging SQL injection and limit access to sensitive data.
Even though all the other answers tell you as how can you fix SQL injections in Java, answer by Mukesh Kumar actually tells you as who is actually preventing these kind of attacks. Understand that its actually DB server which is preventing SQL injection attacks provided you as a programmer follow their recommendation of using parametrized queries.
Refer Here - Preventing SQL Injection Vulnerabilities
It wouldn't be possible for Java programmer to sanitize each & every input String so DB vendors have given us options of Prepared Statements and they tell us to prepare & execute queries by using that & rest of the things will be taken care of by the DB vendor.
Things as drastic as DROP TABLE customer; might not happen but basic premise of SQL injection is that nobody should be able to break your query by just providing invalid input ( either intentional or non - intentional ).
OWASP - SQL Injection Prevention Cheat Sheet
My goal is sql-escaping in bulk-insert query.
Eg:
INSERT INTO log VALUES (0,5,-7,'str'), (4,0,0,'str'), (0,0,0,'str');
The code inserts in table about 100-200 records each 30 seconds. (Log pooling).
I didn't find way to use PreparedStatement for bulk-insert, so i had to manually build that query through StringBuilder.
But i have no idea how to escape strings, don't really much want apply something like kludge-fixes (Quotes escaping through regex-replace etc).
Is there any handy way?
Two ways so far i know.
1st Way
Its insert record one by one
final String sql = "INSERT INTO tablename(columnname) Values(?)";
PreparedStatement statement = connection.prepareStatement(sql);
while (condition) {
statement.setString(1,value);
statement.executeUpdate();
}
2nd way
It inserts all record as bulk insert
final String sql = "INSERT INTO tablename(columnname) Values(?)";
PreparedStatement statement = connection.prepareStatement(sql);
while (condition) {
statement.setString(1,value);
statement.addBatch();
}
statement.executeBatch();
You need to use PreparedStatement and possibly batch insert. See http://www.exampledepot.com/egs/java.sql/BatchUpdate.html
I have to add a statement to my java program to update a database table:
String insert =
"INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";
I heard that this can be exploited through an SQL injection like:
DROP TABLE customer;
My program has a Java GUI and all name, address and email values are retrieved from Jtextfields. I want to know how the following code (DROP TABLE customer;) could be added to my insert statement by a hacker and how I can prevent this.
You need to use PreparedStatement.
e.g.
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStatement ps = connection.prepareStatement(insert);
ps.setString(1, name);
ps.setString(2, addre);
ps.setString(3, email);
ResultSet rs = ps.executeQuery();
This will prevent injection attacks.
The way the hacker puts it in there is if the String you are inserting has come from input somewhere - e.g. an input field on a web page, or an input field on a form in an application or similar.
I want to know how this kind piece of code("DROP TABLE customer;") can
be added to my insert statement by a hacker
For example:
name = "'); DROP TABLE customer; --"
would yield this value into insert:
INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"');
I specially want to know how can I prevent this
Use prepared statements and SQL arguments (example "stolen" from Matt Fellows):
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStament ps = connection.prepareStatment(insert);
Also parse the values you have on such variables and make sure they don't contain any non-allowed characters (such as ";" in a name).
You can check THIS article for info on that! :)
I recommend Parameterized Queries:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
An attacker just has to enter something like 'foo#example.com"); DROP TABLE customer; into the field for email and you are done.
You can prevent this by using the proper escaping for JDBC Statements.
That's why you should be using question marks in your string statements:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
quoted from here
As explained in this post, the PreparedStatement alone does not help you if you are still concatenating Strings.
For instance, one rogue attacker can still do the following:
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
And it's not just SQL, but JPQL and HQL can be compromised if you are not using bind parameters:
PreparedStatement ps = connection.prepareStatement(
INSERT INTO customer(name,address,email) VALUES(?, ?, ?)
);
int index = 0;
ps.setString(++index, name);
ps.setString(++index, address);
ps.setString(++index, email);
ResultSet rs = ps.executeQuery();
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ
Go for PreparedStatement
Advantages of a PreparedStatement:
Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.
Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the value
You should also limit the privileges of the account that accesses the database as tightly as possible. For example, for searching, the account only needs to have read access to those tables and columns that are required. This will prevent any damaging SQL injection and limit access to sensitive data.
Even though all the other answers tell you as how can you fix SQL injections in Java, answer by Mukesh Kumar actually tells you as who is actually preventing these kind of attacks. Understand that its actually DB server which is preventing SQL injection attacks provided you as a programmer follow their recommendation of using parametrized queries.
Refer Here - Preventing SQL Injection Vulnerabilities
It wouldn't be possible for Java programmer to sanitize each & every input String so DB vendors have given us options of Prepared Statements and they tell us to prepare & execute queries by using that & rest of the things will be taken care of by the DB vendor.
Things as drastic as DROP TABLE customer; might not happen but basic premise of SQL injection is that nobody should be able to break your query by just providing invalid input ( either intentional or non - intentional ).
OWASP - SQL Injection Prevention Cheat Sheet
I have a prepared statement like this
stmt = select * from table_name where id IN (?);
Once I pass the parameters the stmt looks like way
stmt = select * from table_name where id IN ('1,2,3');
There is no error while executing the query. However the resultset is returned only for the id=1. Is there some way I can eliminate the quotes / get the resultset for all these id's.
stmt = select * from table_name where id IN (?);
select GROUP_CONCAT(id) id from table ;
if(rs.next()){
stmt.setString(1,rs.getString("id"));
stmt.executeQuery();
}
Thanks in advance.
It's not clear what the ID type is, but I believe you should actually be preparing a statement with each possible value as a separate parameter:
select * from table_name where id IN (?, ?, ?)
Then add the three values for the three parameters. It's a common problem with parameterized SQL - when you want to be able to specify a variable number of values, you need to vary the SQL. There may be a MySQL-specific way of coping with this (like table-valued parameters in SQL Server 2008) but I don't believe there's a generic JDBC way of doing this.