來場戰爭如何?Java開發必須掌握的8種網站***技術

XSS

XSS的全稱是跨站腳本(Cross Site Scripting),是WEB應用程序中最常見到的手段之一。跨站腳本指的是者在網頁中嵌入惡意腳本程序, 當用戶打開該網頁時,腳本程序便開始在客戶端的瀏覽器上執行,以盜取客戶端cookie、 盜取用戶名密碼、下載執行病毒程序等等。

爲了不和層疊樣式表 (Cascading Style Sheets,CSS)的縮寫混淆,故將跨站腳本縮寫爲XSS

有一種場景,用戶在表單上輸入一段數據後,提交給服務端進行持久化,其他頁面上需要從服務端將數據取出來展示。還是使用之前那個表單nick,用戶輸入暱稱之後,服務端會將nick保存,並在新的頁面展現給用戶,當普通用戶正常輸入hollis,頁面會顯示用戶的 nick爲hollis:

<body> 
   hollis
</body>

但是,如果用戶輸入的不是一段正常的nick字符串,而是<script>alert("haha")</script>, 服務端會將這段腳本保存起來,當有用戶查看該頁面時,頁面會出現如下代碼:

<body> 
   <script>
       alert("haha")
   </script>
</body>

其影響就是可能會在頁面直接彈出對話框。

來場戰爭如何?Java開發必須掌握的8種網站***技術

XSS的防禦

XSS之所以會發生,是因爲用戶輸入的數據變成了代碼。因此,我們需要對用戶輸入的數據進行HTML轉義處理,將其中的“尖括號”、“單引號”、“引號” 之類的特殊字符進行轉義編碼。

來場戰爭如何?Java開發必須掌握的8種網站***技術

如今很多開源的開發框架本身默認就提供HTML代碼轉義的功能,如流行的jstl、Struts等等,不需要開發人員再進行過多的開發。使用jstl標籤進行HTML轉義,將變量輸出,代碼 如下:

&lt;c:out value="${nick}" escapeXml="true"&gt;&lt;/c:out&gt;

只需要將escapeXml設置爲true, jstl就會將變量中的HTML代碼進行轉義輸出。

CSRF

CSRF的全稱是跨站請求僞造(cross site request forgery), 是一種對網站的惡意利用,你可以這麼理解CSRF者盜用了你的身份,以你的名義向第三方網站發送惡意請求。CRSF能做的事情包括利用你的身份發郵件、發短信、進行交易轉賬等等,甚至盜取你的賬號。

儘管聽起來跟XSS跨站腳本有點相似,但事實上CSRF與XSS差別很大,XSS利用的是站點內的信任用戶,而CSRF則是通過僞裝來自受信任用戶的請求來利用受信任的網站。

假設某銀行網站A,他以GET請求來發起轉賬操作,轉賬的地址爲www.xxx.com/transfer.do?accountNum=10001&money=10000,accountNum參數表示轉賬的目的賬戶,money參數表示轉賬金額。 而某大型論壇B上,一個惡意用戶上傳了一張圖片,而圖片的地址欄中填的並不是圖片的地址,而是前面所說的轉賬地址:

&lt;img src="http://www.xxx.com/transfer.do?accountNum=10001&money=10000"&gt;

當你登陸網站A後,沒有及時登出,這個時候你訪問了論壇B,不幸的事情發生了,你會發現你的賬戶裏面少了10000塊......

爲什麼會這樣呢,在你登陸銀行A的時候,你的瀏覽器端會生成銀行A的cookie,而當你訪問論壇B的時候,頁面上的<img>標籤需要瀏覽器發起一個新的HTTP請求,以獲得圖片資源, 當瀏覽器發起請求的時候,請求的卻是銀行A的轉賬地址www.xxx.com/transfer.do?accoun tNum=10001&money=10000,並且會帶上銀行A的cookie信息,結果銀行的服務器收到這個請求後,會認爲是你發起的一次轉賬操作,因此你的賬戶裏邊便少了10000塊。

來場戰爭如何?Java開發必須掌握的8種網站***技術

CSRF的防禦

cookie設置爲HttpOnly
CSRF很大程度上是利用了瀏覽器的cookie,爲了防止站內的XSS漏洞盜取cookie,需要在cookie中設置"HttpOnly"屬性,這樣通過程序(如JavascriptS腳本、Applet等)就無法讀取到cookie信息,避免了者僞造cookie的情況出現。

增加token
CSRF之所以能夠成功,是因爲者可以僞造用戶的請求,該請求中所有的用戶驗證信息都存在於cookie中,因此者可以在不知道用戶驗證信息的情況下直接利用用戶的cookie來通過安全驗證。由此可知,抵禦CSRF的關鍵在於:在請求中放入者所不能僞造的信息,並且該信息不存在於cookie之中。鑑於此,系統開發人員可以在HTTP請求中以參數的形式加入一個隨機產生的token,並在服務端進行token校驗,如果請求中沒有token或者token內容不正確,則認爲是CSRF而拒絕該請求。

