Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .tests/sftpgo-logs/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
parsers:
- crowdsecurity/syslog-logs
- ./parsers/s01-parse/Azlaroc/sftpgo-logs.yaml
- crowdsecurity/dateparse-enrich
scenarios: []
postoverflows: []
log_file: sftpgo-logs-25.log
log_type: sftpgo
ignore_parsers: false
558 changes: 558 additions & 0 deletions .tests/sftpgo-logs/parser.assert

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions .tests/sftpgo-logs/sftpgo-logs-25.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{"level":"info","time":"2025-09-14T16:56:57.706","sender":"SSH","connection_id":"34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61","message":"User \"bob\" logged in with \"keyboard-interactive\", from ip \"1.2.3.4\", client version \"SSH-2.0-FileZilla_3.69.3\", negotiated algorithms: {KeyExchange:curve25519-sha256 HostKey:ssh-ed25519 Read:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none} Write:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none}}"}
{"level":"debug","time":"2025-09-14T16:56:57.729","sender":"dataprovider_sqlite","message":"last login updated for user \"bob\""}
{"level":"debug","time":"2025-09-14T16:56:57.729","sender":"common","connection_id":"34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61","message":"ssh connection added, num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:56:57.984","sender":"SFTP","connection_id":"SFTP_34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61_1","message":"connection added, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:62078\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:57:09.434","sender":"common","connection_id":"34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61","message":"ssh connection removed, num open ssh connections: 0"}
{"level":"info","time":"2025-09-14T16:57:09.434","sender":"SFTP","connection_id":"SFTP_34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61_1","message":"connection closed, sent exit status {Status:0} error: EOF"}
{"level":"debug","time":"2025-09-14T16:57:09.434","sender":"SFTP","connection_id":"SFTP_34e4ab426f1522416ac2d92815e2041f2e5d4f0af631d6edcd712afbac2ccf61_1","message":"connection removed, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:62078\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:57:09.591","sender":"ftpserverlib","server_id":"FTP_0","clientId":"13","clientIp":"1.2.3.4:62099","message":"Client connected"}
{"level":"debug","time":"2025-09-14T16:57:09.591","sender":"FTP","connection_id":"FTP_0_13","message":"connection added, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:62099\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:57:19.173","sender":"common","connection_id":"FTP_0_13","message":"connection swapped, close fs error: <nil>"}
{"level":"info","time":"2025-09-14T16:57:19.173","sender":"FTP","connection_id":"FTP_0_13","message":"User \"bob\" logged in with \"password\" from ip \"1.2.3.4\", TLS enabled? false"}
{"level":"debug","time":"2025-09-14T16:57:35.709","sender":"FTP","connection_id":"FTP_0_13","message":"connection removed, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:62099\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:57:35.709","sender":"ftpserverlib","server_id":"FTP_0","clientId":"13","clientIp":"1.2.3.4:62099","message":"Client disconnected"}
{"level":"info","time":"2025-09-14T16:57:36.616","sender":"SSH","connection_id":"b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba","message":"User \"bob\" logged in with \"keyboard-interactive\", from ip \"1.2.3.4\", client version \"SSH-2.0-FileZilla_3.69.3\", negotiated algorithms: {KeyExchange:curve25519-sha256 HostKey:ssh-ed25519 Read:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none} Write:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none}}"}
{"level":"debug","time":"2025-09-14T16:57:36.616","sender":"common","connection_id":"b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba","message":"ssh connection added, num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:57:36.899","sender":"SFTP","connection_id":"SFTP_b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba_1","message":"connection added, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:62151\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:57:44.524","sender":"common","connection_id":"b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba","message":"ssh connection removed, num open ssh connections: 0"}
{"level":"info","time":"2025-09-14T16:57:44.524","sender":"SFTP","connection_id":"SFTP_b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba_1","message":"connection closed, sent exit status {Status:0} error: EOF"}
{"level":"debug","time":"2025-09-14T16:57:44.524","sender":"SFTP","connection_id":"SFTP_b6e3b2dca7eec7e1672472f83466853e1589f1991d0fac2b962c2b714fc984ba_1","message":"connection removed, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:62151\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:57:44.689","sender":"ftpserverlib","server_id":"FTP_0","clientId":"14","clientIp":"1.2.3.4:49713","message":"Client connected"}
{"level":"debug","time":"2025-09-14T16:57:44.689","sender":"FTP","connection_id":"FTP_0_14","message":"connection added, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:49713\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:57:45.270","sender":"common","connection_id":"FTP_0_14","message":"connection swapped, close fs error: <nil>"}
{"level":"info","time":"2025-09-14T16:57:45.270","sender":"FTP","connection_id":"FTP_0_14","message":"User \"bob\" logged in with \"password\" from ip \"1.2.3.4\", TLS enabled? false"}
{"level":"debug","time":"2025-09-14T16:58:01.904","sender":"FTP","connection_id":"FTP_0_14","message":"connection removed, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:49713\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:58:01.904","sender":"ftpserverlib","server_id":"FTP_0","clientId":"14","clientIp":"1.2.3.4:49713","message":"Client disconnected"}
{"level":"info","time":"2025-09-14T16:58:02.799","sender":"SSH","connection_id":"55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a","message":"User \"bob\" logged in with \"keyboard-interactive\", from ip \"1.2.3.4\", client version \"SSH-2.0-FileZilla_3.69.3\", negotiated algorithms: {KeyExchange:curve25519-sha256 HostKey:ssh-ed25519 Read:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none} Write:{Cipher:aes256-ctr MAC:hmac-sha2-256 compression:none}}"}
{"level":"debug","time":"2025-09-14T16:58:02.799","sender":"common","connection_id":"55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a","message":"ssh connection added, num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:58:03.096","sender":"SFTP","connection_id":"SFTP_55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a_1","message":"connection added, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:49753\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:58:12.546","sender":"common","connection_id":"55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a","message":"ssh connection removed, num open ssh connections: 0"}
{"level":"info","time":"2025-09-14T16:58:12.546","sender":"SFTP","connection_id":"SFTP_55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a_1","message":"connection closed, sent exit status {Status:0} error: EOF"}
{"level":"debug","time":"2025-09-14T16:58:12.546","sender":"SFTP","connection_id":"SFTP_55f35cafbc585ec9ec97e08785cc43a90310fb89c9b6ef150f46f07b9ae9802a_1","message":"connection removed, local address \"172.21.0.30:2022\", remote address \"1.2.3.4:49753\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:58:12.707","sender":"ftpserverlib","server_id":"FTP_0","clientId":"15","clientIp":"1.2.3.4:49770","message":"Client connected"}
{"level":"debug","time":"2025-09-14T16:58:12.707","sender":"FTP","connection_id":"FTP_0_15","message":"connection added, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:49770\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T16:58:13.269","sender":"common","connection_id":"FTP_0_15","message":"connection swapped, close fs error: <nil>"}
{"level":"info","time":"2025-09-14T16:58:13.269","sender":"FTP","connection_id":"FTP_0_15","message":"User \"bob\" logged in with \"password\" from ip \"1.2.3.4\", TLS enabled? false"}
{"level":"debug","time":"2025-09-14T16:58:17.593","sender":"FTP","connection_id":"FTP_0_15","message":"connection removed, local address \"172.21.0.30:2121\", remote address \"1.2.3.4:49770\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T16:58:17.593","sender":"ftpserverlib","server_id":"FTP_0","clientId":"15","clientIp":"1.2.3.4:49770","message":"Client disconnected"}
{"level":"debug","time":"2025-09-14T16:59:44.443","sender":"connection_failed","client_ip":"5.6.7.8","username":"bob","login_type":"password","protocol":"SSH","error":"invalid credentials"}
{"level":"debug","time":"2025-09-14T16:59:44.796","sender":"connection_failed","client_ip":"5.6.7.8","username":"bob","login_type":"keyboard-interactive","protocol":"SSH","error":"invalid credentials"}
{"level":"debug","time":"2025-09-14T16:59:50.520","sender":"sftpd","message":"failed to accept an incoming connection from ip \"5.6.7.8\": ssh: disconnect, reason 11: "}
{"level":"debug","time":"2025-09-14T16:59:50.520","sender":"connection_failed","client_ip":"5.6.7.8","username":"","login_type":"no_auth_tried","protocol":"SSH","error":"ssh: disconnect, reason 11: "}
{"level":"debug","time":"2025-09-14T17:00:12.273","sender":"ftpserverlib","server_id":"FTP_0","clientId":"16","clientIp":"5.6.7.8:7843","message":"Client connected"}
{"level":"debug","time":"2025-09-14T17:00:12.274","sender":"FTP","connection_id":"FTP_0_16","message":"connection added, local address \"172.21.0.30:2121\", remote address \"5.6.7.8:7843\", num open connections: 1"}
{"level":"debug","time":"2025-09-14T17:00:12.574","sender":"connection_failed","client_ip":"5.6.7.8","username":"bob","login_type":"password","protocol":"FTP","error":"invalid credentials"}
{"level":"error","time":"2025-09-14T17:00:12.574","sender":"ftpserverlib","server_id":"FTP_0","clientId":"16","err":"read tcp 172.21.0.30:2121->5.6.7.8:7843: use of closed network connection","message":"Network error"}
{"level":"debug","time":"2025-09-14T17:00:12.574","sender":"FTP","connection_id":"FTP_0_16","message":"connection removed, local address \"172.21.0.30:2121\", remote address \"5.6.7.8:7843\" close fs error: <nil>, num open connections: 0"}
{"level":"debug","time":"2025-09-14T17:00:12.574","sender":"ftpserverlib","server_id":"FTP_0","clientId":"16","clientIp":"5.6.7.8:7843","message":"Client disconnected"}
{"level":"debug","time":"2025-09-14T17:00:12.574","sender":"ftpserverlib","server_id":"FTP_0","clientId":"16","err":"close tcp 172.21.0.30:2121->5.6.7.8:7843: use of closed network connection","message":"Problem closing control connection"}
10 changes: 10 additions & 0 deletions .tests/sftpgo-logs/sftpgo-logs.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"eventmanager","message":"loading updated rules"}
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"dataprovider_sqlite","message":"start user cache check, update time 2025-09-13 12:04:31.013 -0400 EDT"}
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"eventmanager","message":"recently updated event rules loaded: 0"}
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"eventmanager","message":"event rules updated, fs events: 0, provider events: 0, schedules: 0, ip blocked events: 0, certificate events: 0, IDP login events: 0"}
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"dataprovider_sqlite","message":"end user cache check, new update time 2025-09-13 12:14:31.013 -0400 EDT"}
{"level":"debug","time":"2025-09-13T12:16:35.504","sender":"connection_failed","client_ip":"1.2.3.4","username":"bob","login_type":"password","protocol":"SSH","error":"invalid credentials"}
{"level":"debug","time":"2025-09-13T12:16:35.843","sender":"connection_failed","client_ip":"1.2.3.4","username":"bob","login_type":"keyboard-interactive","protocol":"SSH","error":"invalid credentials"}
{"level":"debug","time":"2025-09-13T12:16:36.014","sender":"sftpd","message":"failed to accept an incoming connection from ip \"1.2.3.4\": ssh: disconnect, reason 11: "}
{"level":"debug","time":"2025-09-13T12:16:36.014","sender":"connection_failed","client_ip":"1.2.3.4","username":"","login_type":"no_auth_tried","protocol":"SSH","error":"ssh: disconnect, reason 11: "}
{"level":"debug","time":"2025-09-13T12:16:42.724","sender":"connection_failed","client_ip":"1.2.3.4","username":"bob","login_type":"password","protocol":"SSH","error":"invalid credentials"}
7 changes: 7 additions & 0 deletions collections/Azlaroc/sftpgo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: Azlaroc/sftpgo
description: "Collection for detecting bruteforce attacks on SFTPGo (FTP and SFTP protocols)"
author: "Azlaroc"
parsers:
- Azlaroc/sftpgo-logs
scenarios:
- Azlaroc/sftpgo-bf
29 changes: 29 additions & 0 deletions parsers/s01-parse/Azlaroc/sftpgo-logs.yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the name key to define it as Azlaroc/sftpgo-logs

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
onsuccess: next_stage
pattern_syntax:
SFTPGO_TIME: '%{YEAR}-%{MONTHNUM}-%{MONTHDAY}T%{HOUR}:%{MINUTE}:%{SECOND}\.%{NUMBER}'
SFTPGO_FAILED: '\{"level":"%{WORD:log_level}","time":"%{SFTPGO_TIME:evt_time}","sender":"connection_failed","client_ip":"%{IPV4:client_ip}","username":"%{DATA:username}","login_type":"%{DATA:login_type}","protocol":"%{WORD:protocol}","error":"%{GREEDYDATA:error}"\}'
filter: evt.Parsed.program == 'sftpgo'
Copy link
Contributor

