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.
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 am using eclipse and mySQL for coding, while inserting the values I received the syntax error.
if(!(nameOfConvo.equals(visitorName))){
staffConvo = StringUtils.substringAfter(convo, ": ");
System.out.println("Staff - " + staffConvo);
String staffSql = "INSERT INTO webchatdata" + "(staffConvo)" + "VALUES ('"+ staffConvo+ "')";
myStat.executeUpdate(staffSql);
}
else {
visitorConvo = StringUtils.substringAfter(convo, ": ");
System.out.println("Visitor - " + visitorConvo);
String visitorSql = "INSERT INTO webchatdata" + "(visitorConvo)" + "VALUES ('" +visitorConvo+"')";
myStat.executeUpdate(visitorSql);
}
while in mySQL it is printing out some values, it'll only print halfway and display :
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 's in a course that he has interest in, it is likely that he will excel in it. I' at line 1
Inserting other variables into the database were fine like ex.
String timeStampSql = "INSERT INTO conversation" + "(timestamp)" + "VALUES ('" +timeStamp+"')";
myStat.executeUpdate(timeStampSql);
The problem may be with the content you're putting in to SQL.
Assuming the full string might be something like this.. (You have not provided what the actual input is in this case, so I can only assume)
Bob's in a course that he has interest in, it is likely that he will excel in it. I'm writing
Notice that the first and last character are single quotation marks.
This is breaking your sql insert string, because it will close the string when it reads ' in the text.
When you save the string, you need to escape the quotations so the string is not finished incorrectly. Note the backslashes added.
Bob\'s in a course that he has interest in, it is likely that he will excel in it. I\'m writing
I have a bean class which does maintain user data:
soppose I have created a postgresql DB table like this:
StringBuffer sqlStr = new StringBuffer();
sqlStr.append("CREATE TABLE Users ("
user_id bigint,
username character varying NOT NULL,
biography character varying NOT NULL
);
& I want to make a query command and inject my String data inside it:
sqlStr.append("INSERT INTO users(" +
"user_id, username, biography)" +
"\n\tVALUES (" + user.getID()+ "," + user.getUsername() + "," + user.getBiography()+");";
my problem is for example if the data coming from my method has quote or double quote or "," my command will become wrong suppose that the user biography is something like this :
hello, I'm Mr X an "IT Pro" ...
If I run my application and save the output inside a file called query.sql I can't use it because my query command is wrong because of quote & double quote, something like this:
INSERT INTO users(userid, username, biography)
VALUES(2, 'Mehdi', 'hello, I'm Mr X an "IT Pro" ..');
how Can I fix this problem ?
You should never ever use the above method for constructing SQL queries.
"Why not?" you ask, well; where to start. The classic example is Bobby Tables, the more general problem is SQL injection. This leaves your program open to attack but also to random failure - like the situation you describe.
Now, the solution. Always use PreparedStatement to construct your query. In your example
final String query = "INSERT INTO users(user_id, username, biography) VALUES (?,?,?)";
final PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, user.getID());
ps.setString(2, user.getUsername());
ps.setString(3, user.getBiography());
ps.executeUpdate();
A much nicer syntax to use with is the the SET syntax rather than the traditional VALUES syntax. The query would then look like
final String query = "INSERT INTO users SET user_id = ?, username = ?, biography = ?";
EDIT
The OP is building a query for a script file, not executing a query in the code.
There is a utility class in Apache Commons Lang, StringEscapeUtils. This has an escapeSql method. Looking at the source code, all this does is escape single quotes with another single quote.
This works if you build your queries with single quotes:
VALUES (" + user.getID()+ ",'" + user.getUsername() + "'...
So the query, once the example value is inserted will go from:
VALUES (10 ,'hello, I'm Mr X an "IT Pro"'...
Will become
VALUES (10 ,'hello, I''m Mr X an "IT Pro"'...
The apostrophe in "I'm" is now escaped and harmless.
Note that you obviously need to escape the values and not the query, so (assuming you have a static import for the class)
VALUES (" + user.getID()+ ",'" + escapeSql(user.getUsername()) + "'...
But does not escape other sql characters, percent signs for example.
This is really a stop-gap measure to make the code work while you come up with a more robust solution. And you should come up with a more robust solution.
Why dont you use PreparedStatement? That will also give you better performance as the SQL will be pre-compiled on DB side.
Or
You can escape the quotes using
String.replaceAll http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String, java.lang.String)
I'm building a simple java Servlet which passes categories using a URL variable into another Servlet.
For example, in the following code
ResultSet rs = qw.DBquery("select distinct manufacturer from Products order by manufacturer asc");
try {
while (rs.next()) {
table+= "<tr><td><a href=\"getItems?manufacturer="
+ rs.getString("Manufacturer") + "\">"
+ rs.getString("Manufacturer") + "</a></td></tr>\n";
}
}
its output includes:
Adobe
Adobe Acrobat
IBM
IBM - Workstations
IF I click on one, the link gets to the URL as:
http://localhost/getItems?getItems?manufacturer=Adobe%20Acrobat
However, when I get the manufacturer variable and its value
String manufacturer = request.getParameter( "manufacturer" );
ResultSet rs1 = qw.DBquery("select * from products where Manufacturer like '"
+ manufacturer + "'");
the query output fails and doesn't produce anything if there are spaces in the value of manufacturer. Any ideas or workarounds on how to convert this back? Do I need to do some kind of urldecode?
thanks in advance
The encoding of space in a URL as %20 is correct, and the web application container takes care of URL decoding.
String manufacturer = request.getParameter( "manufacturer" );
The String manufacturer in your program should therefore contain 'Adobe Acrobat' (with a space). Can you verify that (by logging it to somewhere)?
"select * from products where Manufacturer like '"+ manufacturer + "'"
Also, please use bind variables.
Directly interpolating query parameters (without any validation, too!) into SQL leaves you totally open to SQL injection attacks. It is bad for performance, too.
"select * from products where Manufacturer like ? "