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