release 0.4

Requirements

You will need the following perl modules :

  • LWP::UserAgent
  • DBD::SQLite
  • WWW::Mechanize

And a proper Term::ReadLine package is definitely recommended (yet not mandatory)

Or, if you are on a debian system :

apt-get install libwww-perl libdbd-sqlite3-perl libwww-mechanize-perl libterm-readline-gnu-perl

You will probably also want to install sqlite3, the command line interface for SQLite 3.

How to use

When starting a new session (new target), the simplest way is to copy conf.pm to targethost.conf.pm, edit it the way you want, then : ./sqlsus -c targethost.conf.pm

If you don't want to run sqlsus interactively, use the -i switch, i.e. : ./sqlsus -c targetconf.pm -i 'select version()'

Note that conf.pm will be sourced first, then whatever configuration file you specified.

This allows you to have a tiny configuration file only overriding the values different from the default ones.

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

You can break a command by using Ctrl+C.

start

In inband mode, this command will find the columns for UNION. That means that, up to a configurable value, sqlsus will inject a query with one more item at each iteration, using sql's HEX() function, and looking at the HTML for the hex values, to be sure that it has been parsed by the SQL server.

In all modes, it will fill %target, which is a hash containing useful variables about the target (by default: current_user(), database() and version())

use

alias to set database, allows you to change the current database to another one and still be able to use all the commands transparently.

get

If the target database is MySQL 5 or newer, and you can read from the system tables, then this command will help you fetch the database structure :

tables

Get the names of the tables for the current database

columns [table_name]

Get the names of the columns [for the specific table]

count [table_name]

For (the specified|each) table that show db will display, get count(*) to know how many items are inside (useful to detect interesting tables).

db

Same as get tables + get columns + get count.

privs

Get the privileges for the user.

databases

Get the names of all the databases.

brute

If the target database is older than MySQL 5, then this command will help you bruteforce the database structure :

tables

Bruteforce the name of the tables, prefix with table_prefix.

sqlsus will take its input from a dictionary, defined in brute_table_dict, and depending on the configuration (uc_first and uc_all) will, for each item tried, try the uppercase and/or uppercase_first version of the word.

If the dictionary attack fails, it will be replaced by an exhaustive bruteforcer (chars a to z).

columns

same as for tables, but only try one case per item, since MySQL discards the case for the columns.

show

This command shows items already grabbed through get, brute or start :

target

Show the target variables (by default : user / database / version)

privs

Show the privileges associated with the user

db

Show the db (with tables / columns / count if available)

all

Same as show target + privs + db

tables

Show the tables of the target database

columns [table_name]

Show the columns of the target database [for the specific table]

describe is an alias to show columns.

set

Allows you to set some variables on the fly, such as document_root (cf takeover demo)

These variables override what is inside the configuration file.

usage: set variable value or set variable "value"

select

Just type a normal SQL SELECT query, and sqlsus will cut it, re-arrange it.

In inband mode, sqlsus will use as many subqueries it can fit in max_sendable, limited to max_subqueries per query.

You can see how the queries are injected by turning debug mode on : set debug 1

The result will be printed in a mysql shell like box, and stored into the session database.

find

On MySQL >= 5, find the tables that have a certain column. You can use SQL wildcards.

eg: find "pass%" will find all the tables in the target database that have at least one column starting with pass

eval

eval perl code from within sqlsus, this allows you to play with the (dirty) internals of sqlsus.

!

execute a command on the local system

download

If you have the FILE privilege, you can download any world readable file, via SELECT LOAD_FILE.

download is just a simpler way to do that, since it removes the unneeded HTML and stores the file in a local tree, starting at files_path

eg: download /etc/passwd will display the remote file /etc/passwd and store it in your local system at $PWD/$server/$files_path/etc/passwd

upload

If nothing has been done yet, depending on the configuration (upload_directories set or not), sqlsus will crawl the website looking for directories, and try to upoad the PHP uploader on each one (smartly).

If the tiny PHP uploader has been uploaded (via SELECT INTO OUTFILE), then sqlsus will upload the requested file via POST through it (be aware of possible POST size restrictions).

If the target file has a relative path (eg: upload shell/backdoor.php backdoor.php), sqlsus will output the URL to access the file.

clone

usage: clone [table [column,column,..]] clone current database [or just a table [and just some columns]] to a local SQLite database

It can be resumed over sessions, it will start after the last fetched row, up to count(*).

backdoor

