什么是Injection?
injection,中文意思就是注入的意思,常見的注入漏洞就是SQL注入啦,是現在應用最廣泛,殺傷力很大的漏洞。
什么是HTML injection?
有交互才會產生漏洞,無論交互是怎么進行的。交互就是網頁有對后台數據庫的讀取或前端的動態效果。HTML文件並不是像大家想的那樣沒有任何交互,在HTML文件里還是會用到一些JavaScript來完成自己需要的一些動態效果,例如,地址欄的參數就是location,用戶所做的點擊觸發事件,以及一些動態的DOM交互都會影響到JavaScript的執行導致漏洞的產生。
如果HTML文件可以被injection的話,那么就可以利用本地的HTML文件在本地域內執行JavaScript代碼,權限是非常高的。
平台簡介:
bWAPP:漏洞平台,開源web應用
漏洞利用:
頁面
我們可以看到這是一個Form提交表單的頁面,並且是get請求方法。
我們提交一些信息看看
提交后可以看到,我們提交的信息在頁面上顯示。並且也在地址欄里面看到我們的信息,這是get請求的一個特征。
A:Low級別(未進行任何過濾)
A-1:增加外鏈,影響SEO,提升外鏈的PR
PAYLOAD:http://127.0.0.1/htmli_get.php?firstname=<a href="http://www.cnblogs.com/ESHLkangi/">ESHLkangi</a>&lastname=ESHLkangi&form=submit
效果:
A-2:反射性xss漏洞,進一步可以偽造存在xss漏洞的惡意網址執行自己DIY的ji代碼,從而搜集到其他人的信息。
PAYLOAD:http://118.89.17.134/htmli_get.php?firstname=<script>alert(document.cookie)</script>&lastname=ESHLkangi&form=submit
效果:
盜取了cookie。
源碼分析:
HTML:
1 <form action="/htmli_get.php" method="GET"> 2 3 <p> 4 <label for="firstname">First name:</label><br> 5 <input id="firstname" name="firstname" type="text"> 6 </p> 7 8 <p> 9 <label for="lastname">Last name:</label><br> 10 <input id="lastname" name="lastname" type="text"> 11 </p> 12 13 <button type="submit" name="form" value="submit">Go</button> 14 15 </form>
對應的PHP代碼:
1 <?php 2 if(isset($_GET["firstname"]) && isset($_GET["lastname"])) 3 { 4 $firstname = $_GET["firstname"]; 5 $lastname = $_GET["lastname"]; 6 if($firstname == "" or $lastname == "") 7 { 8 echo "<font color=\"red\">Please enter both fields...</font>"; 9 } 10 11 else 12 { 13 echo "Welcome " . $firstname . " --- " . $lastname; 14 } 15 } 16 ?>
分析:
在表單提交的時候沒有對用戶輸入的數據進行處理,並且在PHP代碼中echo的時候沒有處理就打印到頁面,當我們在文本框中輸入類似代碼:
<a href="http://www.cnblogs.com/ESHLkangi/">ESHLkangi</a>
那展示到頁面的結果將會是一個可以跳轉頁面的超鏈接,同樣我們也可以獲取cookie。
B:Medium級別(初級的字符處理)
測試
發現,超鏈接沒有實現
cookie也盜取不了。
源碼分析:
HTML:
不變
PHP:
1 function xss_check_1($data) 2 { 3 // Converts only "<" and ">" to HTLM entities 4 $input = str_replace("<", "<", $data); 5 $input = str_replace(">", ">", $input); 6 // Failure is an option^M 7 // Bypasses double encoding attacks 8 // <script>alert(0)</script> 9 // %3Cscript%3Ealert%280%29%3C%2Fscript%3E^M 10 // %253Cscript%253Ealert%25280%2529%253C%252Fscript%253E^M 11 $input = urldecode($input); 12 13 return $input; 14 15 }
通過源碼,我們可以看到,開始使用了str_replace()函數過濾"<"和">"這兩個特殊字符處理了,最后,用了urldecode()函數進行解碼,把URL編碼還原字符串。
POC:
依據代碼的思路,我們可以先對"<"、">"進行urlencode,繞過str_replace()函數的過濾即可。建議把所有特殊的符號都進行編碼,例如"=","/"等
<a href="http://www.cnblogs.com/ESHLkangi/">ESHLkangi</a>
進行urlencode后
%3Ca href="http://www.cnblogs.com/ESHLkangi/"%3EESHLkangi%3C/a%3E
把編碼后的輸入到文本框內
成功繞過!!!
C:High級別(htmlspecialchars)
直接查看源碼,進行一下審計
后台源碼:
1 function xss_check_3($data, $encoding = "UTF-8") 2 { 3 4 // htmlspecialchars - converts special characters to HTML entities 5 // '&' (ampersand) becomes '&' 6 // '"' (double quote) becomes '"' when ENT_NOQUOTES is not set 7 // "'" (single quote) becomes ''' (or ') only when ENT_QUOTES is set 8 // '<' (less than) becomes '<' 9 // '>' (greater than) becomes '>' 10 11 return htmlspecialchars($data, ENT_QUOTES, $encoding); 12 13 }
發現代碼中用了一個htmlspecialchars()函數。簡單分析一下這個函數:
htmlspecialchars() 函數把預定義的字符轉換為 HTML 實體。
預定義的字符是:
& (和號)成為 &
" (雙引號)成為 "
' (單引號)成為 '
< (小於)成為 <
> (大於)成為>
它的語法如下:
htmlspecialchars(string,flags,character-set,double_encode)
其中第二個參數flags需要重要注意,很多開發者就是因為沒有注意到這個參數導致使用htmlspecialchars()函數過濾XSS時被繞過。因為flags參數對於引號的編碼如下:
可用的引號類型:
ENT_COMPAT - 默認。僅編碼雙引號。
ENT_QUOTES - 編碼雙引號和單引號。
ENT_NOQUOTES - 不編碼任何引號。
可以看到的是我們這里是使用了ENT_QUOTES 編碼的,把單引號也過濾了。
技術尚菜,想實現繞過有點困難,現在只能這樣了。。。
知乎上有些解答,可以參考https://www.zhihu.com/question/27646993