Integrated HTTP IDS Design: Whitelist

Whitelist Design Pattern

When designing a whitelist mechanism for an HTTP Intrusion Detection System (IDS), several aspects need to be considered: rule definition, rule management, traffic matching, performance optimization, and security. The design approach is as follows:

1. Rule Definition

Whitelist rules define which requests are legitimate and normal. Rules can be based on the following aspects:

  • IP Address: Allow requests from specific IP addresses or IP ranges.
  • URL Path: Allow specific URL paths or URL patterns.
  • HTTP Method: Allow specific HTTP methods (such as GET, POST, etc.).
  • Request Headers: Allow specific request headers or header patterns.
  • Parameters and Values: Allow specific parameter and value patterns.

Example Rules

{
  "ip_whitelist": ["192.168.1.1", "192.168.1.0/24"],
  "url_whitelist": ["/index.html", "/api/v1/*"],
  "method_whitelist": ["GET", "POST"],
  "header_whitelist": {
    "User-Agent": ["Mozilla/*", "Chrome/*"]
  },
  "param_whitelist": {
    "token": ["^[a-zA-Z0-9]{32}$"]
  }
}

2. Rule Management

Whitelist rules need to be easily managed and updated. Rules can be stored and managed using configuration files or databases, and an interface can be provided to dynamically update the rules.

Configuration File Method

Use configuration files in formats like JSON or YAML to store rules.

{
  "ip_whitelist": ["192.168.1.1", "192.168.1.0/24"],
  "url_whitelist": ["/index.html", "/api/v1/*"],
  "method_whitelist": ["GET", "POST"],
  "header_whitelist": {
    "User-Agent": ["Mozilla/*", "Chrome/*"]
  },
  "param_whitelist": {
    "token": ["^[a-zA-Z0-9]{32}$"]
  }
}

Database Method

Use relational databases or NoSQL databases to store rules and provide an API interface for management.

3. Traffic Matching

Traffic matching involves comparing HTTP requests with whitelist rules to determine if they are legitimate. It can be divided into the following steps:

  1. IP Address Matching:
    • Check if the source IP of the request is in the whitelist.
  2. URL Path Matching:
    • Check if the request URL path is in the whitelist.
  3. HTTP Method Matching:
    • Check if the request HTTP method is in the whitelist.
  4. Request Header Matching:
    • Check if the request headers meet the whitelist rules.
  5. Parameter Value Matching:
    • Check if the request parameters and values meet the whitelist rules.

Example Code

import re

class Whitelist:
    def __init__(self, rules):
        self.ip_whitelist = rules["ip_whitelist"]
        self.url_whitelist = rules["url_whitelist"]
        self.method_whitelist = rules["method_whitelist"]
        self.header_whitelist = rules["header_whitelist"]
        self.param_whitelist = rules["param_whitelist"]

    def is_whitelisted(self, request):
        if not self.match_ip(request.ip):
            return False
        if not self.match_url(request.url):
            return False
        if not self.match_method(request.method):
            return False
        if not self.match_headers(request.headers):
            return False
        if not self.match_params(request.params):
            return False
        return True

    def match_ip(self, ip):
        # Check if the IP is in the whitelist
        for ip_rule in self.ip_whitelist:
            if self.ip_in_range(ip, ip_rule):
                return True
        return False

    def ip_in_range(self, ip, ip_rule):
        # Implement IP range matching logic
        pass

    def match_url(self, url):
        # Check if the URL is in the whitelist
        for url_rule in self.url_whitelist:
            if self.url_match(url, url_rule):
                return True
        return False

    def url_match(self, url, url_rule):
        # Implement URL matching logic, support wildcards
        pass

    def match_method(self, method):
        # Check if the HTTP method is in the whitelist
        return method in self.method_whitelist

    def match_headers(self, headers):
        # Check if the headers match the whitelist rules
        for header, patterns in self.header_whitelist.items():
            if header not in headers:
                return False
            if not any(re.match(pattern, headers[header]) for pattern in patterns):
                return False
        return True

    def match_params(self, params):
        # Check if the parameters match the whitelist rules
        for param, patterns in self.param_whitelist.items():
            if param not in params:
                continue
            if not any(re.match(pattern, params[param]) for pattern in patterns):
                return False
        return True

# Example usage
rules = {
    "ip_whitelist": ["192.168.1.1", "192.168.1.0/24"],
    "url_whitelist": ["/index.html", "/api/v1/*"],
    "method_whitelist": ["GET", "POST"],
    "header_whitelist": {
        "User-Agent": ["Mozilla/.*", "Chrome/.*"]
    },
    "param_whitelist": {
        "token": ["^[a-zA-Z0-9]{32}$"]
    }
}

whitelist = Whitelist(rules)

# Simulated request object for demonstration
class Request:
    def __init__(self, ip, url, method, headers, params):
        self.ip = ip
        self.url = url
        self.method = method
        self.headers = headers
        self.params = params

request = Request(
    ip="192.168.1.100",
    url="/api/v1/resource",
    method="GET",
    headers={"User-Agent": "Mozilla/5.0"},
    params={"token": "1234567890abcdef1234567890abcdef"}
)

