首先提出payload,然后了解大致思路以后,了解一下这几个python中的所用到的几个魔术方法

flask中的最基础的模板注入:

[].__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__']['__import__']('os').popen('whoami').read()

首先说一下大致思路,然后逐一看一下这些魔术方法都代表什么

  1. 我们可以通过普通数据类型的__class__成员属性得到所属类,
  2. 再通过__bases___base____mro__可以得到object类
  3. 再次通过__subclasses__()来得到object下的所有基类
  4. 遍历所有基类检查是否存在指定的魔术方法,比如__init__或者__delete__等,如果存在,那么即可获取__globals__['__builtins__'],就可以调用任意函数了.

__class__

  • 一个实例调用__class__属性时会指向该实例对应的类

我们都知道再python里面,所有的数据类型都存放在Object这一个大类中,其中还包括int,str,dict等

__base__,__bases__,__mro__

首先我们运行一下这三个就知道了:

可以看到

  • __base__ 内置类属性将打印类对象的基类
  • __bases__ 内置类属性将打印类对象的基类的元组
  • __mro__ 它是一个tuple, 装着方法解析时的对象查找顺序,越靠前的优先级越高

ps:在OOP(面对对象编程)程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)

__subclasses__

  • 获取Object下的所有子类:

__globals__

  • 以字典的形式返回函数所在的全局命名空间所定义的全局变量。
  • __globals__ 就是 globals()函数的返回值

例如我们在新开打开python里先定义一个函数,然后看一下全局变量

因为__globals__返回的是函数所在的全局命名空间所定义的全局变量,所以我们才要在基类检查是否存在函数,一般基类中都存在__init__初始化的魔术方法,所以我们可以找到有__init__的基类,当然其他的也可以,然后使用函数找到全局变量中的__builtins__

__builtins__

我们在启动python而没有导入任何包时,依然可以使用一些函数,例如eval(), hex(), char() 等,这些函数被称为内建函数,都保存在__builtins__。Python在启动时就直接为我们导入了。


有了__builtins__,我们就可以调用其中的方法了。

__import__

这个我在之前的博客中也提到了

  • 如果一个模块经常变化就可以使用 __import__()来动态载入

例如:
__import__('os').popen('whoami').read()

__import__('requests').get('https://yuaneu.ro')

最后修改:2021 年 12 月 03 日
如果觉得我的文章对你有用,请随意赞赏