Android Studio Sqlite Sqlinjection possible with gestures? - android

I implemented an app using an SQLite database and the data are stored in background without any user interactions. The only point where the use is needed is when data are deleted with an gesture and that is my question.
Is it possible to make an SQL injection through a gesture and if so, how can I prevent it?

If the user is not inputting text then SQL Injection is highly unlikely.
However, if you use the convenience methods fully and or rawQuery execSQL with the 2nd parameter, passing any values via the 2nd parameter then the values will be bound which protects against SQL injection.
This assumes that you are using the standard SQLiteDatabase as per the SDK.
Examples of inserting rows
This example uses execSQL (both forms) and the insert convenience method to demonstrate the principles of using bound arguments and in the first example of not using a bound argument.
theSQLitedatabase.execSQL("INSERT INTO mytable VALUES('" + userdata + "')"); //<<<<<< potential for injection
theSQLitedatabase.execSQL("INSERT INTO mytable VALUES(?)",new String[]{userdata}); //<<<<< protects as value is bound by SQLite itself
/* Uses the convenience method that builds the SQL (as per 2nd example) and protects */
ContentValues cv = new Contentvalues();
cv.put(the_column_name_as_a_string,userdata);
theSQLitedatabase.insert("mytable",null,cv);

Related

Android SQLite - named parameters

