[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Full-disclosure] PostgreSQL and Informix Function Fuzzing Tool



Hi to all!

After the Oracle PL/SQL fuzzing tool I decided to write the same for
PostgreSQL and Informix. 

Attached goes the 2 function/stored procedure fuzzers I wrote. The
unique "interesting" thinks I found were in PostgreSQL but, as the
PostgreSQL Team say, "they are more annoyances than something else". 

Anyway, attached goes POCs for PostgreSQL which makes postmaster service
consume 100% CPU resources and the tools.

---
Joxean Koret

#!/usr/bin/python

"""
Informix Database Functions 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 informixdb

connection = None

funnydata = ("TEST", "INFORMIX", "''", '"', "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,
                        "A"*50000, "A"*100000,
                        "OID", "%s%s%s%s%s%s%s", "%x%x%x%x%x%x", 
"%d%d%d%d%d%d", "%f%f%f%f%f%f",
                        "A"*8000 + "\?", "./", "../../../../../../../../tmp", 
"`ls -lga`",
                        "array['a']",
                        "array['A'" + ",'A'"*5000 + "]", "array['" + "A"*5000 + 
"']",
                        "\x00", None)

def fuzzFunction(name, args, proc):

    global funnydata
    global connection

    try:
            data = "SELECT FIRST 1 " + name + " ( "

            for i in range(args):
                if i == 0:
                    data += "?"
                else:
                    data += ", ?"

            data += ") from sysprocedures;"
            
            print data

            for funny in funnydata:

                if type(funny) is int:
                    print "Number", funny
                else:
                    print "String",len(str(funny))

                params = ()

                for i in range(args):
                    params += (funny, )

                cur = connection.cursor()

                try:
                    if proc == "f":
                        try:
                            cur.execute(data, params)
                        except:
                            error = str(sys.exc_info()[1])
                            
                            if error.lower().find('can not be resolved.') > -1:
                                print "Error running as function, trying as 
procedure"
                                cur.callproc(name, params)
                            else:
                                raise
                    else:
                        cur.callproc(name, params)

                except:
                    print "From server.",str(sys.exc_info()[1])[0:80]
    except KeyboardInterrupt:
        print "Aborted."
        sys.exit(0)
    except:
        print "Exception:",sys.exc_info()[1]
        #sys.exit(0)

def connect():
    global connection
    
    connection = informixdb.connect("testdb@ifxserver", user="test", 
password="test")

def main():
    connect()
    cur = connection.cursor()
    cur.execute("""
              select distinct procname, numargs, isproc
                     from sysprocedures
            where numargs > 0 
                    order by procname""")
    
    i = 0

    for proName in cur.fetchall():
        i += 1

        print "Fuzzing",proName[0],"with",proName[1],"argument(s)"

        try:
            fuzzFunction(proName[0], proName[1], proName[2])
        except:
            print "Error while fuzzing",proName[0],"(Index",i,")"
            raise

    print
    print "Fuzzed a total of",i,"functions(s)"
    print "Done."

if __name__ == "__main__":
    main()
#!/usr/bin/python

"""
PostgreSQL Database Functions 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
from pyPgSQL import PgSQL

connection = None

funnydata = ("TEST", "POSTGRES", "''", '"', "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,
                        "OID", "%s%s%s%s%s%s%s", "%x%x%x%x%x%x", 
"%d%d%d%d%d%d", "%f%f%f%f%f%f",
                        "A"*8000 + "\?", "./", "../../../../../../../../tmp", 
"`ls -lga`",
                        "array['a']",
                        "array['A'" + ",'A'"*5000 + "]", "array['" + "A"*5000 + 
"']",
                        "chr(0)")

def fuzzFunction(name, args):

    global funnydata
    global connection

    try:
            data = "SELECT " + name + "("

            for i in range(args):
                if i == 0:
                    data += "'%s'"
                else:
                    data += ", '%s'"

            data += ");"
            for funny in funnydata:

                if type(funny) is int:
                    print "Number", funny
                else:
                    print "String",len(str(funny))

                params = ()

                for i in range(args):
                    params += (funny, )

                connection.rollback()
                cur = connection.cursor()
                curData = data % (params)

                try:
                    if curData.find("array[") > -1:
                        curData = curData.replace("'array[", "array[")
                        curData = curData.replace("]'", "]")
                    elif curData.find("chr(0)") > -1:
                        curData = curData.replace("'chr", "chr")
                        curData = curData.replace("0)'", "0)")
                        print curData

                    cur.execute(curData)
                except:
                    print "From server.",str(sys.exc_info()[1])[0:80]
    except KeyboardInterrupt:
        print "Aborted."
        sys.exit(0)
    except:
        print "Exception:",sys.exc_info()[1]
        #sys.exit(0)

def connect():
    global connection
    
    connection = PgSQL.connect(host="localhost", database="testdb", 
client_encoding="utf-8", unicode_results=1,
                                                        user="test")

def main():
    connect()
    cur = connection.cursor()
    cur.execute("""
              select proname, pronargs 
                     from pg_proc 
            where pronargs > 0 
              and proName not in ('substring', 'bpcharicregexeq', 
'bpcharicregexne', 'bpcharregexeq', 
                                                    'bpcharregexne', 
'nameicregexeq', 'nameicregexne', 'numeric_fac',
                                                    'numeric_power', 
'regexnesel', 'regexp_replace', 'texticnlike',
                                                    'texticregexeq', 
'texticregexne', 'texticregexeq', 'factorial', 'textregexq','textregexeq', 
'textregexne')
                    order by proname""")
    
    i = 0

    for proName in cur.fetchall():
        i += 1

        print proName[0]
        continue
        print "Fuzzing",proName[0],"with",proName[1],"argument(s)"
        try:
            fuzzFunction(proName[0], proName[1])
        except:
            print "Error while fuzzing",proName[0],"(Index",i,")"
            raise

    print
    print "Fuzzed a total of",i,"functions(s)"
    print "Done."

if __name__ == "__main__":
    main()

Attachment: test1.sh
Description: application/shellscript

Attachment: test2.sh
Description: application/shellscript

Attachment: test3.sh
Description: application/shellscript

Attachment: test4.sh
Description: application/shellscript

Attachment: signature.asc
Description: Esta parte del mensaje =?iso-8859-1?q?est=E1?= firmada digitalmente

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/