Bug 497604 - Memory exhaustion when anonymous cloning is allowed
Summary: Memory exhaustion when anonymous cloning is allowed
Status: NEW
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P3 critical (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-09 05:55 EDT by scriptalertHello script CLA
Modified: 2016-07-14 13:09 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description scriptalertHello script CLA 2016-07-09 05:55:11 EDT
I can still explain the cause here :

The error lies in org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java in the recvWants() method :
 for (;;) {
 String line;
 try {
 line = pckIn.readString();
 } catch (EOFException eof) {
 if (isFirst)
 break;
 throw eof;
 }

 if (line == PacketLineIn.END)
 break;

 if (line.startsWith("deepen ")) { //$NON-NLS-1$
 depth = Integer.parseInt(line.substring(7));
 continue;
 }

 if (line.startsWith("shallow ")) { //$NON-NLS-1$
 clientShallowCommits.add(ObjectId.fromString(line.substring(8)));
 continue;
 }

 if (!line.startsWith("want ") || line.length() < 45) //$NON-NLS-1$
 throw new PackProtocolException(MessageFormat.format(JGitText.get().expectedGot, "want", line)); //$NON-NLS-1$

 if (isFirst) {
 if (line.length() > 45) {
 FirstLine firstLine = new FirstLine(line);
 options = firstLine.getOptions();
 line = firstLine.getLine();
 } else
 options = Collections.emptySet();
 }

 wantIds.add(ObjectId.fromString(line.substring(5)));
 isFirst = false;
 }
So it‘s clear, it only makes sure that elements are sha1. The variable which interest is wantIds (though clientShallowCommits would also work) :
 line 265
/** Raw ObjectIds the client has asked for, before validating them. */
 private final Set<ObjectId> wantIds = new HashSet<ObjectId>();
 Which clearly states that a WantNotValidException won’t be raised before the client sends 00000009done
As wantIds is stored in ram, a single request can fill up to 40×2.5Go (though only in theory because things gets slower as the list grow bigger because of the HashSet type).

 While this looks to be fully the expected behaviour, please note libgit2 and the official git project don’t behave that way by terminating the connection as soon the client sends a valid but non existing sha1 (considering this as a risk).

 Attack scenario:
 As this vulnerability works on cloning, there’s no mitigating factors that can work on an authentication side.

 Several connections are required in order to bypass the cpu stalls due to the use HashSet. So the attack scenario is a classical botnet one where each zombie sends data (to the limit of concurrent git-upload-pack connections allowed per ip) : but as this vulnerability makes things worst, less than 100 internet connections can render a Jgit repository inaccessible (including for pushing) several days after the end of the attack.