print(whitelist.is_whitelisted(request))  # Should print True if request matches all rules

Initial Whitelist

Creating a universally applicable whitelist involves covering common legitimate traffic patterns while avoiding being too strict to prevent excessive false positives, and not too lenient to allow malicious traffic to evade detection. Below is an initial design for a universally applicable whitelist suitable for most HTTP servers.

1. IP Address Whitelist

The initial whitelist can exclude IP address restrictions unless you have specific trusted IP address ranges. For example, you can allow internal network IP addresses:

{
  "ip_whitelist": ["192.168.0.0/16", "10.0.0.0/8"]
}

2. URL Path Whitelist

Allow common static resources and API paths:

{
  "url_whitelist": [
    "/index.html",
    "/about.html",
    "/contact.html",
    "/css/*",  // Allow all CSS files
    "/js/*",   // Allow all JavaScript files
    "/images/*", // Allow all image files
    "/api/v1/*"  // Allow all API v1 endpoints
  ]
}

3. HTTP Method Whitelist

Allow common HTTP methods:

{
  "method_whitelist": ["GET", "POST", "PUT", "DELETE"]
}

4. Request Header Whitelist

Allow common request header fields and patterns:

{
  "header_whitelist": {
    "User-Agent": ["Mozilla/.*", "Chrome/.*", "Safari/.*"],
    "Accept": ["*/*", "text/html", "application/json"],
    "Content-Type": ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"]
  }
}

5. Parameter and Value Whitelist

Allow common parameter and value patterns:

{
  "param_whitelist": {
    "token": ["^[a-zA-Z0-9]{32}$"],
    "id": ["^[0-9]+$"],
    "name": ["^[a-zA-Z ]+$"]
  }
}

Comprehensive Configuration Example & Implementation Code Example

Combining all the above parts into a comprehensive whitelist configuration, and using Python with the Flask framework to implement an HTTP server, you can apply the whitelist filtering during request processing:

import re
from flask import Flask, request, abort
import ipaddress

app = Flask(__name__)

whitelist_rules = {
    "ip_whitelist": ["192.168.0.0/16", "10.0.0.0/8"],
    "url_whitelist": [
        "/index.html",
        "/about.html",
        "/contact.html",
        "/css/*",
        "/js/*",
        "/images/*",
        "/api/v1/*"
    ],
    "method_whitelist": ["GET", "POST", "PUT", "DELETE"],
    "header_whitelist": {
        "User-Agent": ["Mozilla/.*", "Chrome/.*", "Safari/.*"],
        "Accept": ["*/*", "text/html", "application/json"],
        "Content-Type": ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"]
    },
    "param_whitelist": {
        "token": ["^[a-zA-Z0-9]{32}$"],
        "id": ["^[0-9]+$"],
        "name": ["^[a-zA-Z ]+$"]
    }
}

def ip_in_whitelist(ip):
    for ip_rule in whitelist_rules["ip_whitelist"]:
        if ipaddress.ip_address(ip) in ipaddress.ip_network(ip_rule):
            return True
    return False

def url_in_whitelist(url):
    for url_rule in whitelist_rules["url_whitelist"]:
        if re.match(url_rule.replace("*", ".*"), url):
            return True
    return False

def method_in_whitelist(method):
    return method in whitelist_rules["method_whitelist"]

def headers_in_whitelist(headers):
    for header, patterns in whitelist_rules["header_whitelist"].items():
        if header not in headers:
            return False
        if not any(re.match(pattern, headers[header]) for pattern in patterns):
            return False
    return True

def params_in_whitelist(params):
    for param, patterns in whitelist_rules["param_whitelist"].items():
        if param not in params:
            continue
        if not any(re.match(pattern, params[param]) for pattern in patterns):
            return False
    return True

@app.before_request
def check_whitelist():
    if not ip_in_whitelist(request.remote_addr):
        abort(403)
    if not url_in_whitelist(request.path):
        abort(403)
    if not method_in_whitelist(request.method):
        abort(403)
    if not headers_in_whitelist(request.headers):
        abort(403)
    if not params_in_whitelist(request.args):
        abort(403)

@app.route('/index.html')
def index():
    return "Welcome to the index page."

@app.route('/api/v1/resource', methods=['GET', 'POST'])
def api_resource():
    return "API v1 resource."

# Additional route definitions...

if __name__ == '__main__':
    app.run(debug=True)

How to Implement: Using Flask Hook Functions

  • Use the @app.before_request hook function to perform whitelist checks before processing each request. If a request does not comply with the whitelist rules, return a 403 Forbidden status code.

Deployment and Usage

  1. Starting the Server:
    • Run the above code to start the Flask HTTP server.
  2. Testing Access:
    • Access http://localhost:8080/index.html to verify if it can be accessed normally.
    • Access other paths or use request headers or parameters not included in the whitelist to verify if they are blocked.

By following this approach, we can create an initial, universally applicable HTTP whitelist mechanism. Further configurations should be customized based on the specific HTTP server protection needs.

Another Way to Implement: Filter Module inside SentinelGuard Project

By compositing the whitelists into procedures of detecting intrusion network traffic, it is convenient to implement whitelist function (only done ip whitelist at the current circumstance).