logo

Improper control of interaction frequency - Dart


Need

Enforcement of rate limiting to control user interaction frequency


Context

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

Description

Insecure Code Example

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

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

Secure Code Example

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

  • 108 - Improper control of interaction frequency

  • Last updated

    2023/09/18