diff --git a/ChangeLog b/ChangeLog index eb3401bf..b1ce9327 100644 --- a/ChangeLog +++ b/ChangeLog @@ -116,6 +116,7 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition * `filter.d/openvpn.conf` - new filter and jail for openvpn recognizing failed TLS handshakes (gh-2702) * `filter.d/sendmail-reject.conf` - also recognize "Domain of sender address ... does not resolve" (gh-4035) * `filter.d/vaultwarden.conf` - new filter and jail for Vaultwarden (gh-3979) +* `filter.d/xrdp.conf` - new filter for XRDP, an open source RDP server (gh-3254) * `fail2ban-regex` extended with new option `-i` or `--invert` to output not-matched lines by `-o` or `--out` (gh-4001) diff --git a/config/filter.d/xrdp.conf b/config/filter.d/xrdp.conf new file mode 100644 index 00000000..253bcf8d --- /dev/null +++ b/config/filter.d/xrdp.conf @@ -0,0 +1,35 @@ +# +# Fail2Ban filter for XRDP +# +# Detects login attempts with invalid credentials +# +# Requirements: +# - xrdp >= 0.9.19 +# - The log level in sesman.ini should be set to `INFO` or higher +# to emit the log messages needed for this filter. +# +# Author: Evan Linde +# + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = common.conf + + +[DEFAULT] + +_daemon = xrdp-sesman + + +[Definition] + +authfail_re = \[INFO \] AUTHFAIL: user=(?:\S+|.+) ip= time=\d+ + +failregex = ^%(__prefix_line)s%(authfail_re)s$ + +ignoreregex = + +datepattern = ^\[?%%ExY%%Exm%%Exd-%%ExH:%%ExM:%%ExS\]? + ^{DATE} diff --git a/config/jail.conf b/config/jail.conf index 66d6b107..d0b3fa44 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -995,3 +995,7 @@ logpath = /var/log/daemon.log [vaultwarden] port = http,https logpath = /var/log/vaultwarden.log + +[xrdp] +port = 3389 +logpath = /var/log/xrdp-sesman.log diff --git a/fail2ban/server/datedetector.py b/fail2ban/server/datedetector.py index fd94d55f..2762c0bf 100644 --- a/fail2ban/server/datedetector.py +++ b/fail2ban/server/datedetector.py @@ -165,8 +165,8 @@ class DateDetectorCache(object): r"%b %d, %ExY %I:%M:%S %p", # ASSP: Apr-27-13 02:33:06 r"^%b-%d-%Exy %k:%M:%S", - # 20050123T215959, 20050123 215959, 20050123 85959 - r"%ExY%Exm%Exd(?:T| ?)%ExH%ExM%ExS(?:[.,]%f)?(?:\s*%z)?", + # 20050123T215959, 20050123 215959, 20050123 85959, 20050123-21:59:59 + r"%ExY%Exm%Exd(?:-|T| ?)%ExH:?%ExM:?%ExS(?:[.,]%f)?(?:\s*%z)?", # prefixed with optional named time zone (monit): # PDT Apr 16 21:05:29 r"(?:%Z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?", diff --git a/fail2ban/tests/files/logs/xrdp b/fail2ban/tests/files/logs/xrdp new file mode 100644 index 00000000..1a9e8ee2 --- /dev/null +++ b/fail2ban/tests/files/logs/xrdp @@ -0,0 +1,37 @@ +# +# /var/log/xrdp-sesman.log -- should be about the same on any linux distro +# + +# failJSON: { "time": "2022-04-07T12:11:06", "match": true, "host": "10.171.161.151"} +[20220407-12:11:06] [INFO ] AUTHFAIL: user=badtypist ip=::ffff:10.171.161.151 time=1649351466 + +# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.1 is an innocent, injected address +# failJSON: { "time": "2022-04-07T12:11:24", "match": true, "host": "10.171.161.151", "desc": "specifying ip address as username"} +[20220407-12:11:24] [INFO ] AUTHFAIL: user=192.168.0.1 ip=::ffff:10.171.161.151 time=1649351484 + +# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.4 is an innocent, injected address +# failJSON: { "time": "2022-04-07T12:22:02", "match": true, "host": "10.171.161.151", "desc": "more devious log injection"} +[20220407-12:22:02] [INFO ] AUTHFAIL: user=loginjector ip=192.168.0.4 time=123456789\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection ip=::ffff:10.171.161.151 time=1649352122 + + +# +# /var/log/messages -- RHEL/Fedora family +# + +# failJSON: { "time": "2005-04-07T12:11:06", "match": true, "host": "10.171.161.151"} +Apr 7 12:11:06 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=badtypist ip=::ffff:10.171.161.151 time=1649351466 + +# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.1 is an innocent, injected address +# failJSON: { "time": "2005-04-07T12:11:24", "match": true, "host": "10.171.161.151", "desc": "specifying ip address as username"} +Apr 7 12:11:24 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=192.168.0.1 ip=::ffff:10.171.161.151 time=1649351484 + +# ip injection: 10.171.161.151 should be matched as the host; 192.168.0.4 is an innocent, injected address +# failJSON: { "time": "2005-04-07T12:22:02", "match": true, "host": "10.171.161.151", "desc": "more devious log injection"} +Apr 7 12:22:02 servername xrdp-sesman[41441]: [INFO ] AUTHFAIL: user=loginjector ip=192.168.0.4 time=123456789\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection ip=::ffff:10.171.161.151 time=1649352122 + +# ip injection: innocent, injected ip 192.168.0.4 in a line that shouldn't contain a host +# failJSON: { "match": false } +Apr 7 12:22:02 servername xrdp[52415]: [INFO ] xrdp_wm_log_msg: login failed for user loginjector ip=192.168.0.4 time=12345\n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection + +# failJSON: { "match": false } +Apr 7 12:22:02 servername xrdp[52415]: [INFO ] n[20220407-12:16:59] [INFO ] AUTHFAIL: user=endinjection