前端防禦XSS
0x00 前言
我不否認前端在處理XSS的時候沒有後端那樣方便快捷,但是很多人都在說過濾XSS的事就交給後端來做吧。前端做沒什麼用。我個人是非常反感這句話的。雖然說前端防禦XSS比較麻煩,但是,不是一定不行。他只是寫的程式碼比後端多了而已。而且前端防禦XSS比後端防禦XSS功能多,雖說後端也可以完成這些功能,但是程式碼量會比前端程式碼多很多很多。其實說了那麼多,交給nginx||apache||nodeJs||Python會更好處理。但是我不會C,也就沒辦法寫nginx模組了。而且也不在本文章的範圍內,等我什麼時候學會C再說把。
0x01 後端資料反饋過濾
現在大部分的網站都是在後端過濾一下後,就交給資料庫,然後前端輸出,整個流程只有後端做了防護,一般這個防護被繞過或者某個引數的防護沒有做,那麼網站就會被淪陷了(請別以為XSS只能獲取cookie,熟練的程度取決於你的思想和程式設計) 現在我們來假設一下網站的一個URL引數沒有做好過濾,直接匯入資料庫了,然後在前端反饋結果。程式碼如下:
把使用者輸入的內容匯入到資料庫裡defenderXssTest_GetData.php:
#!php
<?php
if(empty($_GET['xss'])){ //判斷當前URL是否存在XSS引數
exit();
}
$xssString = $_GET['xss'];
/*資料庫基礎配置*/
$mysql_name ='localhost';
$mysql_username ='root';
$mysql_password ='123456';
$mysql_database ='xsstest';
$conn = mysql_connect($mysql_name,$mysql_username,$mysql_password);
mysql_query("set names 'utf8'");
mysql_select_db($mysql_database);
$sql = "insert into XSSTest (xss) values ('$xssString')";
mysql_query($sql);
mysql_close();
返回資料庫中最後一條資料內容(即最新的內容)defenderXssTest_QueryData.php:
#!php
<?php
/*資料庫基礎配置*/
$mysql_name ='localhost';
$mysql_username ='root';
$mysql_password ='123456';
$mysql_database ='xsstest';
$conn = mysql_connect($mysql_name,$mysql_username,$mysql_password);
mysql_query("set names 'utf8'");
mysql_select_db($mysql_database);
$sql ="select * from XSSTest where id = (select max(id) from XSSTest)"; //返回資料庫中最後一條資料
$xssText = mysql_query($sql);
while($row = mysql_fetch_array($xssText)){ //顯示從資料庫中返回的資料
echo $row['xss'];
}
mysql_close();
前端輸入及反饋defenderXssTest.html:
#!xml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前端防禦XSS#Demo1</title>
</head>
<body>
<input type="text" name="xss">
<input type="submit" value="提交" id="xssGet">
</body>
<!--測試請記得更換jQuery路徑!-->
<script type="text/javascript" src="/Public/js/library/jquery.js"></script>
<script>
$("#xssGet").click(function(){
$.ajax({
url: '/defenderXssTest_GetData.php',
type: 'get',
dataType: 'text',
data: "xss="+$('input:first').val(),
cache:false,
async:false,
})
.done(function() {
$.ajax({
url: '/defenderXssTest_QueryData.php',
type: 'post',
dataType: 'text',
cache:false,
async:false,
})
.done(function(data) {
$("body").append(data);
})
})
});
</script>
</html>
一共三個檔案,因為測試用,我就沒把資料庫基礎配置分離出來放在其他檔案裡了。
現在我們在瀏覽器裡開啟defenderXssTest.html檔案:
現在我們再看下資料庫:
已經匯入到資料庫裡了。
OK,以上就是最普通的儲蓄型XSS案例。為什麼會出現這個問題呢,是因為PHP沒有做好過濾。同時前端也沒有做好過濾,這裡會有人說前端做沒用的,攻擊者可以使用burp抓到此資料包,然後改包就可以繞過了。對,確實是這樣。但是大夥從一開始就已經被誤導了。想知道哪裡被誤導麼,往下看。
這裡我畫個前端、Nginx、後端都做了過濾的圖:
思維導圖URL:https://www.processon.com/view/link/56c486cde4b0e2317a8b6681
這裡我們可以看到防火牆的第一道門是前端過濾XSS機制。也是目前被大家所熟知的過濾結構。而本章要說的是:為什麼不把前端過濾copy或者move到後端過濾機制下呢?
這裡是新型的過濾機制的圖:
思維導圖URL:https://www.processon.com/view/link/56c4882ce4b0e5041c35ab53
這裡我們在後端過濾機制的後面加上了前端過濾。為什麼要這樣做呢?
大家都知道前端過濾XSS是可以被抓包軟體給修改的,所以是可以繞過,沒有什麼用。而Nginx過濾我相信大家都知道,很少有人願意去用它,因為如果是做安全文章一類的話,是會被Nginx給拋棄當前的資料包的,也就是你釋出的文章不會被存到資料庫裡,而且Nginx防禦XSS模組並沒有前端、後端那樣簡單方便,需要配置的東西很多。也導致了很多管理員不在Nginx安全上下功夫,即使管理員配置了Nginx過濾XSS模組,也可以繞過。
利用Nginx的一處邏輯缺陷(詳情請移步到:http://www.freebuf.com/articles/web/61268.html 文章裡的0x03小節:利用Nginx&Apache環境bug來實現攻擊),至於後端過濾機制肯定會有不嚴謹的時候,不然也而不會導致那麼多XSS漏洞了。所以當攻擊者輸入的XSS字串繞過了前端、Nginx、後端的話,那麼就會直接匯入到資料庫中。那麼這個時候後端傳來的資料就不可信了。而如果我們在前端顯示後端傳來的資料時加了過濾會怎麼樣呢,答案是very good。當然了,這裡有個前提,是前端顯示後端傳來資料的時候使用的是AJAX方法,而不是類似ThinkPHP這樣在模板裡呼叫。確切的說:此方法只針對於API介面
現在我們來做一個測試,之前的程式碼就是使用了AJAX方法,而
defenderXssTest_GetData.php和defenderXssTest_QueryData.php就類似於後端的API介面。我們現在在原有的基礎上新增一些程式碼:
下面是前端過濾XSS的程式碼,取自於百度FEX前端團隊的Ueditor線上編輯器:
#!php
function xssCheck(str,reg){
return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) {
if(b){
return a;
}else{
return {
'<':'<',
'&':'&',
'"':'"',
'>':'>',
"'":''',
}[a]
}
}) : '';
}
然後我們在原有程式碼的基礎上新增xssCheck()函式就行了。如下:
#!xml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前端防禦XSS#Demo1</title>
</head>
<body>
<input type="text" name="xss">
<input type="submit" value="提交" id="xssGet">
</body>
<script type="text/javascript" src="/Public/js/library/jquery.js"></script>
<script>
$("#xssGet").click(function(){
$.ajax({
url: '/defenderXssTest_GetData.php',
type: 'get',
dataType: 'text',
data: "xss="+$('input:first').val(),
cache:false,
async:false,
})
.done(function() {
$.ajax({
url: '/defenderXssTest_QueryData.php',
type: 'post',
dataType: 'text',
cache:false,
async:false,
})
.done(function(data) {
$("body").append(xssCheck(data));
})
})
});
function xssCheck(str,reg){
return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) {
if(b){
return a;
}else{
return {
'<':'<',
'&':'&',
'"':'"',
'>':'>',
"'":''',
}[a]
}
}) : '';
}
</script>
</html>
現在我們來輸入XSS字串看看:
變成了這個樣子。我們再去資料庫裡看下:
的確是完整的XSS字串,但是前端過濾了,導致此XSS沒有用武之地。
所以前端開發人員只需要在網站的base.js程式碼裡把過濾XSS的函式寫進去,再把每一個ajax傳過來的資料加上函式就可以了。
0x02 前端報警機制
這裡的報警機制不能說特別的完整,是可以繞過的。那這個報警機制到底有何用處呢?就是在攻擊者測試的時候發現及報警。
我們都知道測試XSS的時候和裝逼的時候,攻擊者會輸入alert()
函式,而之前的過濾方式,都是使用正則匹配,從而導致正則過長,匹配不易,執行過慢等問題。而現在我們完全可以重寫alert函式來讓攻擊者在測試的時候,使用的是我們已經重寫後的函式,這樣做的好處是:噹噹前的引數不存在XSS的時候,這些函式是不會被觸發的。而噹噹前引數存在XSS的時候,攻擊者會依次輸入:woaini
->檢視是否在原始碼裡輸出->woaini<>
->檢視<>
有沒有被過濾->輸入<script>alret(1)</script>
或者<img src="test" onerror="alert(1)" />
->使用了我們重寫的函式->觸發報警機制。這樣說可能有些人看不懂,下面是我畫的圖:
思維導圖:https://www.processon.com/view/link/56c55805e4b0e5041c39261f
讓我們來看下具體的程式碼吧:
#!php
var backAlert = alert; //把alert賦值給backAlert ,當後面重寫alert時,避免照成死迴圈,照成溢位錯誤。
window.alert = function(str){ //重寫alert函式
backAlert(str);
console.log("已觸發報警,將資料傳送到後臺");
}
再把console.log換成ajax把資料傳送給後臺應用。後臺接受的時候記得做過濾。前端程式碼記得加密,防止攻擊者看出意圖從而導致繞過,不觸發報警。因為可能有些公司、個人網站已經有了自己的攻擊報警系統、智慧日誌檢索系統,我也就不再寫了。把ajax傳送的資料過濾後存到資料庫裡,再顯示就行了。可以根據自己現有的框架進行開發,思路上面已經了,不難理解,程式碼也不難寫。如果你不會或者說是不想寫,可以等到我下一篇的文章。到時候裡面會有全部的原始碼。
下一章也是有關XSS防禦的,在“前端報警機制”的基礎上做的完善,有可能會用到後端,目前思路已經有了,但是沒時間寫。看三月底之前能不能寫出來吧。
0x03 結語
之前EtherDream已經說了前端防火牆了,只是他做的是防禦,而我是不防禦直接報警。然後人工修復程式碼。因為雖然你防禦住了,但是後端漏洞還在那,而觸發報警機制後就可以進行人工修復。不是說EtherDream寫的不好,反之非常好,在他的基礎上也可以修改成前端報警機制,不過我還是喜歡讓攻擊者高興幾十分鐘後,就懵逼的樣子。在EtherDream的程式碼中有一個很棒的程式碼片段,他使用了內聯事件監聽了onclick等on事件,可以近一步的監聽到駭客的操作。因為版權問題,我不方便把程式碼貼到本文中,畢竟是別人的思想結晶。想了解的話可以去檢視:
http://fex.baidu.com/blog/2014/06/xss-frontend-firewall-1/
相關文章
- antixss防禦xss DLL庫檔案2019-05-11
- Web安全系列(四):XSS 的防禦2018-09-27Web
- xss原理繞過防禦個人總結2020-07-24
- 反射式 XSS 的解釋及其防禦2018-03-13反射
- Lumen XSS 防禦 和 SQL 注入怎樣實現2019-12-15SQL
- 【前端安全】JavaScript防http劫持與XSS2018-04-23前端JavaScriptHTTP
- 如何有效防禦XSS攻擊?網路安全學習教程2021-10-22
- 前端的安全問題與防禦策略2019-05-12前端
- 跨域及相關攻擊&防禦總結(JSONP、CORS、CSRF、XSS)2019-03-14跨域JSONCORS
- AccessibilityService防禦2019-01-04
- DDoS 防禦2018-03-10
- 防禦DDoS原理搞明白,防禦效果才能事半功倍2021-04-07
- 前端安全 - XSS2019-01-06前端
- JeecgBoot抵禦XSS攻擊實現方案2022-05-13boot
- AccessibilityService分析與防禦2019-03-04
- CSS 樣式防禦2018-08-26CSS
- CDN防禦與高防伺服器2022-06-16伺服器
- DDOS伺服器防禦的方法有哪些,如何防禦DDOS攻擊2023-05-04伺服器
- WMI 的攻擊,防禦與取證分析技術之防禦篇2020-08-19
- 防禦式CSS是什麼?這幾點屬性重點防禦!2022-01-31CSS
- CSRF攻擊與防禦2024-11-01
- 什麼是CDN防禦2022-12-22
- CSRF 攻擊與防禦2019-11-18
- LDAP注入與防禦剖析2020-08-19LDA
- WEB攻擊與防禦2018-03-31Web
- 【虹科分享】一種動態防禦策略——移動目標防禦(MTD)2024-01-03
- 高防伺服器如何實現防禦2022-08-10伺服器
- RAKsmart高防伺服器防禦形式解析2020-07-16伺服器
- 詳解Xss 及SpringBoot 防範Xss攻擊(附全部程式碼)2023-03-07Spring Boot
- 前端針對 XSS 安全配置2024-10-26前端
- 前端攻擊 XSS 深入解析2018-04-12前端
- BGP劫持原理及如何防禦2022-09-27
- 伺服器防禦ddos方法2022-02-09伺服器
- API安全的防禦建設2019-01-10API
- CSS keylogger:攻擊與防禦2019-01-03CSS
- 高防伺服器主要防禦的攻擊2020-01-18伺服器
- 高防伺服器如何進行防禦措施2021-08-20伺服器
- 如何有效預防XSS?這幾招管用!!!2019-06-30