Skip to main content

Improper control of interaction frequency

Need

Enforcement of rate limiting to control user interaction frequency

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing data models and database interactions
  • Usage of shelf_io for managing and organizing data storage in a Node.js application

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests()).addHandler(_echoRequest);

io.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
return shelf.Response.ok('Request for "${request.url}"');
}

In this Dart code snippet, we are using the shelf package to create a simple server that listens for incoming requests on localhost at port 8080.

The _echoRequest function is a handler that responds to any incoming request with a simple message.

The main function sets up a pipeline with a logging middleware and the _echoRequest handler. Then it starts the server with io.serve.

The vulnerability lies in the fact that there is no control over the frequency of incoming requests. Any user can send an unlimited number of requests to the server in a short period of time. This can lead to a Denial of Service (DoS) attack, where the server gets overwhelmed with too many requests, thus making it unavailable to other users.

To fix this vulnerability, we need to implement a rate limiting mechanism that limits the number of requests a user can send in a certain period of time. This can be done by adding a rate limiting middleware to the pipeline.

Steps

  • Import a rate limiting package such as 'shelf_rate_limiter'.
  • Create a rate limiter instance specifying the maximum number of requests allowed in a certain time period.
  • Add the rate limiter as a middleware to the shelf pipeline.

Compliant code

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_rate_limiter/shelf_rate_limiter.dart';

void main() {
var rateLimiter = RateLimiter(100, Duration(minutes: 1)); // Allow 100 requests per minute
var handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addMiddleware(rateLimiter.middleware)
.addHandler(_echoRequest);

io.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
return shelf.Response.ok('Request for "${request.url}"');
}

The code above is a Dart backend application using the Shelf framework. The vulnerability of improper control of interaction frequency was present in the original code, as it did not limit the number of requests a user could send to the server in a short period of time.

To fix this vulnerability, we have added a rate limiter to the application. The rate limiter is a middleware that limits the number of requests a user can make in a certain time period. In this case, we have set the rate limiter to allow a maximum of 100 requests per minute.

The rate limiter is added to the Shelf pipeline using the addMiddleware method. This ensures that every request that comes into the server goes through the rate limiter before it reaches the request handler.

When a user exceeds the maximum number of requests, the rate limiter will automatically respond with a 429 (Too Many Requests) status code. This prevents the server from being overwhelmed by too many requests and helps to maintain the performance and reliability of the application.

References