BugTraq
Oracle PL/SQL Fuzzing Tool Dec 06 2006 01:18PM
Joxean Koret (joxeankoret yahoo es)
Hi to all,

In the past I wrote a python tool to fuzz PL/SQL procedures, functions
and packages. With this wonderfull tool I found many vulnerabilities,
many crashes and many-many interesting issues.

I decided to release it to the public because it's a part of an Oracle
specific Vulnerability Assesment Tool I will release when it's
completely finished. It will be licensed under the GPL.

To use the attached python tool you will need a valid Oracle database
account with, at least, the CREATE SESSION privilege granted. You will
need to adapt it to your feets to fuzz a database under your control. At
least: username, password, Oracle SID and IP address.

It only fuzzes 'VARCHAR2', 'RAW', 'NCHAR', 'BINARY_INTEGER',
'BINARY_FLOAT', 'CHAR', 'NVARCHAR2', 'NUMBER', 'FLOAT' and 'LONG RAW'
datatypes, at the moment, but you can easily adapt it to fuzz other
Oracle datatypes, even user defined.

Well, if you find it interesting or if you have any question about, any
criticism, etc... Don't heasitate to contact me. Take fun.

---
Joxean Koret

-----------------------------------
Agian, agian, egün batez
jeikiko dira egiazko Ziberotarrak,
egiazko eüskaldünak,
tirano arrotzen hiltzeko
eta gure aiten aitek ützi daikien
lurraren popüliari erremetitzeko.
-----------------------------------
#!/usr/bin/python

"""

Oracle Database PL/SQL Fuzzing Tool

Copyright (c) 2005, 2006 Joxean Koret, joxeankoret [at] yahoo.es

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; version 2

of the License.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""

import sys

import cx_Oracle

global connection

funnydata = ("TEST", "SYS", "XMLREF", '" || XMLREF() || "', 'TEST" A A ', "'", '"', "A"*30, "A"*100, "A"*128,"A"*256,"A"*512,"A"*1024,

"A"*2048,"A"*3000,"A"*4000,"A"*5000,"A"*6000,"A"*7000,"A"*8000,"A"*10000
,"A"*15000,"A"*20000,"A"*25000,

"A"*30000,"A"*32767, -1, -2, 0, 1, 2, 2147483647, -2147483647, 2147483648, -2147483648,

"ROWID", "PRIMARY KEY", "%s%s%s%s%s%s%s", "%x%x%x%x%x%x", "%d%d%d%d%d%d",

"GRANT DBA TO TEST", "GRANT DBA TO PUBLIC", "SELECT * FROM DBA_USERS",

"' OR '1'='1", "AA' or ""TEST"".""XMLREF"" ","V1", "TEST.V1", '"TEST"."V1"',

None)

def fuzzData(data, index):

global connection

for x in funnydata:

try:

if type(x) is int:

print "Data is number",x

else:

print "Data is " + str(x)[0:30] + " of length " + str(len(str(x)))

varList = []

for var in range(index):

varList.append(x)

cur = connection.cursor()

cur.execute(data, varList)

except:

error = str(sys.exc_info()[1])

if error.upper().find("ORA-00933") > -1 or error.upper().find("ORA-01756:") > -1 or error.upper().find("ORA-00923:") > -1:

print "*** POSSIBLE SQL INJECTION FOUND ***"

elif error.upper().find("ORA-03113") > -1:

if len(str(x)) > 50:

print "*** POSSIBLE BUFFER OVERFLOW ***"

else:

print "*** INSTANCE CRASHED ***"

print "Reconnecting ... "

connect()

elif error.upper().find("ORA-00600") > -1:

print "*** INTERNAL ERROR ***"

elif error.upper().find("PLS-00306:") > -1:

print "Currently unfuzzable :("

continue

elif error.upper().find("ORA-03114") > -1:

print "We are not connected :?"

connect()

print error

def connect():

global connection

link = "test/test@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.1
68.1.10)(PORT=1521)))"

link += "(CONNECT_DATA=(SERVICE_NAME=orcl)))"

connection = cx_Oracle.connect(link)

connection.rollback()

connection.commit()

def isFunc(data, index, cursorData):

global connection

try:

varList = []

data = """BEGIN

"""+ data + """("""

index = 0

for x in cursorData:

index += 1

if index == 1:

data += str(x[1]) + "=>:" + str(index)

else:

data += "," + str(x[1]) + "=>:" + str(index)

data += """);

end;"""

for var in range(index):

varList.append(None)

cur = connection.cursor()

cur.execute(data, varList)

return 0

except:

error = str(sys.exc_info()[1])

if error.upper().find("PLS-00221")> -1:

return 1

else:

return 0

def die(msg):

print msg

sys.exit(0)

def main():

global connection

fuzzPackages = """

select distinct owner "Owner",

package_name "Package",

package_name "Package",

package_name "Package",

object_name "Program_Unit"

from sys.all_arguments x

where argument_name is not null

and not exists (select 1 from sys.all_arguments y

where x.owner = y.owner

and x.package_name = y.owner

and x.object_name = y.object_name

and x.data_level = y.data_level

and y.data_type not in ('VARCHAR2', 'RAW', 'NCHAR', 'BINARY_INTEGER', 'BINARY_FLOAT',

'CHAR', 'NVARCHAR2', 'NUMBER', 'FLOAT', 'LONG RAW')

and rownum = 1)

order by owner, package_name, object_name

"""

packageProcedures = """

select position "Position",

argument_name "Argument",

data_type "Data type",

initcap(in_out) "In_Out",

owner sdev_link_owner,

package_name sdev_link_name,

'PACKAGE' sdev_link_type

from sys.all_arguments

where argument_name is not null

and owner = :1

and (:2 is null or

instr(upper(object_name),upper(:3)) > 0 or

instr(upper(package_name),upper(:4)) > 0 )

and object_name = :5

and data_type in ('VARCHAR2', 'RAW', 'NCHAR', 'BINARY_INTEGER', 'BINARY_FLOAT',

'CHAR', 'NVARCHAR2', 'NUMBER', 'FLOAT', 'LONG RAW')

order by owner, package_name, object_name, position

"""

connect()

bStart = False

try:

cursor = connection.cursor()

cursor.execute(fuzzPackages)

result = """

BEGIN

"""

pkgName = ""

func = 0

print "Running first query. It may take a long while ... "

totalProcs = 0

for pkgData in cursor.fetchall():

totalProcs += 1

if not pkgData[1] is None:

pkgName = pkgData[0] + "." + pkgData[1] + "." + pkgData[4]

else:

pkgName = pkgData[0] + "." + pkgData[4]

procCursor = connection.cursor()

procCursor.execute(packageProcedures, pkgData)

procCursorData = procCursor.fetchall()

func = isFunc(pkgName, len(procCursorData), procCursorData)

if int(func) == 0:

data = """BEGIN

""" + pkgName + """("""

else:

data = """SELECT """ + pkgName + """("""

index = 0

prevX = None

for x in procCursorData:

if x == prevX:

continue

prevX = x

index += 1

if index == 1:

if func == 0:

data += str(x[1]) + "=>:" + str(index)

else:

data += ":" + str(index)

else:

if func == 0:

data += "," + str(x[1]) + "=>:" + str(index)

else:

data += ", :" + str(index)

if func == 0:

data += """);

end;"""

else:

data += """) from dual """

print "----------"

print data

print "----------"

fuzzData(data, index)

connection.close()

except Exception, e:

print "Error",e

print "While fuzzing index",totalProcs,"relative to",pkgName

raise e

print

print "Fuzzed",totalProcs,"procedure(s) and function(s)."

print "Done."

if __name__ == "__main__":

main()

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBFdsM/U6rFMEYDrlERAnnEAJ9zDwW47wE6VvOcIM97eyIZuNHx5gCgjVDB
wpIXnOFaBNIAmCajSZ1MWc8=
=yFUm
-----END PGP SIGNATURE-----

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus