常见web攻击总结
搞Web開發離不開安全這個話題,確保網站或者網頁應用的安全性,是每個開發人員都應該了解的事。本篇主要簡單介紹在Web領域幾種常見的攻擊手段及Java Web中的預防方式。
XSS
SQL注入
DDOS
CSRF
項目地址: https://github.com/morethink/web-security
XSS
一、什么是XSS
XSS攻擊:跨站腳本攻擊(Cross-Site Scripting),為了不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。XSS是一種常見的web安全漏洞,它允許攻擊者將惡意代碼植入到提供給其它用戶使用的頁面中。不同于大多數攻擊(一般只涉及攻擊者和受害者),XSS涉及到三方,即攻擊者、客戶端與Web應用。XSS的攻擊目標是為了盜取存儲在客戶端的cookie或者其他網站用于識別客戶端身份的敏感信息。一旦獲取到合法用戶的信息后,攻擊者甚至可以假冒合法用戶與網站進行交互。
XSS通常可以分為兩大類:
存儲型XSS,主要出現在讓用戶輸入數據,供其他瀏覽此頁的用戶進行查看的地方,包括留言、評論、博客日志和各類表單等。應用程序從數據庫中查詢數據,在頁面中顯示出來,攻擊者在相關頁面輸入惡意的腳本數據后,用戶瀏覽此類頁面時就可能受到攻擊。這個流程簡單可以描述為:惡意用戶的Html輸入Web程序->進入數據庫->Web程序->用戶瀏覽器。
反射型XSS,主要做法是將腳本代碼加入URL地址的請求參數里,請求參數進入程序后在頁面直接輸出,用戶點擊類似的惡意鏈接就可能受到攻擊。
比如說我寫了一個網站,然后攻擊者在上面發布了一個文章,內容是這樣的?<script>alert(document.cookie)</script>,如果我沒有對他的內容進行處理,直接存儲到數據庫,那么下一次當其他用戶訪問他的這篇文章的時候,服務器從數據庫讀取后然后響應給客戶端,瀏覽器執行了這段腳本,就會將cookie展現出來,這就是典型的存儲型XSS。
如圖
二、如何預防XSS
答案很簡單,堅決不要相信用戶的任何輸入,并過濾掉輸入中的所有特殊字符。這樣就能消滅絕大部分的XSS攻擊。
目前防御XSS主要有如下幾種方式:
過濾特殊字符
避免XSS的方法之一主要是將用戶所提供的內容進行過濾(如上面的script標簽)。
使用HTTP頭指定類型
w.Header().Set("Content-Type","text/javascript")
這樣就可以讓瀏覽器解析javascript代碼,而不會是html輸出。
SQL注入
一、什么是SQL注入
攻擊者成功的向服務器提交惡意的SQL查詢代碼,程序在接收后錯誤的將攻擊者的輸入作為查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。
舉例:' OR '1'='1
這是最常見的 SQL注入攻擊,當我們輸如用戶名 admin ,然后密碼輸如' OR '1'=1='1的時候,我們在查詢用戶名和密碼是否正確的時候,本來要執行的是SELECT * FROM user WHERE username='' and password='',經過參數拼接后,會執行 SQL語句?SELECT * FROM user WHERE username='' and password='' OR '1'='1',這個時候1=1是成立,自然就跳過驗證了。
如下圖所示:
但是如果再嚴重一點,密碼輸如的是';DROP TABLE user;--,那么 SQL命令為SELECT * FROM user WHERE username='admin' and password='';drop table user;--'?這個時候我們就直接把這個表給刪除了。
二、如何預防SQL注入
在Java中,我們可以使用預編譯語句(PreparedStatement),這樣的話即使我們使用 SQL語句偽造成參數,到了服務端的時候,這個偽造 SQL語句的參數也只是簡單的字符,并不能起到攻擊的作用。
對進入數據庫的特殊字符('"尖括號&*;等)進行轉義處理,或編碼轉換。
在應用發布之前建議使用專業的SQL注入檢測工具進行檢測,以及時修補被發現的SQL注入漏洞。網上有很多這方面的開源工具,例如sqlmap、SQLninja等。
避免網站打印出SQL錯誤信息,比如類型錯誤、字段不匹配等,把代碼里的SQL語句暴露出來,以防止攻擊者利用這些錯誤信息進行SQL注入。
在上圖展示中,使用了Java JDBC中的PreparedStatement預編譯預防SQL注入,可以看到將所有輸入都作為了字符串,避免執行惡意SQL。
DDOS
一、什么是DDOS
DDOS:分布式拒絕服務攻擊(Distributed Denial of Service),簡單說就是發送大量請求是使服務器癱瘓。DDos攻擊是在DOS攻擊基礎上的,可以通俗理解,dos是單挑,而ddos是群毆,因為現代技術的發展,dos攻擊的殺傷力降低,所以出現了DDOS,攻擊者借助公共網絡,將大數量的計算機設備聯合起來,向一個或多個目標進行攻擊。
在技術角度上,DDoS攻擊可以針對網絡通訊協議的各層,手段大致有:TCP類的SYN Flood、ACK Flood,UDP類的Fraggle、Trinoo,DNS Query Flood,ICMP Flood,Slowloris類等等。一般會根據攻擊目標的情況,針對性的把技術手法混合,以達到最低的成本最難防御的目的,并且可以進行合理的節奏控制,以及隱藏保護攻擊資源。
下面介紹一下TCP協議中的SYN攻擊。
二、SYN攻擊
在三次握手過程中,服務器發送?SYN-ACK?之后,收到客戶端的?ACK?之前的 TCP 連接稱為半連接(half-open connect)。此時服務器處于?SYN_RCVD?狀態。當收到 ACK 后,服務器才能轉入?ESTABLISHED?狀態.
SYN攻擊指的是,攻擊客戶端在短時間內偽造大量不存在的IP地址,向服務器不斷地發送SYN包,服務器回復確認包,并等待客戶的確認。由于源地址是不存在的,服務器需要不斷的重發直至超時,這些偽造的SYN包將長時間占用未連接隊列,正常的SYN請求被丟棄,導致目標系統運行緩慢,嚴重者會引起網絡堵塞甚至系統癱瘓。
三、如何預防DDOS
阿里巴巴的安全團隊在實戰中發現,DDoS 防御產品的核心是檢測技術和清洗技術。檢測技術就是檢測網站是否正在遭受 DDoS 攻擊,而清洗技術就是清洗掉異常流量。而檢測技術的核心在于對業務深刻的理解,才能快速精確判斷出是否真的發生了 DDoS 攻擊。清洗技術對檢測來講,不同的業務場景下要求的粒度不一樣。
CSRF
一、什么是CSRF
CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。
你這可以這么理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至于購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私泄露以及財產安全。
二、CSRF的原理
下圖簡單闡述了CSRF攻擊的思路
從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
登錄受信任網站A,并在本地生成Cookie。
在不登出A的情況下,訪問危險網站B。
看到這里,你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:
你不能保證你登錄了一個網站后,不再打開一個tab頁面并訪問另外的網站。
你不能保證你關閉瀏覽器了后,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認為關閉瀏覽器就等于退出登錄/結束會話了......)
上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
下面講一講java解決CSRF攻擊的方式。
三、模擬CSRF攻擊
登錄A網站
用戶名和密碼都是admin。
http://localhost:8081/login.html:
你有權限刪除1號帖子
http://localhost:8081/deletePost.html:
登錄有CSRF攻擊A網站的B網站
http://localhost:8082/deletePost.html:
明顯看到B網站是8082端口,A網站是8081端口,但是B網站的刪除2號帖子功能依然實現。
四、如何預防CSRF攻擊
簡單來說,CSRF 就是網站 A 對用戶建立信任關系后,在網站 B 上利用這種信任關系,跨站點向網站 A 發起一些偽造的用戶操作請求,以達到攻擊的目的。
而之所以可以完成攻擊是因為B向A發起攻擊的時候會把A網站的cookie帶給A網站,也就是說cookie已經不安全了。
通過Synchronizer Tokens
Synchronizer Tokens: 在表單里隱藏一個隨機變化的 csrf_token csrf_token 提交到后臺進行驗證,如果驗證通過則可以繼續執行操作。這種情況有效的主要原因是網站 B 拿不到網站 A 表單里的 csrf_token
這種方式的使用條件是PHP和JSP等。因為cookie已經不安全了,因此把csrf_token值存儲在session中,然后每次表單提交時都從session取出來放到form表單的隱藏域中,這樣B網站不可以得到這個存儲到session中的值。
下面是JSP的:
<input?type="hidden"?name="random_form"?value=<%=random%>></input>但是我現在的情況是html,不是JSP,并不能動態的從session中取出csrf_token值。只能采用加密的方式了。
Hash加密cookie中csrf_token值
這可能是最簡單的解決方案了,因為攻擊者不能獲得第三方的Cookie(理論上),所以表單中的數據也就構造失敗了。
我采用的hash加密方法是JS實現Java的HashCode方法,得到hash值,這個比較簡單。也可以采用其他的hash算法。
前端向后臺傳遞hash之后的csrf_token值和cookie中的csrf_token值,后臺拿到cookie中的csrf_token值后得到hashCode值然后與前端傳過來的值進行比較,一樣則通過。
你有權限刪除3號帖子
http://localhost:8081/deletePost.html
B網站的他已經沒有權限了
我們通過UserFilter.java給攻擊者返回的是403錯誤,表示服務器理解用戶客戶端的請求但拒絕處理。
http://localhost:8082/deletePost.html
攻擊者不能刪除4號帖子。
前端代碼:
deletePost.html
<html?lang="en">
<head>
????<meta?charset="UTF-8">
????<title>deletePost</title>
????<script?type="text/javascript"?src="js/jquery.min.js"></script>
????<script?type="text/javascript">
????????function?deletePost()?{
????????????var?url?=?'/post/'?+?document.getElementById("postId").value;
????????????var?csrf_token?=?document.cookie.replace(/(?:(?:^|.*;s*)csrf_tokens*=s*([^;]*).*$)|^.*$/,?"$1");
????????????console.log('csrf_token='?+?csrf_token);
????????????$.ajax({
????????????????type:?"post",//請求方式
????????????????url:?url,??//發送請求地址
????????????????timeout:?30000,//超時時間:30秒
????????????????data:?{
????????????????????"_method":?"delete",
????????????????????"csrf_token":?hash(csrf_token)?//?對csrf_token進行hash加密
????????????????},
????????????????dataType:?"json",//設置返回數據的格式
????????????????success:?function?(result)?{
????????????????????if?(result.message?==?"success")?{
????????????????????????$("#result").text("刪除成功");
????????????????????}?else?{
????????????????????????$("#result").text("刪除失敗");
????????????????????}
????????????????},
????????????????error:?function?()?{?//請求出錯的處理
????????????????????$("#result").text("請求出錯");
????????????????}
????????????});
????????}
????????//?javascript的String到int(32位)的hash算法
????????function?hash(str)?{
????????????var?hash?=?0;
????????????if?(str.length?==?0)?return?hash;
????????????for?(i?=?0;?i?<?str.length;?i++)?{
????????????????char?=?str.charCodeAt(i);
????????????????hash?=?((hash?<<?5)?-?hash)?+?char;
????????????????hash?=?hash?&?hash;?//?Convert?to?32bit?integer
????????????}
????????????return?hash;
????????}
????</script>
</head>
<body>
<h3>刪除帖子</h3>
帖子編號?:?<input?type="text"?id="postId"/>
<button?onclick="deletePost();">deletePost</button>
<br/>
<br/>
<br/>
<div>
????<p?id="result"></p>
</div>
</body>
</html>
后臺代碼:
UserInterceptor.java
package?cn.morethink.interceptor;import?cn.morethink.util.JsonUtil;
import?cn.morethink.util.Result;
import?org.springframework.web.servlet.HandlerInterceptor;
import?org.springframework.web.servlet.ModelAndView;
import?javax.servlet.http.Cookie;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?java.io.PrintWriter;
/**
?*?@author?李文浩
?*?@date?2018/1/4
?*/
public?class?UserInterceptor?implements?HandlerInterceptor?{
????
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????????String?method?=?request.getMethod();
????????System.out.println(method);
????????if?(method.equalsIgnoreCase("POST")?||?method.equalsIgnoreCase("DELETE")
????????????????||?method.equalsIgnoreCase("PUT"))?{
????????????String?csrf_token?=?request.getParameter("csrf_token");
????????????Cookie[]?cookies?=?request.getCookies();
????????????if?(cookies?!=?null?&&?cookies.length?>?0?&&?csrf_token?!=?null)?{
????????????????for?(Cookie?cookie?:?cookies)?{
????????????????????if?(cookie.getName().equals("csrf_token"))?{
????????????????????????if?(Integer.valueOf(csrf_token)?==?cookie.getValue().hashCode())?{
????????????????????????????return?true;
????????????????????????}
????????????????????}
????????????????}
????????????}
????????}
????????Result?result?=?new?Result("403",?"你還想攻擊我??????????",?"");
????????PrintWriter?out?=?response.getWriter();
????????out.write(JsonUtil.toJson(result));
????????out.close();
????????return?false;
????}
????
????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{
????}
????
????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{
????}
}
注意:
cookie必須要設置PATH才可以生效,否則在下一次請求的時候無法帶給服務器。
Spring Boot 出現啟動找不到主類的問題時可以mvn clean一下。
Filter設置response.sendError(403)在Spring Boot沒有效果。
總結
上面一共提到了4種攻擊方式,分別是XSS攻擊(關鍵是腳本,利用惡意腳本發起攻擊),SQL注入(關鍵是通過用SQL語句偽造參數發出攻擊),DDOS攻擊(關鍵是發出大量請求,最后令服務器崩潰),CSRF攻擊(關鍵是借助本地cookie進行認證,偽造發送請求)。
原文出處:https://www.cnblogs.com/morethink/p/8734103.html
完
總結
- 上一篇: BXP多分区的正确的操作步骤(转)
- 下一篇: 原生和h5桥接