Saturday, 23 March 2013

SQLite injection - beyond SELECT

I work a lot with mobile and that means whenever I see SQLinjection vulns, chances are that they're in SQLite. This is a massive pain because:
a) no-one really writes guides/tools for SQLite injection
b) It's really limited (as we'll see)

Unfortunately this post is about what is not possible in SQLite injection. Hopefully it will give you a guide to where to focus attacks/defence.

SQL injection as my previous post mentioned is a subset of regular SQL. There's no command execution, file reading/writing or anything particularly cool. You can't even stack queries unless the developer is using less orthodox functions (like rawquery). In essence it normally boils down to information disclosure (i.e. reading from tables that you shouldn't).

Select Statements in Mobile SQLite

With Android you (as the attacker) will hopefully be able to inject on 'projection' variable, that is the part that goes in the "SELECT ____ FROM". This obviously allows you to redirect the statement to go to anywhere else. The ideal test is to try projection=" * FROM SQLITE_MASTER; -- ". If you can get to the master table, you can get anywhere else (unless the programmer has some custom code ready to black list you out of having fun).
Failing this you could try on the 'selection' variable and try a union statement. (see my previous post for more details

This week has been spent looking at the other commands (insert,update,delete). The goal for the attacker is to change values in other tables in the .db file. The big issue here is the table to be queried is selected before your variables get included.

Inject into INSERT statements

insert into TABLENAME(field1,field2) values (val1,val2)
Here you can maybe control field1 & 2 and val1 & 2. The problem is that you can't jump tables. SQLite doesn't permit UNIONs or JOINs in anything other than select statements. You can use CASE to hide SELECT statments in the middle of this but that doesn't get you much in the way of altering data powers. You also can't use table.field in the query. Essentially you are stuck altering the data within that table.

It is therefore possible for SQL injection through inference of values being changed with CASE statements to read data from a table, but it's not possible to jump to and attack other tables.

 Inject into UPDATE or DELETE statements

UPDATE table SET (val1 = val2) WHERE condition
DELETE FROM table WHERE condition

Similarly the update query permits field names (val1), updated values (val2) and where clauses (condition), but no changing of the table name. The delete function is similarly limited.

I'm scratching my head finding a more useful attack vector that somehow nests more useful things inside statements. All comments are welcome. In the meantime, this should make for some useful reading:

No comments: