433 lines
14 KiB
Python
433 lines
14 KiB
Python
import os
|
|
|
|
SKIP_BACKUP_PREFIXES = (
|
|
"redirectlog",
|
|
"stats:ip",
|
|
"stats:user_agent",
|
|
"stats:referrer",
|
|
"stats:host:",
|
|
"sequence:", # per-IP sekwencje żądań (ltrim, ale bez TTL)
|
|
"requests:", # per-IP ostatnie requesty (ltrim, ale bez TTL)
|
|
)
|
|
|
|
|
|
CONFIG = {
|
|
"basic_auth": {
|
|
"username": "admin",
|
|
"password": "admin"
|
|
},
|
|
"api_keys": {
|
|
"default": "d844X5w4GJ7X29tvp3bQ48"
|
|
},
|
|
"api_trusted_networks": [
|
|
"127.0.0.1/32",
|
|
"::1/128",
|
|
"10.87.0.0/16",
|
|
"172.16.0.0/24"
|
|
],
|
|
"trusted_proxies": ["127.0.0.1", "::1"],
|
|
"sqlite_db": os.path.join(os.path.dirname(__file__), "redis_backup.sqlite3"),
|
|
"webserver_bin": "/usr/sbin/angie",
|
|
"log_files": [
|
|
"/var/log/angie/unitraklub.pl_access.log",
|
|
"/var/log/angie/unitra.eu.org_access.log",
|
|
"/var/log/angie/unitrafan.pl_access.log",
|
|
],
|
|
"redis_host": "localhost",
|
|
"redis_port": 6379,
|
|
"redis_db": 8,
|
|
"thresholds": {
|
|
"requests": 25000,
|
|
"errors": 10,
|
|
"success_requests": 20000,
|
|
"error_codes": [404, 500, 410],
|
|
"requests_time_window": 3600,
|
|
"ban_duration": 15552000,
|
|
"request_size": 256000000,
|
|
},
|
|
"deny_file": "/etc/angie/conf.d/deny_auto.conf",
|
|
#'deny_file': 'deny_auto.conf',
|
|
"geoip_db": "GeoIP/GeoLite2-City.mmdb",
|
|
"api_port": 5002,
|
|
"prometheus_port": 9502,
|
|
"pushover": {
|
|
"token": "afh4yqrybtf7jnznyapq2bs1wcdmiq",
|
|
"user_key": "u629MYggcYdRs6UM3TdYJviHWmcdKe",
|
|
"enabled": True,
|
|
},
|
|
"whitelist_endpoints": [
|
|
"/customerror/404",
|
|
"/block_refresh/quicktabs/3",
|
|
"/block_refresh/block/10",
|
|
"/block_refresh/views/apk_user_tracker_page-block_1",
|
|
"/klubowyczat/includes/json/receive/receive_core.php",
|
|
"/klubowyczat/includes/json/receive/receive_buddylist.php",
|
|
],
|
|
"notification_batching": {
|
|
"enabled": True,
|
|
"batch_window": 43200, # X minut w sekundach
|
|
"threshold": 25, # minimum banów do wysłania powiadomienia
|
|
"max_window": 21600, # maksymalny czas oczekiwania
|
|
"summary_limit": 10, # ile najczęstszych IP pokazać w podsumowaniu
|
|
},
|
|
"attack_patterns": {
|
|
"path_traversal": [
|
|
r"\.\./",
|
|
r"\.\.\\",
|
|
r"%2e%2e%2f", # ../
|
|
r"%2e%2e%5c", # ..\
|
|
r"%252e%252e%252f", # podwójnie kodowane ../
|
|
r"%c0%ae%c0%ae%c0%af", # UTF-8 overlong ../
|
|
r"%uff0e%uff0e%u2215", # Unicode fullwidth
|
|
r"/etc/passwd",
|
|
r"/etc/shadow",
|
|
r"/proc/self/environ",
|
|
r"c:\\windows\\system32",
|
|
r"c:\\boot\\.ini",
|
|
r"web\.config",
|
|
r"\.\./\.\./", # ../../
|
|
r"\\..\\", # UNC style
|
|
],
|
|
"command_injection": [
|
|
r";\s*cat\s+/etc/passwd",
|
|
r";\s*ls\s+",
|
|
r";\s*id\s*;",
|
|
r";\s*whoami\s*;",
|
|
r"&&\s*cat\s+",
|
|
r"\|\s*cat\s+",
|
|
r"`cat\s+/etc/passwd`",
|
|
r"\$\(cat\s+/etc/passwd\)",
|
|
r";\s*wget\s+",
|
|
r";\s*curl\s+",
|
|
r";\s*nc\s+",
|
|
r";\s*bash\s*;",
|
|
],
|
|
"nosql_injection": [
|
|
r"\$ne:",
|
|
r"\$gt:",
|
|
r"\$lt:",
|
|
r"\$where:",
|
|
r"\$regex:",
|
|
r"\$exists:",
|
|
r'{"username":\s*{"?\$ne',
|
|
r'{"password":\s*{"?\$ne',
|
|
r";\s*db\.dropDatabase\(\)",
|
|
r"MapReduce",
|
|
r"\$eval:",
|
|
],
|
|
"ldap_injection": [
|
|
r"\*\)\(cn=\*",
|
|
r"\)\(\|",
|
|
r"\(\|\(",
|
|
r"\)\(uid=\*",
|
|
r"\(\&\(",
|
|
r"admin\)\(\|",
|
|
r"\*\)\(userPassword=\*",
|
|
r"\(\!\(",
|
|
r"\)%00",
|
|
],
|
|
"xxe": [
|
|
r"<!ENTITY.*?SYSTEM",
|
|
r"<!ENTITY.*?file://",
|
|
r"<!ENTITY.*?http://",
|
|
r"<!ENTITY.*?https://",
|
|
r"<!ENTITY.*?ftp://",
|
|
r"<!ENTITY.*?expect://",
|
|
r"&xxe;",
|
|
r"<!DOCTYPE.*?\[",
|
|
r'SYSTEM\s+["\']file://',
|
|
],
|
|
"ssti": [
|
|
r"\{\{.*?\}\}",
|
|
r"\{\%.*?\%\}",
|
|
r"\$\{.*?\}",
|
|
r"\{\{7\*7\}\}",
|
|
r"\{\{config\}\}",
|
|
r"\{\{request\}\}",
|
|
r"\{\{self\}\}",
|
|
r"<%.*?%>",
|
|
r"\{\{.*?\.\_\_class\_\_.*?\}\}",
|
|
],
|
|
"csrf": [
|
|
r'<form.*?action=["\']https?://(?!.*?example\.com)',
|
|
r'<img.*?src=["\']https?://(?!.*?example\.com).*?\.php',
|
|
r'<iframe.*?src=["\']https?://(?!.*?example\.com)',
|
|
r"XMLHttpRequest.*?open.*?POST",
|
|
r'fetch.*?method:\s*["\']POST["\']',
|
|
],
|
|
"deserialization": [
|
|
r"O:\d+:",
|
|
r"a:\d+:\{",
|
|
r"java\.io\.Serializable",
|
|
r"rO0AB",
|
|
r"H4sIA",
|
|
r"__reduce__",
|
|
r"__setstate__",
|
|
r"pickle\.loads",
|
|
r"cPickle\.loads",
|
|
r"yaml\.load",
|
|
r"unserialize\(",
|
|
],
|
|
"host_header_injection": [
|
|
r"Host:\s*[^.\r\n]+\.[^.\r\n]+\.[^.\r\n]+",
|
|
r"X-Forwarded-Host:\s*[^.\r\n]+\.[^.\r\n]+",
|
|
r"X-Host:\s*[^.\r\n]+\.[^.\r\n]+",
|
|
r"Host:\s*localhost:\d{4,5}",
|
|
r"Host:\s*127\.0\.0\.1:\d+",
|
|
],
|
|
"open_redirect": [
|
|
r"(redirect|url|return|next|target)=https?://",
|
|
r"(redirect|url|return|next|target)=%2F%2F",
|
|
r"(redirect|url|return|next|target)=//[^/]",
|
|
r"Location:\s*https?://(?!.*?example\.com)",
|
|
r"window\.location.*?=.*?http://",
|
|
r"document\.location.*?=.*?http://",
|
|
],
|
|
"information_disclosure": [
|
|
r'(password|passwd|pwd|secret|key|token)[\s]*[:=][\s]*["\'][^"\']{8,}',
|
|
r"mysql_connect\(",
|
|
r"pg_connect\(",
|
|
r"stack trace",
|
|
r"Fatal error:",
|
|
r"Warning:.*?on line",
|
|
r"Error:.*?at line",
|
|
r"\.git/",
|
|
r"\.env",
|
|
r"config\.php",
|
|
r"backup\.",
|
|
r"\.bak",
|
|
r"\.old",
|
|
],
|
|
"business_logic": [
|
|
r"(price|amount|quantity|discount)=0",
|
|
r"(price|amount|quantity|discount)=-\d+",
|
|
r"(role|privilege|level|type)=admin",
|
|
r"(role|privilege|level|type)=administrator",
|
|
r"bypass=true",
|
|
r"test=true",
|
|
r"debug=true",
|
|
r"admin=true",
|
|
],
|
|
"session_attacks": [
|
|
r"PHPSESSID=.*?\w{26,}",
|
|
r"JSESSIONID=.*?\w{32,}",
|
|
r"session_id=.*?\w{32,}",
|
|
r"sid=.*?\w{16,}",
|
|
r"Cookie:.*?sessionid=fixed",
|
|
r"Set-Cookie:.*?secure=false",
|
|
r"Set-Cookie:.*?httponly=false",
|
|
],
|
|
"sqli_extended": [
|
|
# MongoDB NoSQL
|
|
r"\$where:\s*function\(\)",
|
|
r'ObjectId\(["\'][^"\']*["\']\)',
|
|
# PostgreSQL specific
|
|
r"pg_sleep\(\d+\)",
|
|
r"COPY.*?FROM.*?PROGRAM",
|
|
# Oracle specific
|
|
r"UTL_HTTP\.REQUEST",
|
|
r"SYS\.DBMS_EXPORT_EXTENSION",
|
|
],
|
|
"xss_extended": [
|
|
# DOM-based XSS
|
|
r"document\.write\(",
|
|
r"innerHTML\s*=",
|
|
r"outerHTML\s*=",
|
|
# Event handlers
|
|
r'on\w+\s*=\s*["\'][^"\']*script',
|
|
# Data URIs
|
|
r"data:text/html,",
|
|
r"data:image/svg\+xml",
|
|
# JavaScript protocols
|
|
r"vbscript:",
|
|
r"livescript:",
|
|
],
|
|
"clickjacking": [
|
|
r"<iframe.*?opacity\s*:\s*0",
|
|
r"<iframe.*?visibility\s*:\s*hidden",
|
|
r"<iframe.*?display\s*:\s*none",
|
|
r"position\s*:\s*absolute.*?top\s*:\s*-\d+",
|
|
r"z-index\s*:\s*-?\d+",
|
|
],
|
|
"sqli": [
|
|
r"\b(UNION\s+SELECT|SELECT\s+.*?\s+FROM|INSERT\s+INTO|UPDATE\s+.*?\s+SET|DELETE\s+FROM)\b",
|
|
r"\bOR\s+1=1\b",
|
|
r"\bEXEC\(.*\)",
|
|
r"\bWAITFOR\s+DELAY\b",
|
|
r"\b(SLEEP\(\d+\)|BENCHMARK\(\d+\))",
|
|
r"\b(CAST|CONVERT)\(.*AS.*\)",
|
|
r"\bINFORMATION_SCHEMA\.TABLES\b",
|
|
r"\b0x[0-9a-fA-F]+\b",
|
|
r"\b(;--|#|/\*)\s*$",
|
|
],
|
|
"xss": [r"<script.*?>", r"javascript:", r"onerror=", r"alert\(.*\)"],
|
|
"drupal": [
|
|
r"/user/register\?element_parents=account/mail/%23value&.*_wrapper_format=drupal_ajax",
|
|
r"/file/ajax/.*/upload",
|
|
r"POST\s+/node/\d+/?_format=hal_json",
|
|
r"POST\s+/user/.*?_format=hal_json",
|
|
r"_drupal_ajax=1&form_id=.*_form",
|
|
r"/_entity_embed/.*?/embed",
|
|
r"linkit/match\?search=.*<script",
|
|
r"/_jsonapi\?.*filter\[.*\]\[condition\]\[path\]=.*",
|
|
r"/admin/config/development/configuration/single/export",
|
|
r"rest_export=1",
|
|
r"/taxonomy/term/\d+/edit",
|
|
],
|
|
"rce": [
|
|
r"\b(passthru|shell_exec|phpinfo|proc_open|popen)\b",
|
|
r"\.\./\.\./\.\./\.\./",
|
|
r"/\$(?:\\$\$)+/",
|
|
],
|
|
"lfi": [
|
|
r"\.\./\.\./\.\./\.\./",
|
|
r"(etc/passwd|proc/self/environ)",
|
|
r"php://filter/convert.base64-encode/resource=",
|
|
],
|
|
"ssrf": [
|
|
r"(127\.0\.0\.1|localhost|169\.254\.169\.254)",
|
|
r"(\?|&)url=(http|https|ftp|file)",
|
|
r"/(metadata|instance-data)/",
|
|
r"accesskeyid|secretkey",
|
|
],
|
|
"xxe": [r"<!ENTITY.*SYSTEM.*>", r"%xxe;", r"DOCTYPE.*ENTITY", r"jar:file:/"],
|
|
"ci_cd": [
|
|
r"/(\.git|\.svn|\.hg)/",
|
|
r"/(Jenkinsfile|\.travis\.yml|circleci/config\.yml)",
|
|
r"/(docker-compose\.yml|Dockerfile)",
|
|
r"/(package\.json|requirements\.txt)",
|
|
r"/_apis/build",
|
|
r"/api/v4/ci",
|
|
r"/(github|gitlab)-webhook",
|
|
r"/(bitbucket-pipelines\.yml)",
|
|
],
|
|
},
|
|
"bruteforce": {
|
|
"login_urls": [
|
|
# klasyczne
|
|
"/user/login",
|
|
"/login",
|
|
"/signin",
|
|
"/users/login",
|
|
"/account/login",
|
|
"/auth/login",
|
|
"/admin/login",
|
|
"/admin.php",
|
|
"/admin/index.php",
|
|
"/administrator/",
|
|
"/administrator/index.php",
|
|
"/cpanel",
|
|
"/phpmyadmin",
|
|
|
|
# WordPress / CMS
|
|
"/wp-login.php",
|
|
"/wp-login.php?action=lostpassword",
|
|
"/xmlrpc.php",
|
|
"/wp-admin/",
|
|
"/wp-admin/admin-ajax.php",
|
|
"/wp-content/",
|
|
"/typo3/index.php",
|
|
"/joomla/administrator/",
|
|
|
|
# API loginy
|
|
"/oauth/token",
|
|
"/graphql",
|
|
"/api/login",
|
|
"/api/auth",
|
|
"/api/v1/login",
|
|
"/rest/user/login",
|
|
"/rest/auth/login",
|
|
"/admin/auth/login",
|
|
|
|
# podejrzane / backdoory
|
|
"/makeasmtp.php",
|
|
"/updates.php",
|
|
"/yanz.php",
|
|
"/pwnd.php",
|
|
"/wp-l0gin.php",
|
|
"/wlwmanifest.xml",
|
|
"/classwithtostring.php",
|
|
"/0x.php",
|
|
"/shell.php",
|
|
"/cmd.php",
|
|
"/login.php",
|
|
"/logon.php",
|
|
"/portal/redlion",
|
|
],
|
|
"attempts_threshold": 15,
|
|
"time_window": 300,
|
|
"rate_limits": {
|
|
"api": {"path_regex": r"^/klubowyczat/.*", "limit": 250, "window": 60},
|
|
"assets": {
|
|
"path_regex": r"\.(js|css|png|jpg|jpeg)$",
|
|
"limit": 750,
|
|
"window": 60,
|
|
},
|
|
},
|
|
},
|
|
"sequence": {
|
|
"window_size": 15,
|
|
"suspicious_patterns": [
|
|
{
|
|
"pattern": ["/user/password", "/user/login", "/user/register"],
|
|
"score": 10,
|
|
},
|
|
{"pattern": ["/node/add", "/admin/content", "/admin/users"], "score": 8},
|
|
{"pattern": ["/wp-admin", "/wp-login.php", "/xmlrpc.php"], "score": 12},
|
|
{"pattern": ["/.env", "/config.php", "/database.ini"], "score": 15},
|
|
{"pattern": ["/v1/api", "/v1/admin", "/v1/user"], "score": 7},
|
|
{"pattern": ["/phpinfo.php", "/info.php", "/test.php"], "score": 10},
|
|
],
|
|
"threshold": 15,
|
|
"time_based_sequences": [
|
|
{
|
|
"pattern": ["/api/auth/token", "/api/user/me"],
|
|
"time_window": 2,
|
|
"threshold": 10,
|
|
},
|
|
{
|
|
"pattern": ["/password/reset", "/login"],
|
|
"time_window": 30,
|
|
"threshold": 5,
|
|
},
|
|
],
|
|
},
|
|
"api_abuse": {
|
|
"graphql": [
|
|
r"(__schema|introspection)",
|
|
r"mutation\s+\{",
|
|
r"query\s+\{\s+__typename",
|
|
],
|
|
"rest": [r"/(v1|api)/.*(\$|\|)", r"%24%7B.*%7D", r"/api/.*%0A"],
|
|
},
|
|
"scanner_signatures": [
|
|
r"(nmap|acunetix|nessus|nikto)",
|
|
r"(sqlmap|w3af|zap|burp)",
|
|
r"libwww-perl|curl|python-requests",
|
|
r"(zgrab|masscan|metasploit)",
|
|
],
|
|
"whitelist": {
|
|
"user_agents": [
|
|
r"Googlebot",
|
|
r"Bingbot",
|
|
r"DuckDuckBot",
|
|
r"YandexBot",
|
|
r"Twitterbot",
|
|
r"Applebot",
|
|
r"LinkedInBot",
|
|
r"AdsBot-Google",
|
|
r"SeznamBot",
|
|
r"facebot",
|
|
],
|
|
"ip_ranges": [
|
|
"66.249.64.0/19",
|
|
"157.55.39.0/24",
|
|
"207.46.0.0/16",
|
|
"146.75.0.0/16",
|
|
"141.144.232.95/32",
|
|
],
|
|
"log_lines_limit": 50,
|
|
},
|
|
"stats_retention": {"week": 4, "month": 1, "year": 0},
|
|
}
|