2

I'm dealing with the library qs in Node.js, which lets you stringify and parse query strings.

For example, if I want to send a query with an array of items, I would do qs.stringify({ items: [1,2,3] }), which would send this as my query string:

http://example.com/route?items[0]=1&items[1]=2&items[2]=3

(Encoded URI would be items%5B0%5D%3D1%26items%5B1%5D%3D2%26items%5B2%5D%3D3)

When I do qs.parse(url) on the server, I'd get the original object back:

let query = qs.parse(url) // => { items: [1,2,3] }

However, the default size of the array for qs is limited to 20, according to the docs:

qs will also limit specifying indices in an array to a maximum index of 20. Any array members with an index of greater than 20 will instead be converted to an object with the index as the key

This means that if I have more than 20 items in the array, qs.parse will give me an object like this (instead of the array that I expected):

{ items: { '0': 1, '1': 2 ...plus 19 more items } }

I can override this behavior by setting a param, like this: qs.parse(url, { arrayLimit: 1000 }), and this would allow a max array size of 1,000 for example. This would, thus, turn an array of 1,001 items into a plain old JavaScript object.

According to this github issue, the limit might be for "security considerations" (same in this other github issue).

My questions:

  1. If the default limit of 20 is meant to help mitigate a DoS attack, how does turning an array of over 20 items into a plain old JavaScript object supposed to help anything? (Does the object take less memory or something?)
  2. If the above is true, even if there is an array limit of, say, 20, couldn't the attacker just send more requests and still get the same DoS effect? (The number of requests necessary to be sent would decrease linearly with the size limit of the array, I suppose... so I guess the "impact" or load of a single request would be lower)
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
  • 1
    *Use of this directive mitigates the possibility of denial of service attacks **which use hash collisions**.* Source: http://php.net/manual/en/info.configuration.php#ini.max-input-vars – Jared Farrish Feb 23 '17 at 00:09
  • 1
    And: *If the language does not provide a randomized hash function or the application server does not recognize attacks using multi-collisions, an attacker can degenerate the hash table by sending lots of colliding keys. The algorithmic complexity of inserting n elements into the table then goes to O(n**2), making it possible to exhaust hours of CPU time using a single HTTP request.* Source: https://arstechnica.com/business/2011/12/huge-portions-of-web-vulnerable-to-hashing-denial-of-service-attack/ – Jared Farrish Feb 23 '17 at 00:13
  • 1
    And at least here, this says PHP's `json_decode()` (I'm a PHP developer) is susceptible to hash collisions same as GPC, so it is a question why it is any better: http://lukasmartinelli.ch/web/2014/11/17/php-dos-attack-revisited.html Although Node might have safeguards in place. – Jared Farrish Feb 23 '17 at 00:27
  • 1
    See [Max length of http get request](http://stackoverflow.com/questions/2659952/maximum-length-of-http-get-request). Various servers and clients protect themselves from arbitrary length requests so they don't run any risk of a buffer overflow or unusually large memory usage (which could be used as a DoS attack) by enforcing a limit to the max length of an URL that they will process. If you want larger payloads, use a POST instead of a GET and put the data in the body. – jfriend00 Feb 23 '17 at 03:04
  • 1
    @jfriend00 - At least in PHP, the limitation to the number of array indices/keys is 1000 whether it's G, P or C. The OP is talking about array construction, not GET request length. – Jared Farrish Feb 23 '17 at 03:54
  • 1
    I see this comment in the qs documentation: "The depth limit helps mitigate abuse when qs is used to parse user input, and it is recommended to keep it a reasonably small number." – jfriend00 Feb 23 '17 at 04:03
  • Thank you for the comments. Seems I have a bit of reading to do :) – Josh Beam Feb 24 '17 at 18:21

0 Answers0