通過Referer識別
根據HTTP協議,在HTTP頭中有一個字段叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求都來自於同一個網站。比如某銀行的轉賬是通過用戶訪問http://www.xxx.com/transfer.do頁面完成,用戶必須先登錄www.xxx.com,然後通過點擊頁面上的提交按鈕來觸發轉賬事件。當用戶提交請求時,該轉賬請求的Referer值就會是提交按鈕所在頁面的URL(本例爲www.xxx.com/transfer.do)。如果者要對銀行網站實施CSRF,他只能在其他的網站構造請求,當用戶通過其他網站發送請求到銀行時,該請求的Referer的值是其他網站的地址,而不是銀行轉賬頁面的地址。因此,要防禦CSRF,銀行網站只需要對於每一個轉賬請求驗證其Referer值,如果是以www.xxx.com域名開頭的地址,則說明該請求是來自銀行網站自己的請求,是合法的。如果 Referer是其他網站的話,就有可能是CSRF,則拒絕該請求。

SQL注入

所謂SQL注入,就是通過把SQL命令僞裝成正常的HTTP請求參數,傳遞到服務端,欺騙服務器最終執行惡意的SQL命令,達到目的。者可以利用SQL注入漏洞,查詢非授權信息, 修改數據庫服務器的數據,改變表結構,甚至是獲取服務器root權限。總而言之,SQL注入漏洞的危害極大,者採用的SQL指令,決定的威力。當前涉及到大批量數據泄露的事件,大部分都是通過利用SQL注入來實施的。

假設有個網站的登錄頁面,如下所示:

來場戰爭如何?Java開發必須掌握的8種網站***技術

假設用戶輸入nick爲zhangsan,密碼爲password1,則驗證通過,顯示用戶登錄:

來場戰爭如何?Java開發必須掌握的8種網站***技術

否則,顯示用戶沒有登錄:

來場戰爭如何?Java開發必須掌握的8種網站***技術

SQL注入原理

**下面是一段普通的JDBC的Java代碼,這段代碼就可以被利用,進行SQL注入*

Connection conn = getConnection();
String sql = "select * from hhuser where nick = '" + nickname + "'" + " and passwords = '" + password + "'"; 
Statement st = (Statement) conn.createStatement();
ResultSet rs = st.executeQuery(sql);
List<UserInfo> userInfoList = new ArrayList<UserInfo>(); 
while (rs.next()) {
UserInfo userinfo = new UserInfo();         
userinfo.setUserid(rs.getLong("userid"));       
userinfo.setPasswords(rs.getString("passwords"));       
userinfo.setNick(rs.getString("nick"));         
userinfo.setAge(rs.getInt("age"));      
userinfo.setAddress(rs.getString("address"));       
userInfoList.add(userinfo);
}

當用戶輸入nick爲zhangsan,密碼爲' or '1'='1的時候,意想不到的事情出現了,頁面顯示爲login狀態:
來場戰爭如何?Java開發必須掌握的8種網站***技術

當用戶在密碼欄輸入“' or '1'='1”後,代碼中的SQL語句就會被拼接成:

"select * from hhuser user where nick = 'zhangsan' and passwords = '' or '1'='1'",因爲or後面的1=1是恆爲true的,所以,該語句的執行結果就會有正常的數據返回。從而繞過密碼校驗。

以上便是一次簡單的、典型的SQL注入。當然,SQL注入的危害不僅如此,假設用戶輸入用戶名zhangsan,在密碼框輸入' ;drop table aaa;-- 會發生什麼呢?

SQL注入的防禦

使用預編譯語句
預編譯語句PreparedStatement是java.sql中的一個接口,繼承自Statement接口。通過 Statement對象執行SQL語句時,需要將SQL語句發送給DBMS,由DBMS先進行編譯後再執行。而預編譯語句和Statement不同,在創建PreparedStatement對象時就指定了SQL語句,該語句立即發送給DBMS進行編譯,當該編譯語句需要被執行時,DBMS直接運行編譯後的SQL語句,而不需要像其他SQL語句那樣首先將其編譯。

前面介紹過,引發SQL注入的根本原因是惡意用戶將SQL指令僞裝成參數傳遞到後端數據庫執行, 作爲一種更爲安全的動態字符串的構建方法,預編譯語句使用參數佔位符來替代需要動態傳入的參數,這樣者無法改變SQL語句的結構,SQL語句的語義不會發生改變,即便用戶傳入類似於前面' or '1'='1這樣的字符串,數據庫也會將其作爲普通的字符串來處理。

使用ORM框架
由上文可見,防止SQL注入的關鍵在於對一些關鍵字符進行轉義,而常見的一些ORM框架,如 ibatis、hibernate等,都支持對相應的關鍵字或者特殊符號進行轉義,可以通過簡單的配置, 很好的預防SQL注入漏洞,降低了普通的開發人員進行安全編程的門檻。 Ibatis的insert語句配置:

