I have problems running this sql statement. It works fine if I run it in mysql but in java I get this error:
You have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near '' at line 1
The database has an id(pk) autogenerated, varchar, int, varchar;
Can someone help me?
int i = statement.executeUpdate("INSERT INTO sala values('','"+ nume.getText() + "', "+ Integer.parseInt(capacitate.getText())+ ", '" + sunet.getText()+"'");
Don't just try to fix this code by tweaking the SQL as per adarshr's answer. You have a fundamental security problem here which you should fix right now. You're open to SQL injection attacks due to including user data directly in your SQL.
You should use a PreparedStatement, with the parameters declared as placeholders in the SQL, but then given values separately. Exactly how you'll do that will depend on your JDBC provider, but it'll look something like this:
// TODO: Fix the column names, and close the statement in a try/finally block
PreparedStatement pst = conn.prepareStatement(
"INSERT INTO sala (nume, capacitate, sunet) VALUES (?, ?, ?)");
pst.setString(1, nume.getText());
pst.setInt(2, Integer.parseInt(capacitate.getText()));
pst.setString(3, sunet.getText());
pst.executeUpdate();
Note that if you can get capacite in a way which doesn't require integer parsing, that would be good. Otherwise, consider using NumberFormat which is more locale-friendly. Also note that I've added the column names into the SQL to make this more robust in the face of schema changes.
You haven't closed your query.
int i = statement.executeUpdate("INSERT INTO sala values('','"+ nume.getText() + "', "+ Integer.parseInt(capacitate.getText())+ ", '" + sunet.getText()+"')");
^
But more than all this, you must use PreparedStatement as Jon suggested below.
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
PreparedStatement posted = con.prepareStatement(
"INSERT INTO userdate (description, UUID) VALUES ('"+ desc + "','" + postuuid + "') ON DUPLICATE KEY UPDATE");
this is the error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''
this is the code I have, does anyone know waht might be wrong with this?
Check on MySQL docs for reference on DUPLICATE KEY UPDATE https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
The keyword "UPDATE" is not the absolute end of the statement. You need to specify the fields/values that will be updated
I am trying to insert values into my postgres database
url:"jdbc:postgresql://"+SERVER_NAME+":"+PORT_NUMBER+"/"+DATABSE_NAME,DATABASE_UN,DATABASE_PASS
I am able to read from the database.
But when I write to database (no exceptions) there are no rows inserted to postgres database:
sqlQuery = "INSERT INTO tmp_recommend (id, v1, v2, v3, timestamp, v4, v5) VALUES("
+ "\""+ID+"\", "
+ "\""+value1+"\", "
+ "\""+value2+"\", "
+ value3+", "
+ new Timestamp((new Date().getTime()))+", "
+ "\"value4\", "
+ "\"value5\" "
+ ")";
st.executeUpdate(sqlQuery);
NOTE - I tried the following but didn't help:
Change autocommit setting for database
If I try to do manual commit by conn.commit() it throws an exception
org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled
I'll just stop you immediately. Never ever generate any data manipulation SQL statements using simple string concatenation. Not even in exercise because if you get used to it you have some nasty problems, starting with SQL injection. Use the PreparedStatement accordingly. In your case, like this:
PreparedStatement st = conn.prepareStatement("INSERT INTO tmp_recommend (id, v1, v2, v3, timestamp, v4, v5) VALUES(?, ?, ?, ?, ?, ?, ?)");
st.setString(1, ID);
st.setString(2, value1);
st.setString(3, value2);
st.setString(4, value3);
st.setDate(5, new Timestamp((new Date().getTime())));
st.setString(6, value4);
st.setString(7, value5);
st.executeUpdate()
Note that I did not actually compile the code, you might have to modify something. Also, I assumed you work only with textual data.
Also see: How does a PreparedStatement avoid or prevent SQL injection?
Besides preventing SQL injection attacks and some more type-safety, you probably won't encounter bugs like you have now too often. With manually creating statements you can easily make a statement which will do something, but not what you expect. In the best case it will be nothing, in worst, you just dropped a production database.
And I'm not even touching performance. Prepared statements (depending on the database, but usually) include some sort of pre-compiling.
Edit: I actually noticed with a delay (while editing my own mistake made because miscounting while reading your code) that you have written "value4" and "value5" in your original code as literals, not variables (notice the double-quotes). Others have noticed similar issues with value1 and value2. This only comes to show how cumbersome and error-prone is manual concatenating anything, not only SQL.
I'm facing an issue with insertion to SQL database from java code.
I'm using INSERT sql query using the java code to enter the data from XML file to SQL database.
You may suppose column named "Description".
Imagine there is a record in XML which contains apostrophe ('). The program crashes due to the error caused by the apostrophe which is included in the data.
I know that manually we can add another apostrophe and make it work, but imagine data of 10.000 records, how can we handle this issue?
Don't do this (string concatenation):
String sql = "insert into MyTable (description) values ('" + value + "')";
Statement st = connection.createStatement();
st.executeUpdate(sql);
Do do this (prepared statement):
PreparedStatement ps = connection.prepareStatement(
"insert into MyTable (description) values (?)"
);
ps.setString(1, value);
pt.executeUpdate();
The value will get correctly escaped for you. Not only does this protect against mishaps like the one you mentioned, it also helps defend you from SQL injection attacks.
Humorous illustration:
Source
You have two options, you should use PreparedStatement and bind your parameter(s). Or, if you really, really, want - you could use StringEscapeUtils.escapeSql(str).
I've read many threads regarding this topic, but everybody point to the character set in the database.
I'm using strings with special characters like 'ñ' and I'm not able to set them right in the database. As you may guess, the characters are changed to '?'.
The thing is that using this statement, I get it RIGHT:
stmt = con.prepareStatement("INSERT INTO LONG_CODES_TABLE (TIMESTAMP, TABLE_NAME, CODE__C, CODE_DESC)
VALUES (GET_TIMESTAMP, 'MUNICIPIOS', '" + municipio + "', '" + municipio + "') ");
And just in the same database and table, without changing anything, if I use the following I get the '?' character in the DB:
stmt = con.prepareStatement("INSERT INTO LONG_CODES_TABLE (TIMESTAMP, TABLE_NAME, CODE__C, CODE_DESC)
VALUES (GET_TIMESTAMP, 'MUNICIPIOS', ?, ?) ");
stmt.setString(1, municipio);
stmt.setString(2, municipio);
So, the character problem is happening ONLY if I use setString.
Any ideas?
EDIT: The value of the 'municipio' variable is, for example: 'ABADIÑO'.
Later, I can check the differences between doing it on way or the other by asking for that value with an sql statement, for example:
select * from long_codes_table
where table_name = 'MUNICIPIOS' and code__c = 'ABADIÑO'
One way I get the result row. The other way, I don't.
Thank you.
I had that behaviour, too. On top of that I observed that this error did not occur when the application was started from the IDE. That's how I realized that in the JVM - attributes, the one for the encoding was missing.
java %vm-opts% %clspth% -Dfile.encoding=UTF-8 ...