ASP.NET File Upload: How to prevent network clogging

Denial of service is one of the threats that you need to consider while implementing file upload functionality in your web application. If a user uploads a huge file, it will clog the network and consume server’s memory.

Let us look at what happens under the hood when a file is uploaded. When a form with an “input type=file” element is submitted, the entire file is posted to the server as a HTTP POST request.

Internally the browser opens up a TCP connection with the server on port 80 to send the posted data. After establishing the TCP connection, the client begins to transfer the data. There is a limit to the data (usually 64KB) that the transport layer on the client can transfer to the server without receiving an acknowledgement from the transport layer on the server. The transport layer on the server buffers this received data and transfers it to the application which is listening on port 80, which in this case is IIS. After transferring it to the application layer (IIS in this case), the transport layer sends an acknowledgement to the client’s transport layer, which can then send more data.

IIS, as it receives this data, checks the extension of the POST request. Since it is .aspx and since .aspx extension maps to the aspnet_isapi dll, IIS passes on the request to this dll. This aspnet_isapi dll continues to read data from the TCP connection, and as a chunk of data is read, passes it to the ASP.NET engine using named pipes.

The first thing that the ASP.NET engine does is to compare the “Content Length” header which is a part of the HTTP request (underlined in the picture), with the MaxRequestLength attribute in the <httpruntime> setting. If the content length is greater, it immediately throws the “Max Request Length exceeded” exception. Note that when the ASP.NET engine reads the header, a part of the request is still being transferred on the network.

As soon as the ISAPI dll gets notification of this exception, it closes the TCP connection with the client. No more data is transferred on the network for this request. This is why the MaxRequestLength attribute in the <httpruntime> section is the correct method of restricting file size in ASP.NET, and it restricts both network clogging and excessive server memory usage.

The below table shows actual bytes transferred from the client to the server (recorded using a network protocol analyzer) by varying the upload file size.

Uploaded file size (KB)

MaxRequestLength (KB)

Bytes actually transferred on network (KB)

800

1000

800

1100

1000

127

2000

1000

127

12000

1000

127

30000

1000

127

Summary: If a file with size more than the MaxRequestLength setting is uploaded, the actual bytes transferred on the network is only about 120-150KB. By this time, the ASP.NET engine reads the content length header, knows that the incoming request is too large and throws an exception which causes the TCP connection to close. So using <httpruntime MaxRequestLength=value> is how you can prevent network clogging and excessive use of server memory while implementing a file upload functionality.

References:-

https://www.ietf.org/rfc/rfc1867.txt

https://support.microsoft.com/kb/295626

https://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/regentry/58813.mspx?mfr=true

Varun Sharma

Security Engineer

Microsoft – ACE Team

varun dot sharma at microsoft dot com