@LaurenceJJones LaurenceJJones Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can most likely make this filter and the pattern easier to parse

filter: "evt.Parsed.program == 'sftpgo' && UnmarshalJSON(evt.Parsed.message, evt.Unmarshaled, 'sftpgo') in [nil, '']"

this will parse the incoming log line as json and within the statics you can reference them easier via

statics:
  - meta: source_ip
    expression: evt.Unmarshaled.sftpgo["client_ip"]

nodes:
- grok:
name: SFTPGO_FAILED
apply_on: message
statics:
- meta: log_type
value: sftpgo_auth
- meta: source_ip
expression: evt.Parsed.client_ip
- meta: target_user
expression: evt.Parsed.username
- meta: protocol
expression: evt.Parsed.protocol
- meta: login_type
expression: evt.Parsed.login_type
- meta: error
expression: evt.Parsed.error
- meta: is_failed_login
value: true
- target: evt.StrTime
expression: evt.Parsed.evt_time
- meta: service
value: sftpgo
description: Parse SFTPGo authentication logs (failed attempts only)
17 changes: 17 additions & 0 deletions scenarios/Azlaroc/sftpgo-bf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type: leaky
name: Azlaroc/sftpgo-bf
description: "Detect SFTPGo bruteforce attacks on FTP/SSH"
filter: "evt.Meta.log_type == 'sftpgo_auth' && evt.Meta.is_failed_login == 'true'"
groupby: evt.Meta.source_ip
capacity: 3
leakspeed: "30s"
blackhole: 4h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this like 5m instead blackhole doesnt control the ban duration just the supression on repeated buckets if enforce happens at later time.

labels:
service: sftpgo
confidence: 3
spoofable: 0
classification:
- attack.T1110
behavior: "sftp:bruteforce"
label: "SFTPGo Bruteforce"
remediation: true