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