Quoted string not properly terminated Exception - java

I was updating password in an oracle databse using a java servlet like this
Connection con;
PreparedStatement ps,ps1;
ResultSet rs;
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch (ClassNotFoundException e)
{
System.out.println("Drivers Not Found");
}
try{
con=DriverManager.getConnection("jdbc:odbc:SharedCryptography", "fyp", "fyp");
}catch(SQLException e1)
{
}
String query="UPDATE tbGroup SET GPassword='"+mypassword+"' where GName='"+GroupNamee+"' and OEmail='"+OwnerId+"'";
java.sql.Statement stmt = con.createStatement();
stmt.executeUpdate(query);
But it gives java.sql.SQLException: [Oracle][ODBC][Ora]ORA-01756: quoted string not properly terminated
Am i doing something wrong in it?Please help

You should absolutely avoid string concatenation in SQL statements. You will get in all kind of security and stability problems. Your problem is simply be resolved by using a prepared statement:
String sql="UPDATE tbGroup SET GPassword=? where GName=? and OEmail=?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, myPassword);
ps.setString(2, groupName);
ps.setString(3, ownerId);
ps.executeUpdate();
If you do this, no "'" or "%" or "_" or " in your parameters will cause any problems. Alternatively you can try to escape your characters, but why bother - the PS method is not only more robust and easier to read, it is often also more performant.
For a general description of the security problems, see: https://www.owasp.org/index.php/SQL_injection

One of your variables (probably password) has a quote or semi colon in it. Since you build up your query via String concatenation, you are vulnerable to SQL injection attacks. It looks like you accidentally attacked yourself via injection. If you had a properly maliciously formatted variables you could have done quite a bit of damage to your database.
Please use Parameterized queries
PreparedStatement stmt = con.prepareStatement("UPDATE tbGroup SET GPassword= ? where GName= ? and OEmail=?" )
stmt.setString(1, mypassword);
...
stmt.executeUpdate();
See this for more details
https://www.owasp.org/index.php/Preventing_SQL_Injection_in_Java

Related

Error in preparedstatement.executeupdate()

