Stacktrace with SQL injection? - java

If i insert a quote symbol " in the codContract parameter I receive the following error.
Error querying database. Cause: java.sql.SQLSyntaxErrorException:
ORA-00972: identifier too long
The error may exist in mappers/existence.xml The error may involve
com.iv.queryinterface.AssistenzaMapper.getTitlesFromCodContratct-Inline
The error occurred while setting parameters
SQL:
SELECT t.id_title,
c.des_lastname,
c.des_firstname,
to_char(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW,
DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE
FROM Ivf_Policy p,
Ivf_Title t,
Ivg_Client c,
Ivf_Price pr
WHERE Cod_Contract = TEST
AND p.id_policy = t.id_policy
AND t.cod_type_title IN(2, 3, 13)
AND t.cod_statustitle IN(1, 2)
AND t.cod_client = c.cod_client
AND t.id_price = pr.id_price;
Cause: java.sql.SQLSyntaxErrorException: ORA-00972: identifier too
long
In this example, i set " TEST as value for the codContract parameter. My questions are:
Is this an exploitable SQL injection or a false positive that just prints an sql error into the stack trace?

The code is susceptible to SQL injection, and does no escaping. All that is avoidable by the use of PreparedStatement. Where the query string is not composed dynamically.
Now "TEST is the first part of an SQL identifier till a closing double quote.
I do not want to instruct readers on hacking, but think what something like
"'' OR 1=1 "
+ "UNION SELECT u.login, u.password, '', '', '', '' "
+ "FROM users"
+ "\u0000-- ";
might reveal on data.

Use java.sql.PreparedStatement for avoiding SQL injection.
String query =
"SELECT " +
" t.id_title , " +
" c.des_lastname , " +
" c.des_firstname , " +
" TO_CHAR(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW, " +
" DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE " +
"FROM " +
" Ivf_Policy p, " +
" Ivf_Title t, " +
" Ivg_Client c, " +
" Ivf_Price pr " +
"WHERE " +
"1 = 1 AND " +
" Cod_Contract = ? " +
"AND p.id_policy = t.id_policy " +
"AND t.cod_type_title IN(2, " +
" 3, " +
" 13) " +
"AND t.cod_statustitle IN(1, " +
" 2) " +
"AND t.cod_client = c.cod_client " +
"AND t.id_price = pr.id_price;";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, 'TEST');
ResultSet rs = stmt.executeQuery();

To avoid SQL injection, do not append parameter values directly to SQL queries.
Use bind variables instead.
Thanks.

Related

JDBC resultset not working when using aliases I receive " java.sql.SQLSyntaxErrorException: ORA-00905: missing keyword"

