aboutsummaryrefslogtreecommitdiff

Минималистичный Web Application Firewall (WAF) на OpenResty

UPDATE: добавлена работа со спецификой уязвимости PHP2Shell:

  1. Бан по Multipart-границам формы
  2. Глубине вложенности JSON-структур
  3. Странным параметрам PHPSESSID

Архитектура

[ Входящий запрос ] │ ├──► 0. Белый список IP и Глобальный Бан-лист (L1/L2 кэш) │ ├──► 1. waf.detector (Эвристика заголовков, Smuggling и сессии) │ ├──► 2. waf.limits (Двухпороговый Token Bucket на POST-динамику) │ ├──► 3. waf.analyzer (Анализатор Query String URL на SQLi/LFI) │ └──► 4. waf.filter (Потоковый стриминг Multipart и JSON скобок)

Структура файлов в репозитории:

• example.lua — Пример реализации на фазе access_by_lua 7 уровня OSI (фаза блока http).

• example2.lua — Пример реализации с возвратом данных инцендента для заглушки.

• waf/config.lua — Единая точка конфигурации лимитов, белых списков и штрафных матриц.

• waf/ban.lua — Двухуровневый кэш блокировок (Локальная L1 таблица воркера ➡️ L2 shared_dict).

• waf/detector.lua — Анализатор аномалий HTTP-заголовков и валидатор формата куки PHPSESSID.

• waf/limits.lua — Двухпороговый ограничитель частоты (Rate Limiter) для тяжелых POST-запросов.

• waf/analyzer.lua — Высокоскоростной чистильщик параметров URL-строки (ngx.var.args).

• waf/filter.lua — Низкоуровневый потоковый парсер сырого сокета тела запроса (Multipart и JSON).

Примеры использования

  1. На уровне location

```http {

lua_shared_dict banned_ips 10m; 
lua_shared_dict limits 2m;

map $http_user_agent $is_bot {
    default 0;
    ~*googlebot|yandex|bingbot|baiduspider|mail.ru_bot|ia_archiver|facebot|facebookexternalhit|twitterbot|://google.com|ahrefsbot|semrushbot|telegrambot|vkshare|whatsapp 1;
}

server {
    listen 443 ssl;
    server_name test.ru;
    server_tokens off;

    location ~* /(wp-content|wp-includes|wp-admin|wp-login\.php|xmlrpc\.php|\.git|\.env|vendor|phpmyadmin|adminer\.php|\.htaccess|config\.init) {
        access_log off;
        log_not_found off;
        return 444;
    }

    location / {
        access_log off;
        access_by_lua_file /home/example.lua;
    }
}

}```

  1. На уровне server
http {

    lua_shared_dict banned_ips 10m; 
    lua_shared_dict limits 2m; 

    map $http_user_agent $is_bot {
        default 0;
        ~*googlebot|yandex|bingbot|baiduspider|mail.ru_bot|ia_archiver|facebot|facebookexternalhit|twitterbot|://google.com|ahrefsbot|semrushbot|telegrambot|vkshare|whatsapp 1;
    }

    server {
        listen 443 ssl;
        server_name test.ru;
        access_by_lua_file /home/example.lua;       
    }
}
  1. С заглушкой
    error_page 403 = @waf_block_page;

    location @waf_block_page {
        root /home/html;
        rewrite ^(.*)$ /index.html break;    
        ssi on;         
        access_log off;
    }

    server {
        listen 443 ssl;
        server_name test.ru;
        access_by_lua_file /home/example2.lua;      
    }