You will find a PHP backdoor ready to use in shell/backdoor.php.

To use it, upload it first of course, and then use : ./control_backdoor URL_TO_BACKDOOR [sql credentials]

See the takeover demo for an example on how to use it.

It is really simple and straight forward, 3 modes : exec, php, sql (eg: use mode php to switch to the php mode)

  • exec : try to execute via any available system()-like function the command (won't work in safe_mode)
  • php : eval php code
  • sql : inject SQL queries (SELECT, UPDATE, CREATE, DROP...) in a mysql-like shell.

You can use a file as input, by using < file inside the shell.

Configuration file

Generic options

url_start

Start of the URL : what is before the injection point.

Note that sqlsus will inject this way : url_start . injection . url_end

So if you need a space between the injection point and the start / stop of the URL, put it, no space will be created for you, in order to shorten the query as much as possible.

Note that you may want to add a AND 1=0 at the end of url_start, so that the original query returns nothing, which is usually a good idea when it comes to UNION.

url_end

End of the URL : what is after the injection point.

Again, if needed, prepend a space.

user_agent

The user agent to use for HTTP queries

eg: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"

blind

If the injection is blind, set this variable to 1, and set string_to_match accordingly

string_to_match

In blind mode, string to be found in the HTML when the statement is true

Example : What will be seen in the HTML for http://host/script?id=1 AND 1=1 but not for http://host/script?id=1 AND 1=0

post

Set to 1 if you want to use POST instead of GET.

debug

Set to 1 if you want debug messages, such as when sqlsus sends a request to the server.

null_substitute

Character (not string !) to display when the data is NULL.

hex_encode_strings

Set to 1 to encode strings in their hex equivalent.

Ex: "sqlsus" will become 0x73716c737573

processes

Set to the number of children sqlsus should spawn (only used in blind injection)

http_proxy

Set to the URL of the HTTP proxy you want to use, or leave blank if you don't need any.

cred_realm, cred_user, cred_password

realm, username and password required on a simple HTTP auth.

max_sendable

Maximum sendable chars to the server, usually 4096 for GET, and way more for POST.

max_subqueries

Maximum number of subqueries per query, to disable the usage of subqueries, set it to 0

convert_spaces

Convert spaces to /**/

sleep_after_hit

Number of seconds to sleep after each hit to the web server. Set it to 0 to disable.

This is a simple sleep(), after each url fetching.

Note that you can use floating values, because sqlsus uses Time::HiRes

Data

datapath

Set to the directory where session data (including log file) should go.

These files will be written under ./server/$datapath

filespath

Set to the directory where the files downloaded via download should go.

These files will be written under ./server/$filespath

Inband mode

max_select_cols

Maximum number of columns to try in the union statement before exiting.

columns

columns usable for injection using UNION. This is a perl array.

The first value that is 1 in the array will be used as the injection point, the others will be used as is.

Unless this variable is set, sqlsus will auto-detect the suitable number of columns as well as wish can be used for injection.

union_select

string to use for UNION, because sometimes UNION ALL SELECT is not what you want.

Blind mode

verbose_blind

Set to 1 to display the progress of data fecthing.

default_range

Default character space to use when bruteforcing an item, if no regex matched the item.

The characters are ASCII numbers separated by a comma.

regex_rlike

regexs to test against each item retrieved on a blind injection, and the corresponding ASCII values. They will be tried in order, and the values must be sorted.

max_length

Maximum length of an item above which sqlsus will stop guessing.

Takeover

document_root

Set it to the document root of the target web server, so that sqlsus knows where to upload the PHP uploader.

upload_directories

Set it to the directories that should be tried to upload the PHP uploader, we need a writable for everybody directory.

Leave the array empty to let sqlsus crawl the website for candidate directories, and set max_depth.

crawler_depth

Maximum depth sqlsus should go to, when crawling the website.

uploader

If the PHP uploader has already been uploaded, set this variable to the URL.

Note you shouldn't need to set this variable here, since it will be remembered across sessions.

Core

target_at_start

Array of target keys to get when using start

You may want to reduce it to database only when you are in blind mode, to limit the number of hits for mandatory information.

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.)

When you use clone, the resulting tables / columns, are actual real names, so you can "edit" the database with SQLite3 directly.

Known bugs / limitations

sqlsus won't work on binary data, this is because it focuses on shortening the query as much as possible, and as a result only uses two chars (\x05 and \x07) as separators. A binary mode switch will be added in a future release.