The OWASP CRS Request Traffic Policy action enables OWASP (Open Worldwide Application Security Project) CRS (previously Core Rule Set), a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. It aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts. CRS provides protection against many common attack categories, including SQL Injection, Cross Site Scripting, Local File Inclusion, etc. The owasp-crs-request action only enables rule processing on incoming HTTP requests to your endpoint. In addition to this action, we also recommend you enable the OWASP CRS Response action to analyze outgoing HTTP responses from your endpoint.

Video walkthrough

The following video walks you through ngrok’s OWASP CRS request and response actions in Traffic Policy, which let you add web application firewall protection directly to your ngrok endpoints without changing your existing infrastructure.

Configuration Reference

This is the Traffic Policy configuration reference for this action.

Supported Phases

on_http_request

Type

owasp-crs-request

Configuration Fields

on_error
string
Required

Behavior if there is an error. Must be one of either “continue” or “halt” (default “halt”)

More information can be found in the Managing Fallback Behavior section.

process_body
bool

If false, we do not process rules for the request body. Default is false.

exclude_rule_ids
array of integers

List of OWASP CRS rule IDs to exclude from evaluation.

The minimum value is 900000 and the maximum value is 999999.

Behavior

This action evaluates rules for request headers and body (when process_body is enabled), and each matching rule adds to the overall score of a request. If the score exceeds the set score threshold, the action will block the request. The tallying process is called Anomaly Scoring, and is detailed on the CRS website.

Default Behavior

The default behavior for this action is based on the following Coraza directives and rules from v4.14.0 of the CRS: Included in these rules is an inbound anomaly score threshold of 5 and a paranoia level of 1.

Managing Fallback Behavior (on_error)

If on_error is set to halt (default) and the action encounters an error when forwarding traffic, the Traffic Policy chain will halt and no further actions will be executed. For example, if you have a log action after the owasp-crs-request action, the log action will not be run and the error will be returned. However, if on_error is set to continue, actions that appear after the owasp-crs-request action will still be executed even if the owasp-crs-request action encounters an error.

Body Processing

When process_body is enabled, ngrok evaluates rules against the first 4kb of the body. If the body is larger than 4kb, we ignore the portion after the first 4kb.

Rule Exclusion

When exclude_rule_ids is configured, ngrok skips evaluation of the specified rule IDs. This allows you to disable specific OWASP CRS rules that may be causing false positives in your environment.

Inbound Anomaly Score Threshold Exceeded

If the anomaly score accumulated from matching rules exceeds the threshold, ngrok blocks the request with a HTTP 403 response. The request does not make it to your upstream.

Failure to process the body successfully

If ngrok is unable to read the request body successfully, ngrok blocks the request with a HTTP 500 response. The request does not make it to your upstream.

Examples

Running in block mode

The following configuration demonstrates how to run the owasp-crs-request action in block mode.

Example Traffic Policy Document

on_http_request:
  - actions:
      - type: owasp-crs-request
        config:
          on_error: halt

Example request that ngrok would block

In this example, we attempt to connect to example.ngrok.app using the curl command, and ngrok blocks the request returning back ERR_NGROK_3700
$ curl --http1.1 -X POST https://example.ngrok.app/\
  -H "User-Agent: Mozilla/5.0" \
  -H "Content-Type: application/json" \
  -d '{"q": "<script>alert(1)</script>"}'
<!DOCTYPE html>
<html class="h-full" lang="en-US" dir="ltr">
  <head>
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Regular-WebS.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-RegularItalic-WebS.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Medium-WebS.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Semibold-WebS.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-MediumItalic-WebS.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-Text.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-TextItalic.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-SemiBold.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <link rel="preload" href="https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-SemiBoldItalic.woff" as="font" type="font/woff" crossorigin="anonymous" />
    <meta charset="utf-8">
    <meta name="author" content="ngrok">
    <meta name="description" content="ngrok is the fastest way to put anything on the internet with a single command.">
    <meta name="robots" content="noindex, nofollow">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link id="style" rel="stylesheet" href="https://cdn.dev-ngrok.com/static/css/error.css">
    <noscript>The request was blocked by the WAF. (ERR_NGROK_3700)</noscript>
    <script id="script" src="https://cdn.dev-ngrok.com/static/js/error.js" type="text/javascript"></script>
  </head>
  <body class="h-full" id="ngrok">
    <div id="root" data-payload="eyJjZG5CYXNlIjoiaHR0cHM6Ly9jZG4uZGV2LW5ncm9rLmNvbS8iLCJjb2RlIjoiMzcwMCIsIm1lc3NhZ2UiOiJUaGUgcmVxdWVzdCB3YXMgYmxvY2tlZCBieSB0aGUgV0FGLiIsInRpdGxlIjoiRm9yYmlkZGVuIn0="></div>
  </body>
</html>

Running in test mode

The following configuration demonstrates how to run the owasp-crs-request action in test mode where rules are evaluated but blocks are not enforced.

Example Traffic Policy Document

on_http_request:
  - actions:
      - type: owasp-crs-request
        config:
          on_error: continue
      - type: log
        config:
          metadata:
            message: OWASP CRS request action would be ${actions.ngrok.owasp_crs_request.decision} for ${req.url}
            error_code: ${actions.ngrok.owasp_crs_request.error.code}
            error_message: ${actions.ngrok.owasp_crs_request.error.message}
            matched_rules_first_id: ${actions.ngrok.owasp_crs_request.matched_rules[0].id}
            matched_rules_first_message: ${actions.ngrok.owasp_crs_request.matched_rules[0].message}
            matched_rules_first_data: ${actions.ngrok.owasp_crs_request.matched_rules[0].data}

Action Result Variables

The following variables are made available for use in subsequent expressions and CEL interpolations after the action has run. Variable values will only apply to the last action execution, results are not concatenated.
actions.ngrok.owasp_crs_request.decision
string

The action taken for this request.

actions.ngrok.owasp_crs_request.anomaly_score
int

The total anomaly score for the request. If it equals to or exceeds the set threshold, it will block the request.

actions.ngrok.owasp_crs_request.anomaly_score_threshold
int

The total anomaly score threshold for the request. By default, it is set to 5.

actions.ngrok.owasp_crs_request.matched_rules
array of objects

The list of all rules matched by this request that have a non-zero score.

matched_rules[i].id
int

The ID of the rule.

matched_rules[i].message
string

The text message describing the rule.

matched_rules[i].severity
string

The severity of the matched rule.

matched_rules[i].data
string

Any extra data about the rule and how it matched the request.

actions.ngrok.owasp_crs_request.error.code
string

A machine-readable code describing an error that occurred during the action’s execution.

actions.ngrok.owasp_crs_request.error.message
string

A human-readable message providing details about an error that occurred during the action’s execution.