I wanted to execute this query, but it gave me an error without using variables but it gave me an error ORA-00905: missing keyword.
I tested the query in SQL Developer and it ran with no errors. I'm probably think it's a driver issue or a syntax issue with JDBC. But I have no idea here's the code:
public List<ReimbBean> getAllReimb() {
String sql = "select reim.reimb_id, reim.reimb_amount,"
+ "reim.reimb_submitted, reim.reimb_resolved, "
+ "CONCAT(CONCAT(u.user_first_name,' '),"
+ " u.user_last_name) AS \"REIMB_AUTHOR\", "
+ "reim.REIMB_RESCRIPTION, rst.REIMB_STATUS, "
+ "rtype.REIMB_TYPE, CONCAT(CONCAT(urs.user_first_name,' '), "
+ "urs.user_last_name) AS \"REIMB_RESOLVER\""
+ "FROM ERS_REIMBURSTMENT reim"
+ "LEFT JOIN ERS_USERS u"
+ "ON u.ERS_USERS_ID = reim.REIMB_AUTHOR"
+ "LEFT JOIN ERS_REIMBURSTMENT_STATUS rst"
+ "ON rst.REIMB_STATUS_ID = reim.REIMB_STATUS_ID"
+ "LEFT JOIN ERS_REIMBURSTMENT_TYPE rtype"
+ "ON rtype.reimb_type_id = reim.REIMB_TYPE_ID"
+ "LEFT JOIN ERS_USERS urs"
+ "ON urs.ERS_USERS_ID = reim.REIMB_RESOLVER"
+ "ORDER BY reim.reimb_id";
List<ReimbBean> reimbAllList = new ArrayList<>();
ReimbBean reimb = new ReimbBean();
try {
PreparedStatement preparedStatement = conn6.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
reimb.setReimbAmount(rs.getDouble("reimb_Amount"));
reimb.setReimbDescript(rs.getString("reimb_Description"));
reimb.setReimbSubmitted(rs.getTimestamp("reimb_Submitted"));
reimb.setReimbAuthor(rs.getInt("reimb_Author"));
reimb.setReimbResolved(rs.getTimestamp("reimb_Resolved"));
reimb.setReimbResolver(rs.getInt("reimb_Resolver"));
reimb.setReimbStatusID(rs.getInt("reimb_Status_ID"));
reimb.setReimbTypeID(rs.getInt("reimb_Type_ID"));
reimbAllList.add(reimb);
}
I read online that the preapareStatement is unable to bind objects only variables, so the alternative was to define them explicitly, so I created a part for declarations and substituted the fields with String variables, but the error continues to persist.
You are missing whitespaces at the end of a lot of those strings:
String sql = "select reim.reimb_id, reim.reimb_amount,"
+ "reim.reimb_submitted, reim.reimb_resolved, "
+ "CONCAT(CONCAT(u.user_first_name,' '),"
+ " u.user_last_name) AS \"REIMB_AUTHOR\", "
+ "reim.REIMB_RESCRIPTION, rst.REIMB_STATUS, "
+ "rtype.REIMB_TYPE, CONCAT(CONCAT(urs.user_first_name,' '), "
+ "urs.user_last_name) AS \"REIMB_RESOLVER\" " // Here
+ "FROM ERS_REIMBURSTMENT reim " // and here
+ "LEFT JOIN ERS_USERS u " // and here
+ "ON u.ERS_USERS_ID = reim.REIMB_AUTHOR " // and here
+ "LEFT JOIN ERS_REIMBURSTMENT_STATUS rst " // and here
+ "ON rst.REIMB_STATUS_ID = reim.REIMB_STATUS_ID " // and here
+ "LEFT JOIN ERS_REIMBURSTMENT_TYPE rtype " // and here
+ "ON rtype.reimb_type_id = reim.REIMB_TYPE_ID " // and here
+ "LEFT JOIN ERS_USERS urs " // and here
+ "ON urs.ERS_USERS_ID = reim.REIMB_RESOLVER " // and here
+ "ORDER BY reim.reimb_id";

Jooq - Plain SQL Parameterized Array/List

I would like to supply collection/arrays in the "IN" parameter but I got
When I used array:
org.jooq.exception.SQLDialectNotSupportedException: Cannot bind ARRAY types in dialect MYSQL
When I used list:
org.jooq.exception.SQLDialectNotSupportedException: Type class java.util.Arrays$ArrayList is not supported in dialect DEFAULT
Here is my plain sql:
String sql = "SELECT SUM(foo.reply = 'Y') yes " +
"FROM foo " +
"LEFT OUTER JOIN bar " +
"ON foo.id = bar.foo_id " +
"WHERE " +
"foo.id = ? " +
"AND foo.some_id IN (?) "; //this is the part I would like to use array or list
Here's how I execute it
dslContext.fetch(sql, val(fooId), val(someIds))
.into(Summary.class);
You can't do that with single bind variables (except in PostgreSQL with arrays). But you can use nested plain SQL query parts in jOOQ as such:
String sql = "SELECT SUM(foo.reply = 'Y') yes " +
"FROM foo " +
"LEFT OUTER JOIN bar " +
"ON foo.id = bar.foo_id " +
"WHERE " +
"foo.id = {0} " +
"AND foo.some_id IN ({1}) "; // Use the {0}, {1} placeholders
And then
dslContext.fetch(sql,
val(fooId),
DSL.list(someIds.stream().map(DSL::val).collect(toList())))
.into(Summary.class);
See also DSL.list(QueryPart...)

SQL Query deleting duplicate records not working

Good day. I have a query in my Java code that deletes duplicate rows in a table. Initially it worked and for a while i didn't touch the project. But on running the file a few days ago, my code was throwing exceptions. This is my code:
String query = "DELETE error_log FROM error_log INNER JOIN "
+ "(SELECT min(id) minid, service_source, channel,transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date FROM error_log "
+ "GROUP BY service_source, channel, transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date "
+ "HAVING COUNT(1) > 1 AS duplicates ON "
+ "(duplicates.service_source = error_log.service_source AND duplicates.channel = error_log.channel "
+ "AND duplicates.transaction_type = error_log.transaction_type AND duplicates.provider_name = error_log.provider_name "
+ "AND duplicates.pido_account = error_log.pido_account AND duplicates.beneficiary_id = error_log.beneficiary_id "
+ "AND duplicates.error_description = error_log.error_description AND duplicates.error_date = error_log.error_date "
+ "AND duplicates.minid <> error_log.id"
+ ")"
+ ")";
int deploy = duplicate.executeUpdate(query);
I get this afterwards:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'AS duplicates ON (duplicates.service_source = error_log.service_source AND dupli' at line 1.
How do i correct this and have the duplicates deleted from the table?
You have a missing ) on line + "HAVING COUNT(1) > 1 AS duplicates ON " and have an extra ) at the end.
String query = "DELETE error_log FROM error_log INNER JOIN "
+ "(SELECT min(id) minid, service_source, channel,transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date FROM error_log "
+ "GROUP BY service_source, channel, transaction_type, provider_name, pido_account, beneficiary_id, error_description, error_date "
+ "HAVING COUNT(1) > 1 ) AS duplicates ON "
+ "(duplicates.service_source = error_log.service_source AND duplicates.channel = error_log.channel "
+ "AND duplicates.transaction_type = error_log.transaction_type AND duplicates.provider_name = error_log.provider_name "
+ "AND duplicates.pido_account = error_log.pido_account AND duplicates.beneficiary_id = error_log.beneficiary_id "
+ "AND duplicates.error_description = error_log.error_description AND duplicates.error_date = error_log.error_date "
+ "AND duplicates.minid <> error_log.id"
+ ")";
int deploy = duplicate.executeUpdate(query);
If you haven't made any changes and it stopped working, 1) are you sure you tested this code? and 2) has anyone else made any changes without your knowledge?

