Contents
Requirements
You will need the following perl modules :
- LWP::UserAgent
- DBD::SQLite
- HTML::LinkExtractor
- LWP::Protocol::socks (for socks proxy support)
- Switch
And a proper Term::ReadLine package is definitely recommended (yet not mandatory)
You will probably also want to install sqlite3, the command line interface for SQLite 3.
Or, if you are on a debian system :
apt-get install libwww-perl libdbd-sqlite3-perl libhtml-linkextractor-perl libterm-readline-gnu-perl liblwp-protocol-socks-perl sqlite3 libswitch-perl
It also requires previous SQL injection knowledge, and.. well.. a brain helps.
How to use
When starting a new session (new target), the simplest way is to generate a default conf, using sqlsus --genconf targethost.conf, edit it the way you want, then : sqlsus targethost.conf
Only what differs from the default values are needed in the configuration file, this allows you to have a really tiny configuration file.
Note that package conf; is needed on top of your configuration file.
All the values specified in the configuration file will be overriden by the variables you can set in sqlsus using "set", provided that $allow_override == 1 (which is the default)
This behaviour allows you to adapt sqlsus to your target without the need to exit sqlsus, change the configuration file, fire up sqlsus again, etc...
To generate the configuration file reflecting your actual configuration, you can use genconf <filename> inside sqlsus.
Inband / Blind
Inband means that the answer will be seen via the same channel the injection took place (the result of the query will be in the HTML)
Blind means that the result cannot be directly read, and that we have to guess what it is.
To make both of them really fast, sqlsus uses some neat features, to address the fact that MySQL does not support stacked queries and that there was no SLEEP function before MySQL 5.0.12
On Inband mode, sqlsus will stack as much subqueries it can per query as long as it doesn't hit either max_subqueries or max_sendable.
On Blind mode, sqlsus will :
- match each item against a set of regex, to lower the character space to use to bruteforce the item.
- find the length of the item
- bruteforce each character with the character space found (or using default_range if none were)
Tasks are divided per thread (actually, process) :
- match RE + find length
- bruteforce char
sqlsus will take care that threads remain as busy as possible, and as long as it makes sense (avoid unneeded hits).
Note that in inband mode, it is generally a good idea to make the real query return nothing (append "AND 1=0" for example)
Commands
Inline help is available in sqlsus.
Type help or help <command>.
You can break commands using Ctrl-C. They may take some time to actually stop, so that you can have exploitable results when you break an overly long SELECT.
Configuration file
You can generate a configuration file with sqlsus defaults by using : sqlsus --genconf my.cfg
The resulting file has inline documentation.
SQLite backend
You can access the SQLite backend directly from the command line with SQLite3.
The queries and the associated table are stored in the table queries.
The real names of the columns are stored in the table tables.
databases structure in table databases, history in table history, privileges in table privileges, and variables in table (how surprising) variables.
To store queries results, sqlsus does not use real column names directly to avoid several possible issues, some of them being reserved words and quotes (eg: if you provide select NULL, sqlsus would have to create a column named NULL, which won't be allowed.). This behaviour also prevents sqlsus from being the target of SQL injection.
When you use clone, the resulting tables / columns, are actual real names, so you can "edit" the database with SQLite3 directly.
Under the hood
fetch-ahead
The idea of fetch-ahead is to get useful results as fast as possible.
Therefore, when the amount of data to be returned is not known, sqlsus will be fetching N results ahead, making use of the N user defined threads right after you press enter, rather than waiting for one thread to do a select count() and only then start using all the threads to fetch the data.
Also, since the user can break the select statement when he wants to, it makes more sense to have useful results rather than the number of expected results :)
Note that in blind mode, it is required to know the amount of data to fetch, so in this case, fetch-ahead only applies to get full results ordered, again to have useful information when a user breaks the command.
inband
In inband mode (when the result of the query will be in the HTML), if your query is likely to return more than one row, sqlsus will use as many subqueries it can use at a time (per query), staying under a configurable limit.
Therefore, it can grab up to thousands of records in just 1 server hit (depending on the available injection space) (cf inband demo)
Also, it obviously uses multithreading to speed things up.
Using "autoconf" commands, you can let sqlsus find the best values for maximizing the data returned per server hit.
blind
In blind mode, sqlsus makes the best use of the children forked so that they are as busy as possible, doing relevant tasks.
It does not slowly retrieve data one record at a time, which would be a big waste of time.
The simplified blind algorithm behaves this way (ex: a select query returning multiple rows of multiple columns) :
Spawn children
Give all available children one record to find the length of, and match a regular expression against.
The regular expressions to be matched are based on the most typical records found in a database (alpha_lower, alpha, hex, numeric...)
- Finding the length first avoids wasting server hits by bruteforcing non existent chars.
- Matching the item against some regular expression reduces A LOT the number of hits required by the binary search (around 30% less hits required for typical records).
- Make every available children bruteforce one char to find (ordered), from the pool of records we know the length+regex of.
- When a full record is found, store it, and assign a child to find the next record's length+regex [1] (the other children will still be in loop [2]).
- We don't search the length+regex of all the records once and for all at the beginning. This is (not) done to prioritize full rows grabbing, retrieved ordered. So that if the user wants to break the command, he will have as much usable results as possible.