nginx實現CSRF和XSS防禦

   版權聲明:本文爲博主原創文章,未經博主允許不得轉載。



nginx實現CSRF和XSS防禦

 最近,因爲公司任務要求,搞了一下nginx配置。任務要求是實現CSRF和XSS防護,至於什麼是CSRF和XSS請自行學習一下。首先需要解釋的是,這裏所提到的CSRF和XSS防禦全是基於後臺基於Nginx配置。
1.CSRF防禦
網上搜一下解決方案大概是有四種:
(1)驗證HTTP Referer 字段
(2)在請求地址中添加token並驗證
(3)在HTTP頭中自定義屬性並驗證
(4)Chrome瀏覽器端啓用SameSite cookie
以上四種方法:方法二難點在於如何把 token 以參數的形式加入請求,並且該方法有一個缺點是難以保證 token 本身的安全。方法3侷限性非常大。XMLHttpRequest 請求通常用於 Ajax 方法中對於頁面局部的異步刷新,並非所有的請求都適合用這個類來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄下,從而進行前進,後退,刷新,收藏等操作,給用戶帶來不便。另外,對於沒有進行 CSRF 防護的遺留系統來說,要採用這種方法來進行防護,要把所有請求都改爲XMLHttprequest請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。方法四顯然是有很大的侷限性。因此我採用了方法1來實現CSRF的防禦,方法一實現起來更簡單。然而,這種方法並非萬無一失。Referer 的值是由瀏覽器提供的,雖然 HTTP 協議上有明確的要求,但是每個瀏覽器對於 Referer 的具體實現可能有差別,並不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴於第三方(即瀏覽器)來保障,從理論上來講,這樣並不安全。事實上,對於某些瀏覽器,比如 IE6 或 FF2,目前已經有一些方法可以篡改 Referer 值。如果 www.bank.example網站支持 IE6 瀏覽器,黑客完全可以把用戶瀏覽器的 Referer 值設爲以 www.bank.example域名開頭的地址,這樣就可以通過驗證,從而進行 CSRF 攻擊。
即便是使用最新的瀏覽器,黑客無法篡改 Referer 值,這種方法仍然有問題。因爲 Referer 值會記錄下用戶的訪問來源,有些用戶認爲這樣會侵犯到他們自己的隱私權,特別是有些組織擔心 Referer 值會把組織內網中的某些信息泄露到外網中。因此,用戶自己可以設置瀏覽器使其在發送請求時不再提供 Referer。當他們正常訪問銀行網站時,網站會因爲請求沒有 Referer 值而認爲是 CSRF 攻擊,拒絕合法用戶的訪問。
另外,如果Referer的判斷邏輯寫的不嚴密的話,也容易被攻破,例如
constreferer = request.headers.referer;if (referer.indexOf('www.bank.example') > -1) { // pass}
如果黑客的網站是www.bank.example.hack.com,則referer檢查無效。
***************************************************************************************************
基於上述分析,採用nginx配置文件自帶檢查Referer模塊對Herder Referer字段進行check。
通過java文件動態的配置nginx.conf文件,凡是通過UI 進入到環境的全部進行check,模塊代碼如下:
valid_referers none blocked server_names www.baidu.com
if ($invalid_referer) {
return 403;
}
valid_referers 代表可信referer,此處可信referer的設置將會使變量$invalid_referer的值爲「0」,反之$invalid_referer的值爲「1」,則執行IF條件名並返回相關限制結果。

none是指當referer爲空的時候,比如在鏈接器中直接打開一個圖片鏈接,若要禁止用戶直接訪問,則必須省掉none。

blocked 是指經過某些代理或firewall過濾後的referer,比如省略了url前綴等, 同樣地,若要禁止用戶直接訪問,則必須省掉blocked。

server_names 是nginx配置文件中的server name項,代指網站域名。
根據實際需求將模塊寫進相應的location中,正則要慎重,可能會影響的環境正常運行。
2.CSRF防禦的生效驗證問題
嘗試過使用soapUI進行測試,但是可能是本人的soapUI功力尚淺,使用HTTP Request測試加入Referer頭信息對接口進行測試,總是不生效,這部分將在soapUI的總結中詳細說。本人採用的是Chrome內置的免費插件postman,這是我最近才接觸到,但是發現十分好用,和soapUI相比,操作起來要簡便太多了,而且功能十分強大,真的是強烈推薦給大家。
3.XSS防禦
cross site scripting(跨站腳本攻擊),爲了和cascading style sheets(層疊樣式表)區分,取名爲XSS。通過嵌入腳本的方式進行攻擊,獲取用戶的cookie等信息,或者在服務器端執行來篡改數據。
相比於CSRF防禦問題,XSS的防禦問題顯得略顯繁瑣一些。網上搜一下解決辦法基本上思路也是很清晰了大致要做如下幾步(此處直接引用我在task上的comments並稍加修改):
1)Add the following headers in response (nginx)
add_header X-Frame-Options 'SAMEORIGIN';  #只允許本網站的frame嵌套
add_header X-XSS-Protection '1; mode=block';  #開啓XSS過濾器
add_header X-Content-Type-Options 'nosniff';  #禁止嗅探文件類型
2.Add the HttpOnly and secure flag
這一步根據實際情況的不同,有不同的執行方式。一般的可以在我們的Tomcat配置或是nginx配置中設置,也可以在後臺設置。
HTTP消息之間是無狀態的,cookie和session可以維護信息。黑客一旦竊取cookie,就可以獲得用戶身份。通過瀏覽器的document對象,就可以獲取cookie。HttpOnly會禁止腳本訪問cookie,防止XSS。(進行設定之前一定要和前臺人員確認以防對系統環境造成影響)
secure的設定則是將只允許HTTPS。
3.add XSS-Blocking (nginx)
set $block_xss 0;
if ($query_string ~ "base64_(en|de)code(.*)")
{ set $block_xss 1; }
if ($request_uri ~ "base64_(en|de)code(.*)") { set $block_xss 1; }
if ($query_string ~ "(<|%3C)*.script.*(/?>|%3E)")
{ set $block_xss 1; }
if ($request_uri ~ "(<|%3C)*.script.*(/?>|%3E)") { set $block_xss 1; }
if ($query_string ~ "(<|%3C)*.iframe.*(/?>|%3E)")
{ set $block_xss 1; }
if ($request_uri ~ "(<|%3C)*.iframe.*(/?>|%3E)") { set $block_xss 1; }
if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]
{0,2})")
{ set $block_xss 1; }
if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2}
)")
{ set $block_xss 1; }
if ($block_xss = 1)
{ return 403; }
It can catch more Matching items in Request URL e.g. <script> <script/> <script src=123456789.js />
此處直接把公司task完成後的comments貼出來了。
網上說的大多數是把星號放在script和iframe的兩側,但是通過我的實際驗證後發現,例如
"(<|%3C).*script*.(/?>|%3E)" 正則是不能catch到<script src=123456789.js />,讀者可自行測試。
XSS-Blocking主要就是針對UI界面裏在比如Description或是comments裏面寫入可執行腳本的問題進行防禦。
1.3兩步的nginx的配置要根據項目的實際需求寫在不同的location中。
4.XSS防禦的生效驗證問題
我仍然使用的Chrome自帶插件postman進行測試,當然主要是針對nginx裏面的XSS-Blocking代碼塊進行的測試說白了也就是對正則規則進行測試。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章