攻擊JavaWeb應用[2]-CS互動安全

wyzsk發表於2020-08-19
作者: 園長 · 2013/07/08 14:54

注:本節意在讓大家瞭解客戶端和伺服器端的一個互動的過程,我個人不喜歡xss,對xss知之甚少所以只能簡要的講解下。這一節主要包含HttpServletRequest、HttpServletResponse、session、cookie、HttpOnly和xss,文章是年前幾天寫的本應該是有續集的但年後就沒什麼時間去接著續寫了。由於工作並非安全行業,所以寫的並不算專業希望大家能夠理解。後面的章節可能會有Java裡的SQL隱碼攻擊、Servlet容器相關、Java的框架問題、eclipse程式碼審計等。

0x00 Request & Response(請求與響應)


請求和響應在Web開發當中沒有語言之分不管是ASP、PHP、ASPX還是JAVAEE也好,Web服務的核心應該是一樣的。

在我看來Web開發最為核心也是最為基礎的東西就是Request和Response!我們的Web應用最終都是面向使用者的,而請求和響應完成了客戶端和伺服器端的互動。 伺服器的工作主要是圍繞著客戶端的請求與響應的。

如下圖我們透過Tamper data攔截請求後可以從請求頭中清晰的看到發出請求的客戶端請求的地址為:localhost。

瀏覽器為FireFox,作業系統為Win7等資訊,這些是客戶端的請求行為,也就是Request。
 

enter image description here

當客戶端傳送一個Http請求到達伺服器端之後,伺服器端會接受到客戶端提交的請求資訊(HttpServletRequest),然後進行處理並返回處理結(HttpServletResopnse)。

下圖演示了伺服器接收到客戶端傳送的請求頭裡麵包含的資訊:


enter image description here



頁面輸出的內容為:


host=localhost

user-agent=Mozilla/5.0 (Windows NT 6.1; rv:18.0) Gecko/20100101 Firefox/18.0

accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

accept-language=zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3

accept-encoding=gzip, deflate

connection=keep-alive

請求頭資訊偽造XSS

關於偽造問題我是這樣理解的:傳送Http請求是客戶端的主動行為,伺服器端透過ServerSocket監聽並按照Http協議去解析客戶端的請求行為。

所以請求頭當中的資訊可能並不一定遵循標準Http協議。

用FireFox的Tamper Data和Moify Headers(FireFox擴充套件中心搜Headers和Tamper Data都能找到) 外掛修改下就實現了,請先安裝FireFox和Tamper Data:

 

 點選Start Tamper 然後請求Web頁面,會發現請求已經被Tamper Data攔截下來了。選擇Tamper:

enter image description here

點選Start Tamper 然後請求Web頁面,會發現請求已經被Tamper Data攔截下來了。選擇Tamper:

enter image description here

修改請求頭資訊:


enter image description here


Servlet Request接受到的請求:

Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
    String name = (String) e.nextElement();//獲取key
    String value = request.getHeader(name);//得到對應的值
    out.println(name + "=" + value + "<br>");//輸出如cookie=123
}
    

enter image description here

原始碼下載:http://pan.baidu.com/share/link?shareid=166499&uk=2332775740

使用Moify Headers自定義的修改Headers:

enter image description here

enter image description here

enter image description here

修改請求頭的作用是在某些業務邏輯下程式猿需要去記錄使用者的請求頭資訊到資料庫,而透過偽造的請求頭一旦到了資料庫可能造成xss,或者在未到資料庫的時候就造成了SQL隱碼攻擊,因為對於程式設計師來說,大多數人認為一般從Headers裡面取出來的資料是安全可靠的,可以放心的拼SQL(記得好像Discuz有這樣一個漏洞)。今年一月份的時候我發現xss.tw也有一個這樣的經典案例,Wdot那哥們在記錄使用者的請求頭資訊的時候沒有去轉意特殊的指令碼,導致我們透過偽造的請求頭直接儲存到資料庫。

XSS.tw平臺由於沒有對請求頭處理導致可以透過XSS屌絲逆襲高富黑。
剛回來的時候被隨風玩爆菊了。透過修改請求頭資訊為XSS指令碼,xss那平臺直接接收並信任引數,因為很少有人會蛋疼的去懷疑請求頭的資訊,所以這裡造成了儲存型的XSS。只要別人一登入xss就會自動的執行我們的XSS程式碼了。

Xss.tw由於ID很容易預測,所以很輕易的就能夠影響到所有使用者:

enter image description here

於是某一天就有了所有的xss.tw使用者被隨風那2貨全部彈了www.gov.cn: 

enter image description here

Java裡面偽造Http請求頭

程式碼就不貼了,在傳送請求的時候設定setRequestProperty 就行了,如:

URL realUrl = new URL(url);
URLConnection connection = realUrl.openConnection();
connection.setConnectTimeout(5000);//連線超時
connection.setReadTimeout(5000);// 讀取超時
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
(………………………..)

enter image description here

Test Servlet:

enter image description here

0x01 Session


