In the past years credential theft has become a common theme among web sites. They all stem from a compromise of the web or application server or unrelated other infrastructure. Once access to the file system of the database server is achieved or the database can be accessed using the application's credentials, the stored secret credentials the user configured, and potentially shares with other sites, can be retrieved from the database. As soon as the intrusion is detected, responsible web site owners usually notify the users about the breach and ask them to change their credentials to the website and warn about credentials reuse. Having a breach is obviously bad publicity and evidently has negative consequences.
However, at least one of the attack avenues can be sealed off: Retrieving of the secret data from the database using the credentials of the web application
If all operations (checking, setting the password) on the secret data (credentials) is delegated to the database server, which has access to it regardless, because it stores them, and the application itself can not read them anymore, they can not be stolen through that vector anymore.
This blog post describes a native technology that allows web sites to delegate the password authentication to the SQL database.
- mysql/mariadb SQL functions and sql security setting
- mysql/mariadb UDFs
- Botan crypto lib
The two technologies that fundamentally enable this solution are the ability of mysql/mariadb to adopt a suid like calling mechanism for user defined functions (UDF) and the ability to load dynamic libraries and call code inside them from SQL.
Access to the functions and tables is restricted using normal SQL ACLs (grants). The necessary primitives for the hashing, salting and constant time compare is provided through a custom library that is loaded by mysql/mariadb. It links to the botan crypto library. The actual implementation of the password checking and setting, user adding and deletion, email address adding and so on is implemented in native SQL.
A critical limitation of the way UDF support is implemented in mysql/mariadb prevents the usage of any library that requires any nonreoccuring initialization and/or deinitialization, because there is no central per-lib initialization hook or similiar that could be used for the purpose of initialization. So the library must not need any initialization. Due to the nature of C and how shared objects work, it is not possible to handle several initializations of the same library. It would be possible if there was some way to persist the information that the lib was initialized and it could be distinguished from the uninitialized state the memory is in in the beginning of the execution of the code.
This problem effectively restricts the choice of crypto library to anything that does not support any hardware acceleration because those devices require central coordination by a lib and thus a shared, initialized structure.
I elected to use botan for the implementation of the cryptography. I used the latest version, which is 2.10, because it offers a central header through which its functions can be easily called. In order to support platforms without that version of the library, either botan has to be statically linked into the custom library or the relevant code has to be moved within the library.
I still want to implement support for doing the mschap(v2) handshake between a client and the SQL database, which requires DES in ECB mode and MD4. Those functions are sadly not provided by botan, so they require me to implement them by myself or copy code.