I'm working on Android application that uses SQLite as a local storage. I need to use parameters in sql query but all examples I have found contain unamed parameters, like so:
INSERT INTO SomeTable(ColA, ColB, ColC) VALUES (?,?,?);
I'm wondering - does SQLite on Android supports named parameters? Something like this instead of question marks..
INSERT INTO SomeTable(ColA, ColB, ColC) VALUES (#paramA, #paramB, #paramC);
SQLite itself supports this (according to the documentation https://www.sqlite.org/lang_expr.html).
Thanks in advance
The Android database API allows parameter binding only by index.
This does not prevent you from using named parameters in SQL, but you still have to use the correct index to bind them.
This is pretty much useless, except for documentation, or for reusing a parameter:
db.rawQuery("SELECT * FROM Tab WHERE A = #search OR B = #search",
new String[]{ search });
A more android SQLite specific way is to use a ContentValues for sql insert. In the example below. values is a ContentValues and it contains the column name and the value for the column. Columns not in the ContentValues are set to their default value on the insert.
id = sqlDB.insertOrThrow(RidesDatabaseHandler.TABLE_RIDES,
null, values);

android SQLiteDatabase.insert vs executeSQL

I am working on an app which has multiple db insert/update queries and throughout the app i have used
SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)
method for inserting any data to any table. What i mean by this is i create a ContentValues object and put all my values as key/value pair inside this object and pass it on to this this method.
contentValues.put("col1", valueCol1);
contentValues.put("col2", valueCol2);
contentValues.put("col3", valueCol3);
So just wanted to check if this way of inserting records to a sqlite table is better or is it better to use executeSQL [ From SQLinjection standpoint]. I do understand as per the documentation here
[http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#execSQL(java.lang.String)][1]
that its recommended to use insert over execSQL. But which is more prone to SQLInjections if at all one is. Any inputs/suggestions.
As suggested in the page that you linked
"Instead, you're encouraged to use insert(String, String,
ContentValues), update(String, ContentValues, String, String[]), et
al, when possible."
you should use insert() when it is possible.
To avoid SQL injection requests, you need to clearly delineate between
the SQL statement and the data it includes. The ContentProvider’s
query(), update(), and delete()methods and Activity’s managedQuery()
method all support parameterization. These methods all take the
“String[] selectionArgs” parameter, a set of values that get
substituted into the query string in place of “?” characters, in the
order the question marks appear. This provides clear separation
between the content of the SQL statement in the “selection” parameter
and the data being included. [Mobile Application Security]
So, insert() method like update() or delete() should be sql-injection free.
You should always use parametrized query methods, supported by Content Provider:
When accessing a content provider, use parameterized query methods
such as query(), update(), and delete() to avoid potential SQL
injection from untrusted sources. Note that using parameterized
methods is not sufficient if the selection argument is built by
concatenating user data prior to submitting it to the method.
reference here

Use of Direct Queries in SQLite?

I am currently studying SQLite and I have found that it uses various classes like ContentValues for insertion and updation... I was wondering whether I have to follow the given way or can I write a normal SQL query and use db.execSQL() method to execute them?
Will it bring any inconsistency to my database because with these all "extra" steps doesnt it stop the flow of the query and I feel it would be faster if we use a query directly.
You can do any SQL command you want with db.execSQL except select command or any other SQL command that return data (you use db.rawQuery() for this). The classes used are helper classes that make it easy for you to manipulate DBs (try inserting 100 rows with 20 columns each using ContentValues and db.execSQL and you will get the point). For small tables it will not differ much (and you will not cause inconsistecies), however, for large tables with inputs that depend on user interface or use calculations, it might be useful to have a class like ContentValues with its helper methods.
Yes you can definitely use this way like using
myDB.execSQL("INSERT INTO MyTable VALUES ('fffff', 'numb', 20)");
to insert values but only when you are using database for small queries.
Also there are some flaws using direct methods which gets removed using ContentValues
For example,try to insert a blob into the database using this method ,you will get a null bitmap while converting the retrieved data to bitmap.But when you insert using ContentValues,you will get the correct data i.e you will be able to convert that into Bitmap.

inserting to multiple tables with ContentProvider

I'm implementing a PRIVATE ContentProvider which has few tables with relationships (one to many, many to many). In my current implementation all of the tables are accessible by URIs.
how can I simplify the interface so the inner 'through' tables won't have to be accessed by URIs ?
for example, I have a POSTS table, each POST has many TAGS through the TAGGINGS table.
I want to interact only with the POSTS URI and do the 'private' work inside of the ContentProvider.
for query its simple to return a cursor with joined tables, but how do I do this with insert ? is bulkInsert what I should look into ?
It is a limitation of ContentProvider. If you are not exposing your data to other applications you can use your custom database adapter implementation with methods and queries straight hitting your requirements.
bulkInsert() won't help in this situation as it inserts rows only into one table at once. But take a look at ContentProvider.applyBatch() method and ContentProviderOperation, ContentProviderOperation.Builder classes (you may need withValueBackReference() for one-to-many inserting).
These links should help you understand how to use them:
http://www.grokkingandroid.com/better-performance-with-contentprovideroperation/
http://www.grokkingandroid.com/androids-contentprovideroperation-withbackreference-explained/
What are the semantics of withValueBackReference?
But notice, using ContentProviderOperation is much slower than bulkInsert() if you are inserting many rows at once, as it parses Uri (string comparisions) each time the operation is going to be performed. Doing this way you still have to expose Uri for inserting into child table.
If you decide to use applyBatch(), overwrite it in your provider so it performs all operations in one transaction, so you retain consistency in data and speed up database operations:
#Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
ContentProviderResult[] results = super.applyBatch(operations);
db.setTransactionSuccessful();
return results;
} finally {
db.endTransaction();
}
}
You are free to insert to multiply tables as long as the values needed are provided.
For example:
ContentValues v = new ContentValues();
v.put("title","post1");
v.put("tag","tag1");
getProvider().insert(POST_URI,v);
In the implementation of insert, you could check if fields (tag) belongs to other table exists.If it does , it means that you should do extra works - insert tag first if it does not exist, set up correct association between the tag and the post just inserted.
You can check the source code of android contacts for the reference.
UPDATE:
To insert multiply tags, one hack-y way is to insert a comma separated string. THis is not elegant but it works.
Just to get this right: You want to have one URI and insert a post and all its tags with one insert call to the ContentProvider? Correct?
The problem is, that you need to have all values in the ContentValues object. There is a reason for normalization in database. Nevertheless it might be doable. For tags this should be easy. Just use one String for all tags. For example "android, ios, bada, wp7" and parse this string in your insert method.
You could also use a naming plus integer convention. And as long as there is a tag1, tag2,... tagX you would read these values from within your ContentProvider's insert method.
Neither is elegant, but would work.
In this case bulkInsert or applyBatch have no place in your code. They come only into play, if you want to use multiple calls to your ContentProvider at once and within one transaction.
But I think the better solution would indeed be to actually use multiple operations as described by biegleux.
Since you are going to be inserting into multiple tables the normal SQLiteDatabase.insert helper functions will not work. But this is completely doable in a performant and nice way.
You need to look at this from the endpoint of the user who is going to be inserting into you ContentProvider, even if it is only yourself. So first define the names or keys for all of you fields. Since you won't be using SQLiteDatabase.insert you don't actually need to name them the same as the database fields. None of the names should be duplicate. If for example you have fields in two different tables overlap perhaps tag in TableA and in TableB you could define the name for those field as TableA.tag and TableB.tag. Or use semantic naming for more descriptive names that don't collide.
Next you need to create your insert queries using SQLiteStatement per this answer. Make sure the names you use in createInsert are the same ones that the callers of the ContentProvider use as keys in the ContentValues.

Android SQLite: nullColumnHack parameter in insert/replace methods

The Android SDK has some convenience methods for manipulating data with SQLite. However both the insert and replace methods use some nullColumnHack parameter which usage I don't understand.
The documentation explains it with the following, but what if a table has multiple columns that allow NULL? I really don't get it :/
SQL doesn't allow inserting a completely empty row, so if initialValues is empty, this column [/row for replace] will explicitly be assigned a NULL value.
Let's suppose you have a table named foo where all columns either allow NULL values or have defaults.
In some SQL implementations, this would be valid SQL:
INSERT INTO foo;
That's not valid in SQLite. You have to have at least one column specified:
INSERT INTO foo (somecol) VALUES (NULL);
Hence, in the case where you pass an empty ContentValues to insert(), Android and SQLite need some column that is safe to assign NULL to. If you have several such columns to choose from, pick one via the selection mechanism of your choice: roll of the dice, Magic 8-Ball(TM), coin flip, cubicle mate flip, etc.
Personally, I'd've just made it illegal to pass an empty ContentValues to insert(), but they didn't ask me... :-)

Categories

Resources