Search code examples
javaandroidandroid-sqlitesql-injectionandroid-cursor

Preventing SQL Injection by using Bound Paramaters / Prepared Statements


Good Morning World,

I'm in the process of making a few small changes to source code and it has been brough to my attention that I've exposed myself to being vulnerable to SQL Injection in my current implementation. I apologize if this is a bit of a noob question - but what would be the best practice / method of preventing such an attack using the example below? (I'll reformat my other code using the same method - I'd just like to see how this might be done in this instance)

Source Example:

public class EventUtils {

public static long getEventId(Context context,long msgId) {
    long eventId = -1;
    Message msg = Message.restoreMessageWithId(context, msgId);
    if(msg != null) {
        PackedString info = new PackedString(msg.mMeetingInfo);
        long startTime = Utility.parseEmailDateTimeToMillis(info.get(MeetingInfo.MEETING_DTSTART));
        long endTime = Utility.parseEmailDateTimeToMillis(info.get(MeetingInfo.MEETING_DTEND));
        String title = info.get(MeetingInfo.MEETING_TITLE);

        String[] projection = new String[]{ Events._ID };
        String selectionClause = Events.DTSTART + " = '" + startTime + "' AND "
                + Events.DTEND + " = '" + endTime + "' AND "
                + Events.TITLE + " = '" + title + "'";
        ContentResolver resolver = context.getContentResolver();

        Cursor cursor = resolver.query(CalendarContract.Events.CONTENT_URI,
                projection, selectionClause, null, null);
        if(cursor != null && cursor.getCount() > 0) {
            while(cursor.moveToNext()) {
                eventId = cursor.getLong(0);
            }
        }
        cursor.close();
    }
    return eventId;
}
}

Solution

  • Modified query string (here you set the parameter placeholders):

    String selectionClause = Events.DTSTART + " = ? AND "
        + Events.DTEND + " = ? AND "
        + Events.TITLE + " = ?";
    

    Then pass the parameters as a string array (will replace the placeholders, respecting the **same order*):

    Cursor cursor = resolver.query(CalendarContract.Events.CONTENT_URI,
          projection, selectionClause, new String[]{startTime, endTime, title}, null);