Session是儲存於伺服器記憶體當中的會話,我們知道Http是無狀態協議,為了支援客戶端與伺服器之間的互動,我們就需要透過不同的技術為互動儲存狀態,而這些不同的技術就是Cookie和Session了。

設定一個session:

session.setAttribute("name",name);//從請求中獲取使用者的name放到session當中

session.setAttribute("ip",request.getRemoteAddr());//獲取使用者請求Ip地址
out.println("Session 設定成功.");

enter image description here

直接獲取session如下圖可以看到我們用FireFox和Chrome請求同一個URL得到的SessionId並不一樣,說明SessionId是唯一的。一旦Session在伺服器端設定成功那麼我們在此次回話當中就可以一直共享這個SessionId對應的session資訊,而session是有有效期的,一般預設在20-30分鐘,你會看到xss平臺往往有一個功能叫keepSession,每過一段時間就帶著sessionId去請求一次,其實就是在保持session的有效不過期。

enter image description here

enter image description here

Session 生命週期(從建立到銷燬)



1、session的預設過期時間是30分鐘,可修改的最大時間是1440分鐘(1440除以60=24小時=1天)。


2、伺服器重啟或關閉Session失效。


注:瀏覽器關閉其實並不會讓session失效!因為session是儲存在伺服器端記憶體當中的。客戶端把瀏覽器關閉了伺服器怎麼可能知道?正確的解釋或許應該是瀏覽器關閉後不會去記憶關閉前客戶端和伺服器端之間的session資訊且伺服器端沒有將sessionId以Cookie的方式寫入到客戶端快取當中,重新開啟瀏覽器之後並不會帶著關閉之前的sessionId去訪問伺服器URL,伺服器從請求中得不到sessionId自然給人的感覺就是session不存在(自己理解的)。

