-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[UNDERTOW-2451] fix the information leakage issues #1668
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,8 +73,6 @@ public class HpackDecoder { | |
|
||
private boolean first = true; | ||
|
||
private final StringBuilder stringBuilder = new StringBuilder(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no leakage in this class either. In this case, we are reusing the same builder across multiple decode invocations, but we are clearing the buffer right after we use it on every call. It just prevents us from having to create a new builder everytime we are invoked, which is a good thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The root cause for this leak is very similar to the vulnerability CVE-2020-17527 in Tomcat. I added additional details at https://issues.redhat.com/browse/UNDERTOW-2451. |
||
|
||
public HpackDecoder(int maxAllowedMemorySize) { | ||
this.specifiedMemorySize = Math.min(Hpack.DEFAULT_TABLE_SIZE, maxAllowedMemorySize); | ||
this.maxAllowedMemorySize = maxAllowedMemorySize; | ||
|
@@ -247,11 +245,11 @@ private String readHpackString(ByteBuffer buffer) throws HpackException { | |
if (huffman) { | ||
return readHuffmanString(length, buffer); | ||
} | ||
StringBuilder stringBuilder = new StringBuilder(length); | ||
BFionaccept marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (int i = 0; i < length; ++i) { | ||
stringBuilder.append((char) (buffer.get() & 0xFF)); | ||
} | ||
String ret = stringBuilder.toString(); | ||
stringBuilder.setLength(0); | ||
if (ret.isEmpty()) { | ||
//return the interned empty string, rather than allocating a new one each time | ||
return ""; | ||
|
@@ -260,12 +258,12 @@ private String readHpackString(ByteBuffer buffer) throws HpackException { | |
} | ||
|
||
private String readHuffmanString(int length, ByteBuffer buffer) throws HpackException { | ||
StringBuilder stringBuilder = new StringBuilder(length); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. final ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this fix, I referenced the patch for a similar vulnerability (CVE-2020-17527) in the corresponding functional module of Tomcat, as shown in this commit: apache/tomcat@d56293f#diff-98723542790b05d2e3c2dadeef7c632e641e3118b3b809660e9b1ef41686cfe0R226. I removed the Certainly, I think it is also acceptable to retain the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I’m sorry, I accidentally deleted a previous conversation. |
||
HPackHuffman.decode(buffer, length, stringBuilder); | ||
String ret = stringBuilder.toString(); | ||
if (ret.isEmpty()) { | ||
return ""; | ||
} | ||
stringBuilder.setLength(0); | ||
return ret; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't remove currentString here. The parser is invoked multiple times as bytes are made available and, when the last byte is read, it wil need the whole currentString to form a parsed result, it will neeed information from previous parse invocations. Otherwise, you risk losing bytes. It all depends on how many bytes the parser has received on every invocation.