Wp-Login Angreifer mit Crowdsec aussperren
Ich wollte crowdsec um eine einfache Regel erweitern. Alle Zugriffe auf die normale Wordpress Login url wp-login.php auf meinem Blog sind als Angriffe aufzufassen und die Absendeadresse soll von Crowdsec geblockt werden.
Die folgende “Dokumentation” dient nur als meine persönliche Gedächtnisstütze und hat keinerlei Anspruch auf Korrektheit. Bei mir hat es halt so geklappt und den nächsten Usecase würde ich wieder so angehen.
Ich beginne mir eine kleine Testdatei mit den relevanten Logdaten zu erstellen
grep wp-login /usr/local/www/www-hb/logs/nx-error.log > wp-login.log
Dann erstelle ich einen Parser
vi /usr/local/etc/crowdsec/parsers/s01-parse/nginx-logs-hb.yaml
filter: "evt.Parsed.program startsWith 'nginx'"
onsuccess: next_stage
name: hagen-bauer/nginx-logs-hb
description: "Parse nginx error logs"
nodes:
- grok:
pattern: '(%{IPORHOST:target_fqdn} )?%{NGINXERRTIME:time} \[%{LOGLEVEL:loglevel}\] %{NONNEGINT:pid}#%{NONNEGINT:tid}: (\*%{NONNEGINT:cid} )?%{GREEDYDATA:message}, client: %{IPORHOST:remote_addr}, server: %{DATA:target_fqdn}, request: "%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}", host: "%{IPORHOST}(:%{NONNEGINT})?"'
apply_on: message
statics:
- meta: log_type
value: http_error-log
- target: evt.StrTime
expression: evt.Parsed.time
pattern_syntax:
NO_DOUBLE_QUOTE: '[^"]+'
onsuccess: next_stage
nodes:
- filter: "evt.Parsed.message contains 'wp-login'"
statics:
- meta: log_type
value: "nginx_wplogin"
statics:
- meta: service
value: http
- meta: source_ip
expression: "evt.Parsed.remote_addr"
- meta: http_status
expression: "evt.Parsed.status"
- meta: http_path
expression: "evt.Parsed.request"
- meta: http_verb
expression: "evt.Parsed.verb"
- meta: http_user_agent
expression: "evt.Parsed.http_user_agent"
- meta: target_fqdn
expression: "evt.Parsed.target_fqdn"
``
und das ganze teste ich zuerst
cscli explain --file wp-login.log --type nginx
line: 2021/11/19 02:01:26 [error] 71930#100755: *453882 open() "/usr/local/www/html/wp-login.php" failed (2: No such file or directory), client: 193.142.146.138, server: www.hagen-bauer.de, request: "GET /wp-login.php HTTP/1.1", host: "www.hagen-bauer.de"
├ s00-raw
| ├ 🟢 crowdsecurity/non-syslog (first_parser)
| └ 🔴 crowdsecurity/syslog-logs
├ s01-parse
| └ 🟢 hagen-bauer/nginx-logs-hb (+16 ~3)
├ s02-enrich
| ├ 🟢 crowdsecurity/dateparse-enrich (+2 ~1)
| ├ 🟢 crowdsecurity/geoip-enrich (+13)
| ├ 🔴 crowdsecurity/http-logs
| └ 🟢 crowdsecurity/whitelists (unchanged)
├-------- parser success 🟢
├ Scenarios
Wichtig ist das da was gefunden wird und kein “parser failed” am Ende steht. Jetzt finden wir was aber wir müssen noch sagen was mit den Ergebnissen getan werden soll. Das geschieht in einem “Scenario”
vi /usr/local/etc/crowdsec/scenarios/http-wordpress-login-xmlrpc.yaml
type: leaky
format: 2.0
#debug: true
name: hagen-bauer/http-wordpress-login-xmlrpc
description: "Detect attempt to access to wp-login "
filter: "evt.Meta.log_type == 'nginx_wplogin' "
groupby: "evt.Meta.source_ip"
#distinct: evt.Parsed.request
capacity: 4
leakspeed: 2m
blackhole: 5m
labels:
service: nginx
type: bruteforce
remediation: true
Und noch mal prüfen ob was passiert
cscli explain --file wp-login.log --type nginx
line: 2021/11/19 02:01:26 [error] 71930#100755: *453882 open() "/usr/local/www/html/wp-login.php" failed (2: No such file or directory), client: 193.142.146.138, server: www.hagen-bauer.de, request: "GET /wp-login.php HTTP/1.1", host: "www.hagen-bauer.de"
├ s00-raw
| ├ 🟢 crowdsecurity/non-syslog (first_parser)
| └ 🔴 crowdsecurity/syslog-logs
├ s01-parse
| └ 🟢 hagen-bauer/nginx-logs-1bs3 (+16 ~3)
├ s02-enrich
| ├ 🟢 crowdsecurity/dateparse-enrich (+2 ~1)
| ├ 🟢 crowdsecurity/geoip-enrich (+13)
| ├ 🔴 crowdsecurity/http-logs
| └ 🟢 crowdsecurity/whitelists (unchanged)
├-------- parser success 🟢
├ Scenarios
└ 🟢 hagen-bauer/http-wordpress-login-xmlrpc
Jetzt kann man von einem anderen Rechner durch wiederholten Aufruf der wp-login.php mal prüfen ob eine “Entscheidung” gefällt worden ist
# cscli decision list
+---------+----------+--------------------+---------------------------------------+--------+---------+------------------------+--------+--------------------+----------+
| ID | SOURCE | SCOPE:VALUE | REASON | ACTION | COUNTRY | AS | EVENTS | EXPIRATION | ALERT ID |
+---------+----------+--------------------+---------------------------------------+--------+---------+------------------------+--------+--------------------+----------+
| 95xxx81 | crowdsec | Ip:140.238.175.147 | hagen-bau/http-wordpress-login-xmlrpc | ban | CH | 31898 ORACLE-BMC-31898 | 5 | 2h10m34.812851056s | 951 |
+---------+----------+--------------------+---------------------------------------+--------+---------+------------------------+--------+--------------------+----------+