<insert id="insert" parameterClass="userDO">
insert into users(gmt_create,gmt_modified,userid,user_nick,address,age,sex) values(now(),now(),#userId#,#userNick#,#address#,#age#,#sex#)
</insert>
通過#符號配置的變量,ibatis能夠對輸入變量的一些關鍵字進行轉義,防止SQL注入***。

避免密碼明文存放
對存儲的密碼進行單向Hash,如使用MD5對密碼進行摘要,而非直接存儲明文密碼,這樣的好處就是萬一用戶信息泄露,即圈內所說的被“”,無法直接獲取用戶密碼,而只能得到一串跟密碼相差十萬八千里的Hash碼。

處理好相應的異常
後臺的系統異常,很可能包含了一些如服務器版本、數據庫版本、編程語言等等的信息,甚至是數據庫連接的地址及用戶名密碼,者可以按圖索驥,找到對應版本的服務器漏洞或者數據庫漏洞進行,因此,必須要處理好後臺的系統異常,重定向到相應的錯誤處理頁面,而不是任由其直接輸出到頁面上。

上傳文件漏洞

在上網的過程中,我們經常會將一些如圖片、壓縮包之類的文件上傳到遠端服務器進行保存, 文件上傳指的是惡意者利用一些站點沒有對文件的類型做很好的校驗這樣的漏洞, 上傳了可執行的文件或者腳本,並且通過腳本獲得服務器上相應的權利,或者是通過誘導外 部用戶訪問或者下載上傳的病毒或者文件,達到目的。

爲了防範用戶上傳惡意的可執行文件和腳本,以及將文件上傳服務器當做免費的文件存儲服務器使用,需要對上傳的文件類型進行白名單(非黑名單,這點非常重要)校驗,並且限制上傳文件的大小,上傳的文件,需要進行重新命名,使者無法猜測到上傳文件的訪問路徑。

對於上傳的文件來說,不能簡單的通過後綴名稱來判斷文件的類型,因爲惡意可以將可執行文件的後綴名稱改成圖片或者其他的後綴類型,誘導用戶執行。因此,判斷文件類型需要使用更安全的方式。很多類型的文件,起始的幾個字節內容是固定的,因此,根據這幾個字節的內容,就可以確定文件類型,這幾個字節也被稱爲魔數(magic number)。

DDoS

DDoS(Distributed Denial of Service),即分佈式拒絕服務,是目前最爲強大、最難以防禦的方式之一。前不久(2018-03-01),GitHub就遭受了一次比較嚴重的DDoS,我的文章《GitHub遭受的DDoS到底是個什麼鬼?》中有關於這次和DDoS的詳細介紹。這裏不再贅述。

DDoS的有很多種類型,如依賴蠻力的ICMP Flood、UDP Flood等等,隨着硬件性能的提升,需要的機器規模越來越大,組織大規模的越來越困難,現在已經不常見,還有就是依賴協議特徵以及具體的軟件漏洞進行的,如Slowloris,Hash碰撞等等,這類主要利用協議以及軟件漏洞發起,需要在特定環境下才會出現,更多的者採用的是前面兩種的混合方式,即利用了協議、系統的缺陷,又具備了海量的流量, 如SYN Flood、DNS Query Flood等等。

DNS Query Flood

DNS Query Flood實際上是UDP Flood的一種變形,由於DNS服務在互聯網中不可替代的作用,一旦DNS服務器癱瘓,影響甚大。

DNS Query Flood採用的方法是向被的服務器發送海量的域名解析請求,通常,請求解析的域名是隨機生成,大部分根本就不存在,並且通過僞造端口和客戶端IP,防止查詢請求被ACL過濾。被的DNS服務器在接收到域名解析請求後,首先會在服務器上查找是否有對應的緩存, 由於域名是隨機生成的,幾乎不可能有相應的緩存信息,當沒有緩存,並且該域名無法直接由該DNS服務器進行解析的時候,DNS服務器會向其上層DNS服務器遞歸查詢域名信息,直到全球互聯網的13臺根DNS服務器。大量不存在的域名解析請求,給服務器帶來了很大的負載,當解析請求超過一定量的時候,就會造成DNS服務器解析域名超時,這樣者便達成了目的。

CC

CC(Challenge Collapsar)屬於DDoS的一種,是基於應用層HTTP協議發起的DDos,也被稱爲HTTP Flood。

CC的原理是這樣的,者通過控制的大量“肉雞”或者利用從互聯網上搜尋的大量匿名的HTTP代理,模擬正常用戶給網站發起請求直到該網站拒絕服務爲止。大部分網站會通過CDN以及分佈式緩存來加快服務端響應,提升網站的吞吐量,而這些精心構造的HTTP請求往往有意避開這些緩存,需要進行多次DB查詢操作或者是一次請求返回大量的數據,加速系統 資源消耗,從而拖垮後端的業務處理系統,甚至連相關存儲以及日誌收集系統也無法倖免。

最後

喜歡的可以關注我的公衆號,java小瓜哥的分享平臺,平時整理的資料都放在裏面了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章