Skip to main content

Asymmetric denial of service

Need

The solution to the vulnerability of asymmetric denial of service is the need for implementing robust security measures to prevent service outages caused by resource exhaustion.

Context

  • Usage of Python 3.6+ for developing Python applications
  • Usage of Django for building web applications

Description

Non compliant code

# server.py
from django.http import HttpResponse
from django.views import View

class AmplificationView(View):
def get(self, request, *args, **kwargs):
response = 'response' * 1000000
return HttpResponse(response)

In the above code, we have a Django view AmplificationView that responds to a GET request with a large amount of data. This is a simple simulation of an amplification attack.

When the get method is triggered by a GET request, it responds with a string 'response' repeated 1,000,000 times. This creates a large response to a very small request, thus simulating an amplification attack.

If an attacker identifies this endpoint, they can send a single small request and cause the server to generate and send a large amount of data in response. This can quickly consume server resources and potentially lead to a denial of service if the server is overwhelmed with such requests.

This code is vulnerable because it does not limit the size of the response that can be generated and sent by a single request. This allows an attacker to consume a disproportionate amount of server resources with a single small request.

Steps

  • Limit the size of the response that can be generated by a single request. This can be done by setting a maximum limit on the size of the response.
  • Implement rate limiting to prevent a single client from making too many requests in a short period of time.
  • Use a load balancer to distribute incoming requests across multiple servers, reducing the impact of a single malicious request.
  • Monitor the server for unusual activity, such as a sudden increase in the number of requests or the size of responses. This can help detect an attack early and take appropriate action.
  • Consider using a Content Delivery Network (CDN) to absorb the impact of an amplification attack.

Compliant code

# server.py
from django.http import HttpResponse
from django.views import View
from django.core.cache import cache
from ratelimit.decorators import ratelimit

class AmplificationView(View):
@ratelimit(key='ip', rate='10/m') # Limit the number of requests per minute per IP
def get(self, request, *args, **kwargs):
has_been_ratelimited = getattr(request, 'limited', False)
if has_been_ratelimited:
return HttpResponse('Too many requests', status=429)

response = 'response' * 1000 # Limit the size of the response
return HttpResponse(response)

The updated code includes several measures to prevent an asymmetric denial of service attack.

Firstly, the size of the response generated by a single request is limited. This is done by reducing the number of times the string 'response' is repeated from 1,000,000 to 1,000. This prevents an amplification attack, where a single request can generate a large response.

Secondly, rate limiting is implemented using the ratelimit decorator from the ratelimit package. This limits the number of requests that can be made from a single IP address to 10 per minute. If a client exceeds this limit, they receive a 429 'Too many requests' response. This prevents a single client from overwhelming the server with requests.

Note that this code does not include the use of a load balancer or a Content Delivery Network (CDN), as these are infrastructure solutions that cannot be implemented in the application code. However, they are recommended as additional measures to protect against denial of service attacks.

Finally, monitoring for unusual activity is also recommended, but this is not included in the code as it typically involves external logging and monitoring solutions.

References