none
Denial of Service - The call to ReadToEnd() might allow an attacker to crash the program or otherwise make it unavailable to legitimate users. RRS feed

  • Question

  • Hi All,

    I have got this error under security scanning with ReadToEnd() method. Can anyone suggest how can I fix this issue?

    Friday, December 7, 2018 3:43 AM

Answers

All replies

  • Content Removed
    Friday, December 7, 2018 4:22 AM
  • Thank you very much for your inputs Andrew.
    Friday, December 7, 2018 5:01 AM
  • Hi Andrew,

    We are taking the text from the URL parameters...So, it shouldn't be an issue right?

    Thanks,

    Sri

    Friday, December 7, 2018 5:11 AM
  • Content Removed
    Friday, December 7, 2018 5:24 AM
  • hi andrew, can you share how to pass this security risk ?

    The call to ReadToEnd() might allow an attacker to crash the program or otherwise make it unavailable to legitimate users.

    Tuesday, March 19, 2019 7:52 AM
  • hi andrew, can you share how to pass this security risk ?

    The call to ReadToEnd() might allow an attacker to crash the program or otherwise make it unavailable to legitimate users.

    Anyone can spin up a sockets program, in any OS and/or any programming or scripting language, that makes HTTP Requests.

    At that point the way HTTP works is that you open a TCP connection on a particular port (let's say 80), and the server responds by opening a connection back to the requestor.  Different HTTP Request or Packet types may or may not have content attached.  Different HTTP Platforms may or may not appropriately cut off transmitters who deliberately attempt to send more than a reasonable-length URI aka URL (which isn't standardized outside of individual servers, such as that Microsoft IIS has one URI char limit while Apache has a different URI char limit).

    Anyone with 10 minutes to kill and bad intentions can spin up a custom HTTP Request that connects to your server and starts pumping an endless amount of data.  They could pump random characters into the Method Name, URI field, or HTTP Version section of an HTTP Packet's first line forever, for example:

    GET /adklkho9iueaiunm/vhpo7ayeh/poqueiy/ddkh<ad infinitum>

    As long as they never transmit 0x0d0a (aka \r\n) an HTTP Server that wasn't configured (or able to be configured) to cut off at for example a 2048 character limit would keep recording the incoming characters as a URI request.  Even if your HTTP Server was testing each incoming character for invalid path chars, all the malicious programmer had to do is clamp their random generator to valid path chars.  Even if your HTTP Server was testing at each / separator if the previous bit represented a valid path, all the malicious programmer would have to do is throw in a ? and then continue piping fake parameters.

    For that matter, any HTTP Server that's worth using won't limit you to just the HTTP Methods specified by W3C, when it passes through to CGI (ie your custom backend code).  It should allow you to create your own HTTP Methods if you so desire.  So if your HTTP Server is better than Fischer Price, an attacker could send an infinitely long method name too.

    Attackers could do the same sending a POST request and then beginning a content pipeline without specifying a Content-Length header to tell the server when it intends to stop.  You may be able to configure your HTTP Server to check for this header in POSTs, but do you really want to keep that in mind at setup-time (and risk forgetting a step every single time you set up your webserver on new equipment, or reset to defaults during a troubleshoot) or is it a better idea to just account for it in CGI and then not worry about whether the server's doing it or not?

    So to consider your own CGI/Backend code "secure" you can't assume that the server does any of this clamping for you.  You have to know your own OS's character limit for physical filepaths, and you have to pick a reasonable number of characters to read and let that be a hard limit.  So where your standard HTTP Request packet should look like (for example):

    METHOD(whitespace)URI(whitespace)HTTP/1.0(\r\n)

    Your code should read (up to maximum HTTP Method Characters, let's say 12 since that's reasonably longer than the longest currently standard HTTP Method name) and if it doesn't hit a whitespace by that time then you must forcibly close the connection by signalling the server that something went wrong - let's say you kick back HTTP Status 405 (invalid method).

    If instead you validate to a standard or custom HTTP Method within the first 12 characters, you now start reading the URI.  Let's say 2048 is a maximum character length for URIs, which should give you plenty of space for all valid filepath components plus a good number of Request Parameters (such as follow a ? in a URI).  If you don't hit another (whitespace) by 2048, kick back a 400 (bad request).  It might be handy if your CGI code specifies "URI too long."

    Finally you have to do the same for the HTTP Version specifier, but this time you're looking for up to Maximum Characters followed by 0x0d0a or \r\n.

    Acknowledging that bugs occur in all software and you have no way of knowing whether the next update will contain bugs that allow attackers to exploit these kinds of holes, using ReadToEnd() assumes either that the server will clamp or else assumes that all requestors will always do everything correctly and without malice.

    If ReadToEnd() ever did wind up infinitely sucking up randomly generated characters this way, it really wouldn't take much for an attacker to lock out all other users just by tying up all your available sockets with garbage connections.  There are only 65536 available TCP ports to begin with, and only the ones from 45000 to 65535 should ever be grabbed by any given server platform to make a new "client socket" for incoming connections.

    In cases where your server accepts and communicates only on Port 80 with all requestors, it would take several thousands less such malicious connections to bind up your network buffers and slow  communications to a crawl.

    In all events, you're effectively doing (or allowing anyone else to do) the following with your webserver/CGI code when you call Stream.ReadToEnd():

                Random randchar = new Random();
                string mystring = string.Empty;
                do
                {
                    mystring += (char)randchar.Next(0x61, 0x7a); // minimum value of lowercase 'a', maximum value of lowercase 'z'
                } while (true);

    The fix is simply:

                Random randchar = new Random();
                string mystring = string.Empty;
                do
                {
                    mystring += (char)randchar.Next(0x61, 0x7a); // minimum value of lowercase 'a', maximum value of lowercase 'z'
                    if (mystring.Length >= 2048) { break; }
                } while (true);



    Monday, April 1, 2019 12:33 AM
  • if u rectify this issue..please let me know the solution of those issue
    Friday, October 18, 2019 4:54 AM