當我們關閉伺服器時Tomcat會在安裝目錄workCatalinalocalhost專案名目錄下建立SESSIONS.ser檔案。此檔案就是Session在Tomcat停止的時候 持久化到硬碟中的檔案. 所有當前訪問的使用者Session都儲存到此檔案中. Tomcat啟動成功後.SESSIONS.ser  又會反序列化到記憶體中,所以啟動成功後此檔案就消失了. 所以正常情況下 從啟Tomcat使用者是不需要登入的. 注意有個前提,就是儲存到Session裡面的user物件所對應的User類必須要序列化才可以。(摘自:http://alone-knight.iteye.com/blog/1611112

SessionId是神馬?有什麼用?



我們不妨來做一個偷取sessionId的實驗:
首先訪問:http://localhost/Test/SessionTest?action=setSession&name=selina 完成session的建立,如何建立就不解釋瞭如上所述。


同時開啟FireFox和Chrome瀏覽器設定兩個Session:

 



enter image description here

我們來看下當前使用者的請求頭分別是怎樣的:

 

enter image description here



我們依舊用TamperData來修改請求的Cookie當中的jsessionId,下面是見證奇蹟的時刻:



enter image description here

我要說的話都已經在圖片當中的文字註釋裡面了,偉大的Xss駭客們看明白了嗎?你盜取的也許是jsessionId(Java裡面叫jsessionId),而不只是cookie。那麼假設我們的Session被設定得特別長那麼這個SessionId就會長時間的保留,而為Xss攻擊提供了得天獨厚的條件。而這種Session長期存在會浪費伺服器的記憶體也會導致:SessionFixation攻擊!



如何應對SessionFixation攻擊



1、使用者輸入正確的憑據,系統驗證使用者並完成登入,並建立新的會話ID。


2、Session會話加Ip控制


3、加強程式設計師的防範意識:寫出明顯xss的程式設計師記過一次,寫出隱晦的xss的程式設計師警告教育一次,連續查出存在3個及其以上xss的程式設計師理解解除勞動合同(哈哈,開玩笑了)。

0x02 Cookie


Cookie是以檔案形式[快取在客戶端]的憑證(精簡下為了通俗易懂),cookie的生命週期主要在於伺服器給設定的有效時間。如果不設定過期時間,則表示這個cookie生命週期為瀏覽器會話期間,只要關閉瀏覽器視窗,cookie就消失了。
這次我們以IE為例:

enter image description here


我們來建立一個Cookie:



if(!"".equals(name)){

           Cookie cookies = new Cookie("name",name);//把使用者名稱放到cookie

           cookies.setMaxAge(60*60*60*12*30) ;//設定cookie的有效期

    //     c1.setDomain(".ahack.net");//設定有效的域
    
       response.addCookie(cookies);//把Cookie儲存到客戶端

           out.println("當前登入:"+name);
}else {

           out.println("使用者名稱不能為空!");
    
}

有些大牛級別的程式設計師直接把帳號密碼明文儲存到客戶端的cookie裡面去,不得不佩服其功力深厚啊。客戶端直接記事本開啟就能看到自己的帳號密碼了。

enter image description here


繼續讀取Cookie:

enter image description here

我想cookie以明文的形式儲存在客戶端我就不用解釋了吧?檔案和資料擺在面前!
盜取cookie的最直接的方式就是xss,利用IE瀏覽器輸出當前站點的cookie:

javascript:document.write(document.cookie)
    
    

enter image description here



首先我們用FireFox建立cookie:


enter image description here

然後TamperData修改Cookie:

enter image description here

一般來說直接把cookie傳送給伺服器伺服器,程式設計師過度相信客戶端cookie值那麼我們就可以在不用知道使用者名稱和密碼的情況下登入後臺,甚至是cookie注入。jsessionid也會放到cookie裡面,所以拿到了cookie對應的也拿到了jsessionid,拿到了jsessionid就拿到了對應的會話當中的所有資訊,而如果那個jsessionid恰好是管理員的呢?

0x03 HttpOnly


上面我們用

javascript:document.write(document.cookie)

透過document物件能夠拿到儲存於客戶端的cookie資訊。

HttpOnly設定後再使用document.cookie去取cookie值就不行了。

透過新增HttpOnly以後會在原cookie後多出一個HttpOnly;

普通的cookie設定:

Cookie: jsessionid=AS348AF929FK219CKA9FK3B79870H;

加上HttpOnly後的Cookie:

Cookie: jsessionid=AS348AF929FK219CKA9FK3B79870H; HttpOnly;

(參考YearOfSecurityforJava)

在JAVAEE6的API裡面已經有了直接設定HttpOnly的方法了:  enter image description here

API的對應說明:

大致的意思是:如果isHttpOnly被設定成true,那麼cookie會被標識成HttpOnly.能夠在一定程度上解決跨站指令碼攻擊。  enter image description here

在servlet3.0開始才支援直接透過setHttpOnly設定,其實就算不是JavaEE6也可以在set Cookie的時候加上HttpOnly; 讓瀏覽器知道你的cookie需要以HttpOnly方式管理。而ng a 在新的Servlet當中不只是能夠透過手動的去setHttpOnly還可以透過在web.xml當中新增cookie-config(HttpOnly預設開啟,注意配置的是web-app_3_0.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <session-config>
        <cookie-config>
            <http-only>true</http-only>
            <secure>true</secure>
        </cookie-config>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

還可以設定下session有效期(30分):

<session-timeout>30</session-timeout>

0x04 CSRF (跨站域請求偽造)


CSRF(Cross Site Request Forgery, 跨站域請求偽造)使用者請求偽造,以受害人的身份構造惡意請求。(經典解析參考:http://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/ )

CSRF 攻擊的物件

在討論如何抵禦 CSRF 之前,先要明確 CSRF 攻擊的物件,也就是要保護的物件。從以上的例子可知,CSRF 攻擊是駭客藉助受害者的 cookie 騙取伺服器的信任,但是駭客並不能拿到 cookie,也看不到 cookie 的內容。另外,對於伺服器返回的結果,由於瀏覽器同源策略的限制,駭客也無法進行解析。因此,駭客無法從返回的結果中得到任何東西,他所能做的就是給伺服器傳送請求,以執行請求中所描述的命令,在伺服器端直接改變資料的值,而非竊取伺服器中的資料。所以,我們要保護的物件是那些可以直接產生資料改變的服務,而對於讀取資料的服務,則不需要進行 CSRF 的保護。比如銀行系統中轉賬的請求會直接改變賬戶的金額,會遭到 CSRF 攻擊,需要保護。而查詢餘額是對金額的讀取操作,不會改變資料,CSRF 攻擊無法解析伺服器返回的結果,無需保護。

Csrf攻擊方式

物件:A:普通使用者,B:攻擊者

1、假設A已經登入過xxx.com並且取得了合法的session,假設使用者中心地址為:http://xxx.com/ucenter/index.do
2、B想把A餘額轉到自己的賬戶上,但是B不知道A的密碼,透過分析轉賬功能發現xxx.com網站存在CSRF攻擊漏洞和XSS漏洞。
3、B透過構建轉賬連結的URL如:http://xxx.com/ucenter/index.do?action=transfer&money=100000 &toUser=(B的帳號),因為A已經登入了所以後端在驗證身份資訊的時候肯定能取得A的資訊。B可以透過xss或在其他站點構建這樣一個URL誘惑A去點選或觸發Xss。一旦A用自己的合法身份去傳送一個GET請求後A的100000元人民幣就轉到B賬戶去了。當然了在轉賬支付等操作時這種低階的安全問題一般都很少出現。

防禦CSRF:

驗證 HTTP Referer 欄位
在請求地址中新增 token 並驗證
在 HTTP 頭中自定義屬性並驗證
加驗證碼
 (copy防禦CSRF毫無意義,參考上面給的IBM專題的URL)

最常見的做法是加token,Java裡面典型的做法是用filter:https://code.google.com/p/csrf-filter/(連結由plt提供,原始碼上面的在:http://ahack.iteye.com/blog/1900708)

CSRF的介紹drops已有文章,可以參考:/papers/?id=155

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章