On Thursday, 13 April, 2017 06:14, Matthias-Christian Ott <[email protected]> 
wrote:

> I'm unsure what the threat and security model of SQLite's authorizer
> callback is. I think it would only be an effective authorization
> mechanism if the attacker was able to only execute SQL statements on a
> database and the database was otherwise not accessible to the attacker.
> So I'm not sure whether the following behaviour should be seen as a
> vulnerability. Nonetheless, I wanted to point out SQLite's behaviour and
> document it.
 
> One of the parameters of the authorizer is the name of the database of
> the operation that is to be authorized. The documentation gives you the
> impression that "main" and "temp" are two reserved database names and
> cannot be changed. However, the name of the main database can be changed
> by sqlite3_db_config. So if the name of the main database is relevant to
> the authorizer, it must be impossible to change it through
> sqlite3_db_config (in the context of the application). The following
> code demonstrates the "problem":
 
> #include <assert.h>
> #include <stddef.h>
> #include <string.h>
> #include <sqlite3.h>
> 
> int auth(void *p, int op, const char *name1, const char *name2,
>        const char *dbname, const char *caller)
> {
>     return dbname != NULL && strcmp(dbname, "main") == 0 ?
>         SQLITE_DENY : SQLITE_OK;
> }

The implementation above is what is called "default permit".  This means that 
everything is permitted except that which has been defined by enumeration to be 
specifically denied.  This is the model used, for example, by most Antivirus 
programs.  It requires a complete enumeration of all possible badness in order 
to work and anything that is not specifically enumerated (such as a new malware 
variant) cannot be denied until it is added to the enumeration.

The proper model to use is "default deny", in which case everything is denied 
except for those things which are by enumeration permitted.  This is how most 
Discretionary Access Control Systems work (Login, Firewalls, etc).  That means 
that you cannot bypass the denial by becoming something unanticipated.  
Whitelisting software, for example, works this way too.

It is possible to use a "hybrid" model.  For example, you would check first to 
ensure that the database name is one of the ones that you are enumerating.  It 
not, then deny.  You can then, secure in the knowledge that the remainder of 
your authorization code is now limited only "enumerated" possibilities, so that 
if someone changes the database name to something unexpected the default is to 
deny.

However, in the case of SQLite (and many other authorization systems such as 
most DRM and copy protection), it is simply sufficient to use software that 
does not implement the authorizer in order to bypass it.  So in the case of 
SQLite just using the standard shell compiled without authorization hooks in 
place is sufficient to do what you will to the database (barring some other 
outer layer of protection limiting you to using only one specific set of code 
containing the authorizer functions to access the database file, such as 
application level encryption with the key being application specific).

The original Lotus 123 version 1a, for example, implemented a call to its 
authorizer (to make sure it was running from the original diskette) early in 
the startup code.  You simply replaced the machine code of the call with an XOR 
A INC A NOP NOP and the protection was bypassed entirely.





_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to