# SELECT code_execution FROM * USING SQLite; **[research.checkpoint.com/2019/select-code_execution-from-using-sqlite/](https://research.checkpoint.com/2019/select-code_execution-from-using-sqlite/)** August 10, 2019 ### Gaining code execution using a malicious SQLite database **Research By: Omer Gull** ## tl;dr August 10, 2019 SQLite is one of the most deployed software in the world. However, from a security perspective, it has only been examined through the lens of WebSQL and browser exploitation. We believe that this is just the tip of the iceberg. In our long term research, we experimented with the exploitation of memory corruption issues within SQLite without relying on any environment other than the SQL language. Using our innovative techniques of Query Hijacking and Query Oriented Programming, we proved it is possible to reliably exploit memory corruptions issues in the SQLite engine. We demonstrate these techniques a couple of real-world scenarios: pwning a password stealer backend server, and achieving iOS persistency with higher privileges. ----- We hope that by releasing our research and methodology, the security research community will be inspired to continue to examine SQLite in the countless scenarios where it is available. Given the fact that SQLite is practically built-in to every major OS, desktop or mobile, the landscape and opportunities are endless. Furthermore, many of the primitives presented here are not exclusive to SQLite and can be ported to other SQL engines. Welcome to the brave new world of using the familiar Structured Query Language for exploitation primitives. ## Motivation [This research started when omriher and I were looking at the leaked source code of some](https://twitter.com/omriher?lang=en) [notorious password stealers. While there are plenty of password stealers out there (Azorult,](https://malpedia.caad.fkie.fraunhofer.de/details/win.azorult) [Loki Bot, and](https://securelist.com/loki-bot-stealing-corporate-passwords/87595/) [Pony to name a few), their modus operandi is mostly the same:](https://www.acunetix.com/blog/articles/pony-malware-credential-theft/) A computer gets infected, and the malware either captures credentials as they are used or collects stored credentials maintained by various clients. It is not uncommon for client software to use SQLite databases for such purposes. After the malware collects these SQLite files, it sends them to its C2 server where they are parsed using PHP and stored in a collective database containing all of the stolen credentials. Skimming through the leaked source code of such password stealers, we started speculating about the attack surface described above. Can we leverage the load and query of an untrusted database to our advantage? Such capabilities could have much bigger implications in countless scenarios, as SQLite is one of the most widely deployed pieces of software out there. A surprisingly complex code base, available in almost any device imaginable. is all the motivation we needed, and so our journey began. ## SQLite Intro The chances are high that you are currently using SQLite, even if you are unaware of it. To quote its authors: _SQLite is a C-language library that implements a small, fast, self-contained, high-reliability,_ _full-featured, SQL database engine. SQLite is the most used database engine in the world._ _SQLite is built into all mobile phones and most computers and comes bundled inside_ _countless other applications that people use every day._ Unlike most other SQL databases, SQLite does not have a separate server process. SQLite reads and writes directly to ordinary disk files. A complete SQL database with multiple tables, indices, triggers, and views is contained within a single disk file. ### Attack Surface ----- The following snippet is a fairly generic example of a password stealer backend. Given the fact that we control the database and its content, the attack surface available to us can be divided into two parts: The load and initial parsing of our database, and the SELECT query performed against it. The initial loading done by sqlite3_open is actually a very limited surface; it is basically a lot [of setup and configuration code for opening the database. Our surface is mainly the header](https://www.sqlite.org/fileformat.html#the_database_header) parsing which is battle-tested against AFL. Things get more interesting as we start querying the database. Using SQLite authors’ words: _“The SELECT statement is the most complicated command in the SQL language.”_ Although we have no control over the query itself (as it is hardcoded in our target), studying the SELECT process carefully will prove beneficial in our quest for exploitation. As SQLite3 is a virtual machine, every SQL statement must first be compiled into a byte[code program using one of the sqlite3_prepare* routines.](https://www.sqlite.org/c3ref/prepare.html) Among other operations, the prepare function walks and expands all SELECT subqueries. ----- Part of this process is verifying that all relevant objects (like tables or views) actually exist and locating them in the master schema. ### sqlite_master and DDL Every SQLite database has a `sqlite_master table that defines the schema for the` database and all of its objects (such as tables, views, indices, etc.). The sqlite_master table is defined as: The part that is of special interest to us is the sql column. This field is the DDL (Data Definition Language) used to describe the object. In a sense, the DDL commands are similar to C header files. DDL commands are used to define the structure, names, and types of the data containers within a database, just as a header file typically defines type definitions, structures, classes, and other data structures. These DDL statements actually appear in plain-text if we inspect the database file: ----- During the query preparation, sqlite3LocateTable() attempts to find the in-memory structure that describes the table we are interested in querying. sqlite3LocateTable() reads the schema available in sqlite_master, and if this is the first time doing it, it also has a callback for every result that verifies the DDL statement is valid and build the necessary internal data structures that describe the object in question. ## DDL Patching Learning about this preparation process, we asked, can we simply replace the DDL that appears in plain-text within the file? If we could inject our own SQL to the file perhaps we can affect its behaviour. Based on the code snippet above, it seems that DDL statements must begin with “create “. With this limitation in mind, we needed to assess our surface. Checking SQLite’s documentation revealed that these are the possible objects we can ----- create: The CREATE VIEW command gave us an interesting idea. To put it very simply, VIEWs are just pre-packaged SELECT statements. If we replace the table expected by the target software with a compatible VIEW, interesting opportunities reveal themselves. ### Hijack Any Query Imagine the following scenario: The original database has a single TABLE called dummy that is defined as: The target software queries it with the following: We can actually hijack this query if we craft dummy as a VIEW: ----- This “trap” VIEW enables us to hijack the query – meaning we generate a completely new query that we totally control. This nuance greatly expands our attack surface, from the very minimal parsing of the header and an uncontrollable query performed by the loading software, to the point where we can now interact with vast parts of the SQLite interpreter by patching the DDL and creating our own views with sub-queries. Now that we can interact with the SQLite interpreter, our next question was what exploitation primitives are built into SQLite? Does it allow any system commands, reading from or writing to the filesystem? As we are not the first to notice the huge SQLite potential from an exploitation perspective, it makes sense to review prior work done in the field. We started from the very basics. ### SQL Injections As researchers, it’s hard for us to even spell SQL without the “i”, so it seems like a reasonable place to start. After all, we want to familiarize ourselves with the internal primitives offered by SQLite. Are there any system commands? Can we load arbitrary libraries? [It seems that the most straightforward trick involves attaching a new database file and writing](https://atta.cked.me/home/sqlite3injectioncheatsheet) to it using something along the lines of: ----- We attach a new database, create a single table and insert a single line of text. The new database then creates a new file (as databases are files in SQLite) with our web shell inside it. The very forgiving nature of the PHP interpreter parses our database until it reaches the PHP open tag of “