rpc: Prevent easy memory exhaustion attack #4373

pull laanwj wants to merge 1 commits into bitcoin:master from laanwj:2014_04_rpc_memory_exhaustion changing 1 files +14 −2
  1. laanwj commented at 1:23 PM on June 20, 2014: member

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

    Fixes #4343.

  2. jgarzik commented at 2:31 PM on June 20, 2014: contributor

    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.

  3. gavinandresen commented at 2:35 PM on June 20, 2014: 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...

  4. jgarzik commented at 2:42 PM on June 20, 2014: contributor

    @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.

  5. jgarzik commented at 2:45 PM on June 20, 2014: contributor

    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.

  6. laanwj commented at 2:47 PM on June 20, 2014: member

    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.

  7. laanwj closed this on Jun 20, 2014

  8. laanwj commented at 2:49 PM on June 20, 2014: member

    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).

  9. jgarzik commented at 2:55 PM on June 20, 2014: contributor

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

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

  10. sipa commented at 10:39 PM on June 20, 2014: member

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

  11. laanwj reopened this on Jun 21, 2014

  12. laanwj commented at 8:03 AM on June 21, 2014: member

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

  13. rpc: Prevent easy memory exhaustion attack
    Allocate memory for POST message data only as bytes come in, instead of
    all at once at the beginning.
    
    Fixes #4343.
    2ec5a3d212
  14. laanwj commented at 7:23 AM on July 4, 2014: member

    Rebased and changed POST_READ_SIZE to 256kiB.

  15. BitcoinPullTester commented at 8:05 AM on July 4, 2014: none

    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.

  16. laanwj merged this on Jul 7, 2014
  17. laanwj closed this on Jul 7, 2014

  18. laanwj referenced this in commit ebb37a417a on Jul 7, 2014
  19. pyritepirate referenced this in commit 435d4939a5 on Nov 29, 2018
  20. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me