So I have this snippet of code:
String username = props.getProperty("jdbc.username");
try {
String username = parts[1];
// Check procedure
System.out.println("Checking user");
// Check database user table for username
conn = getSQLConnection();
Statement stat = conn.createStatement();
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
// Check given password against user entry
if(user.next()){
System.out.println("User Exists: " + username);
sendMessage("true");
return;
}
else{
System.out.println("User Does Not Exist: " + username);
sendMessage("false user");
return;
}
For educational purposes, is the SQL statement protected from an SQL injection even though I know where the input is coming from?
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
This is subject to SQL injection.
Imagine what happens if username has this value:
John'; delete from user where 'a' = 'a
And yes, a s*load of Java JDBC SQL tutorials get this wrong. Basically, always use PreparedStatements.
Not only because this makes it safe ot use even if username has malicious values as the above, but also, and more importantly, because the same query can be reused by the RDBMS engine for all further invocations.
In short, there is no reason at all not to use them. And tutorials demonstrating SQL using string concatenation should die a painful, SQL injection death.
As explained in this post, one rogue attacker can do the following to yoour application:
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 that can be affected. Even JPQL can be compromised if you are not using bind parameters.
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ
Related
Sonarqube is giving me this error:
[BLOCKER] Change this code to not construct SQL queries directly from user-controlled data
Here is my code:
String countSQL;
countSQL = (String.format("SELECT count(*) as total FROM ltid_owner.enty %s",additionalWhereClauses));
jdbcTemplateTMI.queryForObject(countSQL, Integer.class);
In the above code additionalWhereClauses could be something like this shown below which I am building on the fly when the user clicks on the grid to perform filtering on different columns:
additionalWhereClauses = where UPPER(enty_num) like '003%'
Can you please let me know how to resolve this issue?
Your code combines strings into SQL statements. If any of these strings contains user provided input, an attacker can sneak in code to trigger an SQL injection attack and possibly run arbitrary code on your computer (obligatory Bobby Tables reference).
Simple example:
String sql = "SELECT * FROM users WHERE name = '" + name + "' AND password = '" + password + "'";
If I enter ' OR 1=1 -- for the name (and "..." for the password, but that doesn't really matter anymore) the code becomes a valid SQL statement:
SELECT *
FROM users
WHERE name = '' OR 1=1 -- ' AND password = '...'
but the user name / password check is completely disabled.
To avoid this, use prepared statements. They build the SQL command in a way that SQL injection is impossible.
Maybe this never happens in your code as you don't accept user input, but Sonar doesn't know this (and human reviewers won't either). I'd always use prepared statements. Just because your code only passed column headers from a frontend, doesn't mean an attacker cannot manually call your web service endpoints and pass whatever they want, it your code runs as an HTTP endpoint.
Trying to delete record from my database, but I get the error "Unknown column '' in 'where clause'".
private void deleteUser() {
String query = "DELETE FROM user WHERE Name =" + tfemail.getText() + "";
executeQuery(query);
showUsers();
}
You can't write queries this way. Imagine someone put in the tfemail field this text:
"Joe' OR FALSE"
and let's see what that would do to your SQL query:
DELETE FROM user WHERE Name = 'Joe' OR FALSE;
bye, database!
Some dbs let you execute stuff on the server the db engine runs on. Which means this trick can be used to completely hack the machine or format the disk entirely. bye, entire machine.
This also means your executeQuery method needs to be removed - that abstraction ('here is some SQL, please run it') is rarely useful (as it cannot contain any user input), and entices you to write security leaks.
The solution is prepared statements:
PreparedStatement ps = con.prepareStatement("DELETE FROM user WHERE Name = ?");
ps.setString(1, "Joe");
ps.executeUpdate();
This solves your problem, and does so safely - ps.setString(1, "Joe' OR FALSE"); is now no longer an issue (the DB engine or JDBC driver guarantees that it will take care of the problem; the effect would be to delete the entry in your user table that literally reads "Joe' OR FALSE").
Furthermore, storing passwords in a database is not an acceptable strategy; the solution is e.g. bcrypt: Use a hashing algorithm designed specifically to store passwords.
String query = "DELETE FROM user WHERE Name ='" + tfemail.getText() + "'";
^ ^
|___________add___________|
I have developed a java program and I need to update and insert the login details of users. I have two textfields created and two buttons name add user and edit the user. when I type the username and password in the two textfields the user added to the database successfully, the error is in the edit user, I want to update the password of the user based on username,
I'm getting SQL error when trying to update the user,
here is my SQL query for updating the password of a user based on his username,
String sql = "UPDATE Admin SET password='"+JT_pass1.getText()+"' WHERE
username = "+JT_username1.getText();
when i execute im getting this error,
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column
'sss' in 'where clause'
"sss" is what I entered to username field,
Mysql database I have admin table which consists of two columns admin and username,
I cannot figure out where am I getting wrong, please any help would be highly appreciated.
Your immediate problem is that you forgot to place single quotes around the username in your query. Hence, the database is interpreting sss as a column. But you should really be using prepared statements:
String query = "UPDATE Admin SET password=? WHERE username = ?";
PreparedStatement update = con.prepareStatement(query);
update.setString(JT_pass1.getText());
update.setString(JT_username1.getText());
update.executeUpdate();
There are many advantages to using prepared statements. First, it will automatically take care of proper escaping of strings and other types of data. In addition, it will prevent SQL injection from happening.
To get this to work, you need to add quotes around the username like so:
String sql = "UPDATE Admin SET password='"+JT_pass1.getText()+"' WHERE
username = '"+JT_username1.getText()+"'";
However, updating the database this way is vulnerable to SQL injection, so it would be much better to use Prepared Statements.
To consider "JT_username1.getText()" as a part of you query string, you have to enclose it under proper quotation.
Same like added "JT_pass1.getText()" between single and double quote, you have to add "JT_username1.getText()" as well.
String sql = "UPDATE Admin SET password='" + JT_pass1.getText() + "' WHERE username = '"+JT_username1.getText()+"'";
I am getting quite angry with this, so I seek help from the crowd ;)
What I want to do: We have a Unity learning game which shall implement a login window. The entered credentials are then hashed (the pw is) and sent to the server, who then should check this against a database.
I have the following table:
xy.users_confirms with the following colums:
id username email password hashcode created
Why does my code
String sql = "SELECT " + "xy.users_confirms.password as pwhash, "
+"FROM xy.users_confirms " +"WHERE xy.users_confirms.username = " +"\"userNameToGetHashFor\"";
lead me to the SQLException "Parameter index out of range (1 > number of parameters, which is 0)"
?
Thanks, any input is much appreciated!
Try this:
String parameter = "'"+ strNameToGetHashFor + "'";
String sql = "SELECT " + "xy.users_confirms.password as pwhash, "
+"FROM xy.users_confirms "
+"WHERE xy.users_confirms.username ="+ parameter;
You are using varchar value as a parameter so it's need to be quot like this.'username'. or you can use Stored Procedure.
Personally, I would try getting a working query using the custom query box directly in phpmyadmin. Once you have a working query you can re-write it in java.
And I would try writing the syntax like this into the phpmyadmin query box:
SELECT password as pwhash
FROM xy.users_confirms
WHERE username ='userNameToGetHashFor'
Using the above syntax I don't see anyway your error could persist.
Phpmyadmin screen cap showing custom query box: http://screencast.com/t/9h8anH0Aj
(the 2 empty text boxes in screen cap are just me hiding my database info)
The comma after pwhash is one potential cause:
+ "xy.users_confirms.password as pwhash*!*,*!* "
Depending on the DBMS, you may also need to use single quotes instead of double quotes like this:
+ "'userNameToGetHashFor'";
Also this code is potentially vulnerable to a SQL Injection attack so you may want to make the userNameToGetHashFor a parameter rather than concatenating the string into the SQL statement.
So, what I'm trying to do here is check the user table in my users mySQL database for duplicate entries in the username row, before inserting a new username. Here's an example of my code. Currently, the results ResultSet does not do anything and I'm not exactly sure how to implement it into the IF statement that follows. And yes, I have the catches for the try, just not in this example. Sorry if this is a rather simple question, I just started programming with Java last week. Also, it's my first question on here and I definitely appreciate the help.
try{
String sequel = ("SELECT username FROM `users`.`user`");
PreparedStatement userNameInfo = conn.prepareStatement(sequel);
userNameInfo.executeQuery(sequel);
ResultSet results = userNameInfo.getResultSet();
if (sequel.equals("")) {
conn.setAutoCommit(false);
String sql = "INSERT INTO `users`.`user`(`username`,`password`,`email`) VALUES('" + newusername +"', '" + newpassword + "', '" + newemail +"')";
PreparedStatement prest = conn.prepareStatement(sql);
prest.executeUpdate(sql);
conn.commit();
conn.close();
System.out.println("Added Successfully!");
}
else {
System.out.println("Add failed!");
}
}
So I think what you trying to do - and should do I think, is select if the username is in the table then add or not. So the sql needs to be like:
select username from users where username = ?
then set the param in the query. See docs here:
http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html
You then need to check what is in the resultset after the query, and see if anything is in there. The API docs for this will be in about the same place as the PreparedStatement docs.
Adding a constraint in the db will also give you a belt and braces.
Hope this helps
When you define your SQL table, you can define some items to be unique.
So in your example, if you want usernames to be unique, you would add:
UNIQUE(username)
to your table declaration.
If you want the pair username / email to be unique, you would add:
UNIQUE(username, email)
The documentation is here
Have you created the primary key in the table? A primary key automatically prevents duplicate values.
If you want to prevent duplicate usernames, then make your username column the primary key.
Umm, I am not a java guy. But this may help you.
You can retrieve the row count of the first result set after the query executes. If the row count is equal to 0, that means database does not contain a similar record.