SQL Inject


SUBMITTED BY: XGrats

DATE: Sept. 30, 2023, 7:37 a.m.

FORMAT: Text only

SIZE: 7.7 kB

HITS: 279

  1. #!/usr/bin/env python
  2. ####################################################################################
  3. #
  4. # sqlinject-finder.py
  5. #
  6. # Author: XGrats
  7. # Date : 12/02/2010
  8. # Description: Simple python script that parses through a pcap and looks at the
  9. # GET and POST request data for suspicious and possible SQL injects.
  10. #
  11. ####################################################################################
  12. import dpkt, re, urllib, sys, getopt
  13. tab = False
  14. #removes inline comments that can sometimes be used for obfuscating the sql
  15. def removeComments(val):
  16. while True:
  17. index = val.find("/*")
  18. index2 = val.find("*/")
  19. if index != -1 and index2 != -1:
  20. #looks like there is some type of SQL obfuscation, let's remove the comments
  21. remove = val[index:index2+2]
  22. val = val.replace(remove, "")
  23. else:
  24. break
  25. return val
  26. #checks for common sql injection tactics using all the variables from post or get data
  27. def analyzeRequest(vals, sIP, page, frameno):
  28. var = vals[0] #the variable, i.e. in id=1, the var is id
  29. val = vals[1] #the value, i.e. in id=1, the val is 1
  30. val = val.decode('ascii') #not sure if this is really doing anything, but we need to deal with non ascii characters for analysis
  31. val = urllib.unquote(val) #removes url encodings like %20 for space, etc
  32. val = val.replace("+", " ") #sometimes in urls, instead of a space you can have a + . So, we want to remove those for analysis
  33. #print val
  34. display = [False, sIP, page, var, val]
  35. ##### Look for obfuscation techniques ######
  36. index = val.find("/*")
  37. if index != -1:
  38. display[0] = True
  39. display.append("Might be attempting to obfuscate a SQL statement with a comment")
  40. val = removeComments(val)
  41. ##### Look for commenting out the end of a MSSQL statement ######
  42. index = val.rfind("--")
  43. if index != -1:
  44. display[0] = True
  45. display.append("Might be attempting to end a SQL statement by commenting out the remaining statement")
  46. ##### Look for commenting out the end of a MySQL statement #####
  47. index = val.rfind("#")
  48. if index != -1:
  49. display[0] = True
  50. display.append("Might be attempting to end a SQL statement by commenting out the remaining statement")
  51. ##### Look for common SQL syntax in the values of a param #####
  52. sqlvals = ("cast(", "declare ", "select ", "union ", "varchar", "set(", "create ", " or ", " NULL,", " concat(")
  53. for sql in sqlvals:
  54. index = val.lower().find(sql)
  55. if index != -1:
  56. display[0] = True
  57. display.append("Possible use of SQL syntax in variable")
  58. break
  59. if display[0] == True:
  60. if tab:
  61. line = str(display[1]) + "\t" + str(display[2]) + "\t" + str(display[3]) + "=" + str(display[4]) + "\t" + str(frameno)
  62. for i in range(len(display)-5):
  63. line = line + "\t" + str(display[i+5])
  64. print line
  65. else:
  66. print "Source : " + str(display[1])
  67. print "Page : " + str(display[2])
  68. print "Value : " + str(display[3]) + "=" + str(display[4])
  69. print "Frame : " + str(frameno)
  70. for i in range(len(display)-5):
  71. print "Reason : " + str(display[i+5])
  72. print ""
  73. def octetIP(sIP):
  74. ip = ""
  75. for s in sIP:
  76. ip = ip + str(ord(s)) + "."
  77. return ip[:-1]
  78. #reads the pcap file and parses out get and post requests for analysis
  79. def parsepcap(filename):
  80. try:
  81. f = open(filename, 'rb')
  82. except:
  83. print "Error reading file. Please make sure the file exists"
  84. sys.exit()
  85. try:
  86. pcap = dpkt.pcap.Reader(f)
  87. except:
  88. print "Error reading file. Please make sure the file is a valid pcap file."
  89. sys.exit()
  90. sIP=""
  91. page=""
  92. frameno = 1
  93. for ts, buf in pcap:
  94. eth = dpkt.ethernet.Ethernet(buf)
  95. ip = eth.data
  96. #make sure we are dealing with ip (2048) and tcp (proto=6)
  97. if eth.type ==2048 and ip.p == 6:
  98. tcp = ip.data
  99. #assuming http is running on port 80
  100. if tcp.dport == 80 and len(tcp.data) > 0:
  101. index = 1
  102. getvals = ""
  103. try:
  104. http = dpkt.http.Request(tcp.data)
  105. url = http.uri
  106. #deal with post data
  107. if http.method == "POST":
  108. getvals=http.body
  109. index = url.find("?")
  110. if index != -1:
  111. page = url[:index]
  112. else:
  113. page = url
  114. #deal with GET data
  115. elif http.method == "GET":
  116. index = url.rfind("?")
  117. if index != -1:
  118. getvals = url[index+1:]
  119. page = url[:index]
  120. except:
  121. data = tcp.data
  122. index = str(data).find("POST")
  123. if index == 0:
  124. url = str(data).split(" ")
  125. page = url[1] #POST is usually always the second value in the POST
  126. index = str(data).count("\n") #need to look into this method a little more, basically, we want to get POST data out of other streams
  127. if index == 0:
  128. index = str(data).find("=")
  129. if index != -1:
  130. getvals = str(data)
  131. #split up each variable and its cooresponding value
  132. if getvals != "":
  133. getvals = getvals.split("&")
  134. for val in getvals:
  135. i = val.find("=")
  136. val = (val[:i], val[i+1:])
  137. sIP = octetIP(ip.src)
  138. analyzeRequest(val, sIP, page, frameno)
  139. frameno += 1
  140. f.close()
  141. #usage stuff
  142. def usage():
  143. print ""
  144. print "This tool parses through a pcap file and looks for potential SQL injection attempts."
  145. print ""
  146. print "usage: sqlinject-finder.py -f filename [-t]"
  147. print "Options and arguments (and corresponding environment variables):"
  148. print "-f, --filename : valid pcap file"
  149. print "-t, --tab : prints output in tab delimited format"
  150. print "-h, --help : shows this screen"
  151. print ""
  152. print "Example: #python sqlinject-finder.py -f capture.pcap"
  153. print " #python sqlinject-finder.py -f capture.pcap -t > capture.tsv"
  154. print ""
  155. def main():
  156. try:
  157. opts, args = getopt.getopt(sys.argv[1:], "f:th", ["filename=", "tab", "help"])
  158. except getopt.GetoptError, err:
  159. print str(err)
  160. usage()
  161. sys.exit(2)
  162. filename = ""
  163. for o, a in opts:
  164. if o in ("-f", "--filename"):
  165. filename = a
  166. elif o in ("-t", "--tab"):
  167. global tab
  168. tab = True
  169. elif o in ("-h", "--help"):
  170. usage()
  171. sys.exit()
  172. else:
  173. usage()
  174. sys.exit()
  175. if (filename == ""):
  176. print "please specify a filename"
  177. sys.exit()
  178. if tab:
  179. print "Source\tPage\tValue\tFrame\tReason(s)"
  180. parsepcap(filename)
  181. if __name__ == "__main__":
  182. main()

comments powered by Disqus