Skip to content
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

rpc: Prevent easy memory exhaustion attack #4373

Merged
merged 1 commit into from
Jul 7, 2014

Conversation

laanwj
Copy link
Member

@laanwj laanwj commented Jun 20, 2014

Allocate memory for POST message data only as bytes come in, instead of
all at once at the beginning.

Fixes #4343.

@jgarzik
Copy link
Contributor

jgarzik commented Jun 20, 2014

Comments:

  • Agree this wants fixing.
  • Memory exhaustion in RPC is a low priority, since it's an internal control plane, not something that should be exposed to the open Internet.
  • 16k seems small. It is easy to construct a valid JSON batch request of this size. Make it 1MB.
  • During review, I noticed we use getline(), which is similarly unbounded input.

So, increase the limit and consider fixing getline() calls too.

@gavinandresen
Copy link
Contributor

So with this fix, you actually have to SEND 4GB (or whatever) of data to exhaust 4GB (or whatever) of memory, instead of just sending a header SAYING that you'll send 4GB of data.

ACK: better is better. Although did you consider just setting an arbitrary, large limit on nLen? Code would be simpler...

@jgarzik
Copy link
Contributor

jgarzik commented Jun 20, 2014

@gavinandresen Actually, very good final point. Just change the limit here:

    int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
    if (nLen < 0 || nLen > (int)MAX_SIZE)
        return HTTP_INTERNAL_SERVER_ERROR;

to 1MB.

Currently the limit is not infinite, either:

static const unsigned int MAX_SIZE = 0x02000000;

So, that's 32MB.

@jgarzik
Copy link
Contributor

jgarzik commented Jun 20, 2014

General comment: Our RPC code really wants to be smarter in any case. You can just as easily open a bunch of connections, even with the loop, and exhaust memory. Or another familiar HTTP attack is opening a bunch of connections, keeping them open for hours or days without making progress.

i.e. send one character per day across 10,000 connections. Stupid server will not timeout, and sockets will be rapidly exhausted.

@laanwj
Copy link
Member Author

laanwj commented Jun 20, 2014

Yes there is already a limit, and yes this is low priority, I was mislead by the issue description that this happened before the rpcallow check. Closing.

@laanwj laanwj closed this Jun 20, 2014
@laanwj
Copy link
Member Author

laanwj commented Jun 20, 2014

Also it's not about unbounded input, but as @gavinandresen remarks correctly that with this change you actually have to send the amount of bytes to get them allocated instead of being able to open 100 connections up-front and specifying 32 mbytes of data and keeping open the connection without actually sending it (which is very cheap to do).

@jgarzik
Copy link
Contributor

jgarzik commented Jun 20, 2014

@laanwj Agree, that is why I did not NAK the patch.

Adding a loop is fine with me... just 16k was much too low.

@sipa
Copy link
Member

sipa commented Jun 20, 2014

Untested ACK; I would raise the 16k too, though.

@laanwj laanwj reopened this Jun 21, 2014
@laanwj
Copy link
Member Author

laanwj commented Jun 21, 2014

OK, seemingly this fix-on-top-of-a-stack-of-hacks is good enough for now, will change POST_READ_SIZE to 1MiB.

Allocate memory for POST message data only as bytes come in, instead of
all at once at the beginning.

Fixes bitcoin#4343.
@laanwj
Copy link
Member Author

laanwj commented Jul 4, 2014

Rebased and changed POST_READ_SIZE to 256kiB.

@BitcoinPullTester
Copy link

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/p4373_2ec5a3d212ac4b09e6c32d495f34ee3cdedc8c66/ for binaries and test log.
This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/
Contact BlueMatt on freenode if something looks broken.

@laanwj laanwj merged commit 2ec5a3d into bitcoin:master Jul 7, 2014
laanwj added a commit that referenced this pull request Jul 7, 2014
2ec5a3d rpc: Prevent easy memory exhaustion attack (Wladimir J. van der Laan)
pyritepirate referenced this pull request in pyritepirate/pyrite Nov 29, 2018
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RPC Server blindly believes whatever you specify in content-length header and allocates data and does a read()
5 participants