SQL statement works in Workbench but not in Java

The SQL statement below works in mySQL Workbench, but when I execute it in Eclipse, there is an mySQL exeception error. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'by schedule.id' at line 1
String sqlStr = "select movie_db.movie , schedule.date , schedule.timeslot "
+ ", schedule.seats as NoSeats,"
+ " a.bookingsMade, if ( (schedule.seats-a.bookingsMade) is null, schedule.seats,(schedule.seats-a.bookingsMade) ) as availSeats"
+ " ,schedule.movie_id, schedule.id as scID"
+ " from schedule"
+ " left outer join movie_db on ( movie_db.id=schedule.movie_id )"
+ " left outer join ("
+ " select count(*) as bookingsMade, tickets.movie_id as aid from tickets"
+ " group by schedule_id"
+ " ) as a on (schedule.id=a.aid)"
+ " where schedule.movie_id=?"
+ "group by schedule.id";
PreparedStatement pstmt = sqlConnect.getPreparedStatement(sqlStr);
pstmt.setInt(1, Integer.parseInt(movieId));
ResultSet rs = pstmt.executeQuery();
that cannot work:
where schedule.movie_id=?"
+ "group by schedule.id";
change it to
where schedule.movie_id=?"
+ " group by schedule.id";

Error SQL in java: Illegal operation on empty result set

I have a problem with an empty result set, which are throwing some errors. But it is working fine as long as it is not empty.
String sql = "SELECT M2.fromProfileId, profiles.profileMiniature, profiles.firstName, profiles.lastName, profiles.timeFormat, lastMessages.message, lastMessages.timeStamp " +
"FROM (" +
" SELECT M1.fromProfileId, " +
" max(M1.timeStamp) AS lastMessageTime " +
" FROM messages AS M1 " +
" WHERE M1.toProfileId = ? " +
" GROUP BY M1.fromProfileId " +
" ORDER BY max(M1.timeStamp) DESC " +
" LIMIT 10 " +//line 60
" ) AS M2 " +
"INNER JOIN messages AS lastMessages " +
"ON (" +
" lastMessages.timeStamp = M2.lastMessageTime " +
"AND lastMessages.fromProfileId = M2.fromProfileId" +
" )" +
"INNER JOIN profiles " +
"ON M2.fromProfileId = profiles.profileId ";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1, profileId);
ResultSet result = statement.executeQuery();
JSONArray messages = new JSONArray();
while(result.next()){
JSONObject message = new JSONObject();
message.put("fromProfileId", result.getString("fromProfileId"));
message.put("profileMiniature", result.getString("profileMiniature"));
message.put("firstName", result.getString("firstName"));
message.put("lastName", result.getString("lastName"));
message.put("lastMessage", result.getString("message"));
message.put("lastMessageTime", result.getString("timeStamp"));
message.put("timeFormat", result.getString("timeFormat"));
messages.put(message);
}
and the error is Illegal operation on empty result set. How shall I fix this?
StackTrace:
Illegal operation on empty result set.
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at
com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
at
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5656)
at
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5576)
at
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5616)
at
messages.GetMessages.doGet(GetMessages.java:60)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:534)
etc..
I found many bugs in MySQL JDBC driver which seem to cause this exception.

Categories