I was executing my code on IntelliJ and it shows an error in this code, I don't understand why? I just have 3 columns and 1 row in my database and I want to update each column with new values( VARCHAR() ), but keeps showing this error.
print("\n>>");//print is a function which does System.out.print("");
String url= in.escinput();//escinput() is a function which does ob.nextLine()
print(">>");
String user=in.escinput();
print(">>");
String pass=in.escinput();
String nurl="",nuser="",npass="";
println("Uploading updates...");
try {
Connection c = DriverManager.getConnection(url, user, password);
Statement s=c.createStatement();
PreparedStatement ps;
ps=c.prepareStatement("Update conn set url="+url);
ps=c.prepareStatement("Update conn set user="+user);
ps=c.prepareStatement("Update conn set password="+pass);
ps.executeUpdate();
ResultSet rs=s.executeQuery("SELECT * from conn");
while (rs.next())
{
nurl=(rs.getString("url"));
nuser=(rs.getString("user"));
npass=(rs.getString("password"));
}
if ((nurl.equals(url))||(nuser.equals(user))||(npass.equals(pass)))
{
if ((nurl.equals(url))&&(nuser.equals(user))&&(npass.equals(pass)))
println("Update was sucessful");
else
{
if (!(nurl.equals(url)))
println("URL was not updated");
if (!(nuser.equals(user)))
println("USER was not updated");
if (!(npass.equals(pass)))
println("PASSWORD was not updated");
}
}
c.close();
}
catch (Exception e)
{
in.conerror();
String h=in.escinput();
if (h.equals("printST"))
e.printStackTrace();
}
In this line
PreparedStatement ps;
ps=c.prepareStatement("Update conn set url="+url);
ps=c.prepareStatement("Update conn set user="+user);
ps=c.prepareStatement("Update conn set password="+pass);
ps.executeUpdate();
IntelliJ shows this error
java.sql.SQLSyntaxErrorException: Unknown column 'passs' in 'field list'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1350)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at JA_2_0.main(JA_2_0.java:256)
I don't understand what's happening, please help
Since I don’t see passs (with three s characters) in your code, I’m guessing the pass variable contains something like ,passs in it, quite possibly as a deliberate measure to test your proper use of PreparedStatement.
Don’t invent your own sanitizing of input
I assume in.escinput() is meant to sanitize a string so it’s safe to place into an SQL statement. However, no programmer should be doing that themselves. PreparedStatement already does that, and it will always do it better than any application programmer can:
String pass = ob.nextLine();
// ...
ps = c.prepareStatement("Update conn set password=?");
ps.setString(1, pass);
Repeated assignments are destructive, not additive
The assignment operator (=) does not add to a variable. When you assign three values to ps, you are just replacing the value of ps. The old value is discarded. There is no secret mechanism remembering or adding the assignments into a batch operation.
You probably just want a single update statement:
String url = ob.nextLine();
String user = ob.nextLine();
String pass = ob.nextLine();
// ...
ps = c.prepareStatement("Update conn set url=?, user=?, password=?");
ps.setString(1, url);
ps.setString(2, user);
ps.setString(3, pass);
ps.executeUpdate();
ps.close();
You could also do it as three statements, though that doesn’t have any benefit, and in fact would be slower:
ps = c.prepareStatement("Update conn set url=?");
ps.setString(1, url);
ps.executeUpdate();
ps.close();
ps = c.prepareStatement("Update conn set user=?");
ps.setString(1, user);
ps.executeUpdate();
ps.close();
ps = c.prepareStatement("Update conn set password=?");
ps.setString(1, pass);
ps.executeUpdate();
ps.close();
Method calls don’t need to be encased in parentheses
Finally, you don’t need parentheses around every expression. Generally, parentheses are only needed when you need to override the natural precedence of operators. While they don’t make a difference in how the program behaves, they do make your code harder to read and harder to maintain.
Meaning, you can change this:
nurl=(rs.getString("url"));
nuser=(rs.getString("user"));
npass=(rs.getString("password"));
to this:
nurl=rs.getString("url");
nuser=rs.getString("user");
npass=rs.getString("password");
And you can change this:
if ((nurl.equals(url))||(nuser.equals(user))||(npass.equals(pass)))
{
if ((nurl.equals(url))&&(nuser.equals(user))&&(npass.equals(pass)))
to this:
if (nurl.equals(url) || nuser.equals(user) || npass.equals(pass))
{
if (nurl.equals(url) && nuser.equals(user) && npass.equals(pass))
And you can change this:
if (!(nurl.equals(url)))
println("URL was not updated");
if (!(nuser.equals(user)))
println("USER was not updated");
if (!(npass.equals(pass)))
println("PASSWORD was not updated");
to this:
if (!nurl.equals(url))
println("URL was not updated");
if (!nuser.equals(user))
println("USER was not updated");
if (!npass.equals(pass))
println("PASSWORD was not updated");
The period (.) has extremely high precedence, so an expression that uses it is treated as a single value in almost every circumstance.

SQL insert into Quotes wrong

int rs = stmt.executeUpdate("INSERT INTO Leden VALUES (null,"+u+","+p+",'1')");
I'm getting the error
java.sql.SQLException: Unknown column '(the U variable)' in 'field list';
I know for sure it is 100% the "" but i can't seem to find it where it goes wrong
any help is appreciated!
This is my whole method (I want to learn how to do it with a prepared statement)
public static void connectionDB(String u, String p, String f){
{
try {
String username = "/////////";
String password = "///////";
String url = "///////////////";
Connection connection = DriverManager.getConnection(url, username, password);
Statement stmt = connection.createStatement();
int rs = stmt.executeUpdate("INSERT INTO Leden VALUES (null,'"+u+"','"+p+"','1')");
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("Database connected!");
}
}
It should be like
int rs = stmt.executeUpdate("INSERT INTO Leden VALUES (null,'"+u+"','"+p+"','1')");
Update:-
You can also look into prepared statements because
Prepared statements are much faster when you have to run the same statement multiple times, with different data. Thats because SQL will validate the query only once, whereas if you just use a statement it will validate the query each time.
Assuming fields are A,B,C,D;
A is int and remains are strings
String insertTableSQL = "INSERT INTO Leden"
+ "(A,B,C,D) VALUES"
+ "(?,?,?,?)";
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "Hello");
preparedStatement.setString(3, "this");
preparedStatement.setString(4, "OP");]
preparedStatement .executeUpdate();
It should be
int rs = stmt.executeUpdate("INSERT INTO Leden VALUES (null,'"+u+"','"+p+"','1')'");
The issue is, that " is used in SQL for objects like columns or tables, whereas ' is used for strings. So in +u+, which seems to not exists in context of your query.
Your query itself should therefore look something like (given, that +u+ and +p+ are strings.
INSERT INTO Leden VALUES (null,'+u+','+p+','1')
If you need to have " inside your columns, it would read like
INSERT INTO Leden VALUES (null,'"+u+"','"+p+"','1')
Also I would recommend to specify the columns you are inserting to so it looks similar to:
INSERT INTO "Leden" ("col1", "col2", "col3", "col4") VALUES (null,'+u+','+p+','1')
This will prevent your query from failing when extending table definition by another column.
Also using prepared statements could be a good idea here, as it helps you preventing from e.g. SQL injections.

SQL command not properly ended in servlets

i have a servlet which takes emailid and password from a form, which is then supposed to access the table called hr.faculty, and if the credentials found correct, creates a session. but i am getting an error: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended when i try to login. plz help.
The code is as follows:
email=request.getParameter("email");
pass=request.getParameter("pass");
try{
try {
Class.forName(driver);
} catch (ClassNotFoundException ex) {
out.println(ex);
}
Connection con=null;
con=DriverManager.getConnection(oracleURL,username,password);
DatabaseMetaData dmd=con.getMetaData();
Statement s=con.createStatement();
String q="SELECT password FROM HR.faculty WHERE email=" + email;
ResultSet rs=s.executeQuery(q);
pw=rs.getString("password");
if(pw.equals(pass)){
//session creation
}
Looks like a syntax error on your query, you're not using binding variables so you have to do the wrapping yourself. This would work:
String q="SELECT password FROM HR.faculty WHERE email='" + email+"'";
In general using prepared statements is much preferred as it protects you from SQL injection.
Also looks like your retrieval of the result is invalid, you need to move the cursor in the ResultSet otherwise it will return an error. This would work:
ResultSet rs=s.executeQuery(q);
rs.first();//move to the first result
pw=rs.getString("password");
Try
String q="SELECT password FROM HR.faculty WHERE email='" + email + "'";
But you look for prepared statements.
I kind of cringe every time I see code like this. You should be using prepared Statements instead. What you are doing allows SQL injection.
It will alleviate the security holes, and your syntax error if you use prepared statements.
Use PreparedStatment s = con.prepareStatement(mySqlQuery); instead of Statement s = con.createStatement();
Then in your sql string, you replace all "input" with a ?, so mySqlQuey = "SELECT password FROM HR.faculty WHERE email=?"
You then replace all question marks with s.setString(1, value). Or if you were replacing it with an int it would be s.setInt(1, value); etc.
The edit to your code:
Connection con=null;
con=DriverManager.getConnection(oracleURL,username,password);
DatabaseMetaData dmd=con.getMetaData();
PreparedStatement s=con.prepareStatement("SELECT password FROM HR.faculty WHERE email=?");
s.setString(1, email);
ResultSet rs=s.executeQuery(q);
pw=rs.getString("password");
if(pw.equals(pass)){
//session creation
}

what is wrong with the sql query in the java code

String sql = "UPDATE `test`.`books` SET ? = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1,whatToUp);
ps.setString(2, data);
ps.setString(3, isbn);
ps.executeUpdate(sql);
System.out.println("Statement executed");
conn.close();
Error say that something is wrong with query . I am usign MySQL 5.6.
I copied the statement from the workbench 6.0 and just placed ? wherever I needed.
Even this Gives an error:
String sql = "UPDATE `test`.`books` SET `title` = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(sql);
System.out.println("Statement executed");
conn.close();
You can build the query dynamically
String sql = "UPDATE `test`.`books` SET " + whatToUp + " = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(); // you need to use the overloaded method without an argument
Note that you are then vulnerable to SQL injection.
If for some reason that is wrong, remove all the quotes.
String sql = "UPDATE test.books SET " + whatToUp + " = ? WHERE isbn = ?;";
If that doesn't work, then your schema doesn't match. That's up to you.
In my rush to answer I didn't see you were using
ps.executeUpdate(sql);
This method's javadoc says
Note:This method cannot be called on a PreparedStatement or
CallableStatement.
You have to use
ps.executeUpdate();
since you've already provided the sql statement to the method.
All of this would've been solved extremely quickly if you had just provided the exception stack trace. Consider that next time you ask a question
The problem is that you are calling executeUpdate(String) on a PreparedStatement, for which the documentation says:
SQLException - [...], the method is called on a PreparedStatement or CallableStatement
You need to use executeUpdate() (so without parameters) to execute a PreparedStatement. The reason is: a prepared statement already knows its query (the one it was created with), so it makes no sense to provide a query when executing it.
Note that the MySQL implementation is not entirely conforming to JDBC. It actually does allow executing with a String here, but it causes a syntax error because of the parameter placeholders.
Your first piece of code will never work, because parameters can only be used in places of values, not in places where object names (like table names) are expected.
#SotiriosDelimanolis gave you the answer.
Just build the SQL String differently
Stringbuilder sql = new Stringbuilder("UPDATE test.books SET ");
sql.append(whatToUp);
sql.append(" = ? WHERE isbn = ?");
PreparedStatement ps = null;
ps = conn.prepareStatement(sql.toString());
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(sql.toString());
System.out.println("Statement executed");
conn.close();

java.sql.SQLException: SQL logic error or missing database, SQLite, JDBC

I have created a database connection with SQLite using JDBC in Java. My SQL statements execute properly, but sometimes I get the following error while I use conn.commit():
java.sql.SQLException: SQL logic error or missing database
Can anyone please help me how to avoid this type of problem. Is there a better approach of calling JDBC programs?
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:/home/Data/database.db3");
conn.setAutoCommit(false);
String query = "Update Chits set BlockedForChit = 0 where ServerChitID = '" + serverChitId + "' AND ChitGatewayID = '" + chitGatewayId + "'";
Statement stmt = conn.createStatement();
try {
stmt.execute(query);
conn.commit();
stmt.close();
stmt = null;
}
Can your variables serverChitId & chitGatewayId contain characters that would corrupt the SQL? It is usually safer to use PreparedStatements:
PreparedStatement ps = conn.prepareStatement("Update Chits set BlockedForChit = 0 where ServerChitID = ? AND ChitGatewayID = ?");
ps.setString(1, serverChitId);
ps.setString(2, chitGatewayId);
ps.executeUpdate();
This way the JDBC driver is responsible for making sure the necessary escapes are made to the strings.
Try setting conn.setAutoCommit to true. Also you need to delete conn.commit();.
If you are doing this inside of a function, make your function synchronized.
It's even more better if you use PreparedStatement instead of Statement.
All this is happening because sometimes you are trying to connect and modify your database at a same time and since the last connection hasn't commited yet, it throws that exception. When you set it to autoCommit it will handle the flow by itself.(it was really painful for me cause it says nothing more, I read all of the org.sqlite.DB files to find this out)
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:/home/Data/database.db3");
conn.setAutoCommit(true);
PreparedStatement ps = "Update Chits set BlockedForChit = 0 where ServerChitID = ? AND ChitGatewayID = ? ";
ps.setString(1, serverChitId);
ps.setString(2, chitGatewayId);
try {
ps.executeUpdate();
}

Categories