Skip to content

Security

This section explains how to harden lilya based projects. It explains how to use the security features and common attack vectors.

Host limiting

Problem

We have no public API and the project should only serve for a specific host (dns name). We don't want other traffic which could maybe originate from a ddos.

Solution

The TrustedHostMiddleware can solve the problem. Here we can either block or mark wrong hosts. Its usage is descriped in TrustedHostMiddleware.

The Challenge of URL-Reflected Search and Malicious Injections

Problem

We sometimes need to implement a search function where the query is reflected in the URL bar, similar to Google's behavior. This allows other modules in a project to easily reference the search term.

The Security Risk: Arbitrary Text Injection A significant concern with this approach is the potential for scammers to inject arbitrary text blocks into the URL, even if properly escaped. This can be used to trick users, especially since modern search boxes are often highly customized and visually appealing.

For example, a scammer could inject text like "Call XY for help" into the URL. Users might mistakenly believe this text is part of the legitimate website content rather than solely a component of their search query, leading to convincing and harmful social engineering attacks.

Solution

Enhancing Security with TrustedReferrerMiddleware The TrustedReferrerMiddleware is a good tool for mitigating the risk of malicious parameter injection. This middleware can be used to validate that a referral was only from a legitimate hosts. So the GET parameters can be used safely.

By default, the middleware injects referrer_is_trusted into the request scope. This allows your application to:

  • Display a warning to the user.
  • Trigger an import dialog.
  • Simply ignore GET parameters from untrusted referrers.

This provides a robust defense against arbitrary text injection but still allows comfortable linking.

from __future__ import annotations

from lilya.apps import Lilya
from lilya.middleware import DefineMiddleware
from lilya.middleware.trustedreferrer import TrustedReferrerMiddleware
from lilya.routing import Include, Path
from lilya.requests import Request
from lilya.responses import Response

async def safe_get_search(request: Request) -> Response:
    search_param = ""
    if request.scope["referrer_is_trusted"]:
        search_param = request.query_params["q"]
    return Response(f"Search for {search_param}.")


routes = [Path("/", handler=safe_get_search)]


app = Lilya(routes=routes, middleware=[
    DefineMiddleware(TrustedReferrerMiddleware, allowed_referrers=["example.com"])
])

Resource exhaustion

Problem

Some calls are quite expensive. An automated caller can clog up server resources.

Solution

Rate Limiting in Lilya: Leveraging the ClientIPMiddleware

Currently, Lilya provides foundational building blocks for implementing rate limiting. We can utilize the ClientIPMiddleware to extract the client's IP address, which then serves as a crucial identifier for applying rate-limiting policies. This allows us to control the rate of requests based on individual client IPs, preventing abuse and ensuring system stability.

There is however an external project for ASGI ratelimiting which should also work with ClientIPMiddleware because this middleware inject the x-real-ip header:

RateLimitMiddleware

Session fixing

Problem

Session stealing by stealing cookies via malware. Especially for sessions with high privileges this is a problem.

Solution

This technique works by using the clientip and the session middleware. We limit a session to an ip. We have even two options: ClientIPMiddleware or ClientIPScopeOnlyMiddleware, depending if we need headers. The usage is documented in SessionFixingMiddleware.

Note

If the client has an unstable connection, the session can reset from time to time. It is recommended to use the session fixing carefully only for sensitive areas or use the notify_fn parameter to port from the old session to the new session when appropiate.