Skip to content

Commit 56519a1

Browse files
committed
Add Azlaroc/sftpgo collection with tests for PR crowdsecurity#1461
1 parent 4145eea commit 56519a1

File tree

6 files changed

+112
-0
lines changed

6 files changed

+112
-0
lines changed

.tests/sftpgo-logs/config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
parsers:
2+
- crowdsecurity/syslog-logs
3+
- ./parsers/s01-parse/Azlaroc/sftpgo-logs.yaml
4+
- crowdsecurity/dateparse-enrich
5+
scenarios: []
6+
postoverflows: []
7+
log_file: sftpgo-logs.log
8+
log_type: sftpgo
9+
ignore_parsers: false

.tests/sftpgo-logs/parser.assert

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
len(results) == 4
2+
len(results["s00-raw"]["crowdsecurity/non-syslog"]) == 10
3+
results["s00-raw"]["crowdsecurity/non-syslog"][0].Success == true
4+
results["s00-raw"]["crowdsecurity/non-syslog"][1].Success == true
5+
results["s00-raw"]["crowdsecurity/non-syslog"][2].Success == true
6+
results["s00-raw"]["crowdsecurity/non-syslog"][3].Success == true
7+
results["s00-raw"]["crowdsecurity/non-syslog"][4].Success == true
8+
results["s00-raw"]["crowdsecurity/non-syslog"][5].Success == true
9+
results["s00-raw"]["crowdsecurity/non-syslog"][6].Success == true
10+
results["s00-raw"]["crowdsecurity/non-syslog"][7].Success == true
11+
results["s00-raw"]["crowdsecurity/non-syslog"][8].Success == true
12+
results["s00-raw"]["crowdsecurity/non-syslog"][9].Success == true
13+
len(results["s00-raw"]["crowdsecurity/syslog-logs"]) == 10
14+
results["s00-raw"]["crowdsecurity/syslog-logs"][0].Success == false
15+
results["s00-raw"]["crowdsecurity/syslog-logs"][1].Success == false
16+
results["s00-raw"]["crowdsecurity/syslog-logs"][2].Success == false
17+
results["s00-raw"]["crowdsecurity/syslog-logs"][3].Success == false
18+
results["s00-raw"]["crowdsecurity/syslog-logs"][4].Success == false
19+
results["s00-raw"]["crowdsecurity/syslog-logs"][5].Success == false
20+
results["s00-raw"]["crowdsecurity/syslog-logs"][6].Success == false
21+
results["s00-raw"]["crowdsecurity/syslog-logs"][7].Success == false
22+
results["s00-raw"]["crowdsecurity/syslog-logs"][8].Success == false
23+
results["s00-raw"]["crowdsecurity/syslog-logs"][9].Success == false
24+
len(results["s01-parse"][""]) == 10
25+
results["s01-parse"][""][0].Success == false
26+
results["s01-parse"][""][1].Success == false
27+
results["s01-parse"][""][2].Success == false
28+
results["s01-parse"][""][3].Success == false
29+
results["s01-parse"][""][4].Success == false
30+
results["s01-parse"][""][5].Success == true
31+
results["s01-parse"][""][6].Success == true
32+
results["s01-parse"][""][7].Success == false
33+
results["s01-parse"][""][8].Success == true
34+
results["s01-parse"][""][9].Success == true
35+
len(results["s02-enrich"]["crowdsecurity/dateparse-enrich"]) == 4
36+
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Success == true
37+
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Success == true
38+
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Success == true
39+
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Success == true
40+
len(results["success"][""]) == 0

.tests/sftpgo-logs/sftpgo-logs.log

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"eventmanager","message":"loading updated rules"}
2+
{"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"}
3+
{"level":"debug","time":"2025-09-13T12:14:31.013","sender":"eventmanager","message":"recently updated event rules loaded: 0"}
4+
{"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"}
5+
{"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"}
6+
{"level":"debug","time":"2025-09-13T12:16:35.504","sender":"connection_failed","client_ip":"174.245.92.29","username":"switchgo","login_type":"password","protocol":"SSH","error":"invalid credentials"}
7+
{"level":"debug","time":"2025-09-13T12:16:35.843","sender":"connection_failed","client_ip":"174.245.92.29","username":"switchgo","login_type":"keyboard-interactive","protocol":"SSH","error":"invalid credentials"}
8+
{"level":"debug","time":"2025-09-13T12:16:36.014","sender":"sftpd","message":"failed to accept an incoming connection from ip \"174.245.92.29\": ssh: disconnect, reason 11: "}
9+
{"level":"debug","time":"2025-09-13T12:16:36.014","sender":"connection_failed","client_ip":"174.245.92.29","username":"","login_type":"no_auth_tried","protocol":"SSH","error":"ssh: disconnect, reason 11: "}
10+
{"level":"debug","time":"2025-09-13T12:16:42.724","sender":"connection_failed","client_ip":"174.245.92.29","username":"switchgo","login_type":"password","protocol":"SSH","error":"invalid credentials"}

collections/Azlaroc/sftpgo.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: Azlaroc/sftpgo
2+
description: "Collection for detecting bruteforce attacks on SFTPGo (FTP and SFTP protocols)"
3+
author: "Azlaroc"
4+
parsers:
5+
- Azlaroc/sftpgo-logs
6+
scenarios:
7+
- Azlaroc/sftpgo-bf
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
onsuccess: next_stage
2+
pattern_syntax:
3+
SFTPGO_TIME: '%{YEAR}-%{MONTHNUM}-%{MONTHDAY}T%{HOUR}:%{MINUTE}:%{SECOND}\.%{NUMBER}'
4+
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}"\}'
5+
filter: evt.Parsed.program == 'sftpgo'
6+
nodes:
7+
- grok:
8+
name: SFTPGO_FAILED
9+
apply_on: message
10+
statics:
11+
- meta: log_type
12+
value: sftpgo_auth
13+
- meta: source_ip
14+
expression: evt.Parsed.client_ip
15+
- meta: target_user
16+
expression: evt.Parsed.username
17+
- meta: protocol
18+
expression: evt.Parsed.protocol
19+
- meta: login_type
20+
expression: evt.Parsed.login_type
21+
- meta: error
22+
expression: evt.Parsed.error
23+
- meta: is_failed_login
24+
value: true
25+
- target: evt.StrTime
26+
expression: evt.Parsed.evt_time
27+
- meta: service
28+
value: sftpgo
29+
description: Parse SFTPGo authentication logs (failed attempts only)

scenarios/Azlaroc/sftpgo-bf.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type: leaky
2+
name: Azlaroc/sftpgo-bf
3+
description: "Detect SFTPGo bruteforce attacks on FTP/SSH"
4+
filter: "evt.Meta.log_type == 'sftpgo_auth' && evt.Meta.is_failed_login == 'true'"
5+
groupby: evt.Meta.source_ip
6+
capacity: 3
7+
leakspeed: "30s"
8+
blackhole: 4h
9+
labels:
10+
service: sftpgo
11+
confidence: 3
12+
spoofable: 0
13+
classification:
14+
- attack.T1110
15+
behavior: "sftp:bruteforce"
16+
label: "SFTPGo Bruteforce"
17+
remediation: true

0 commit comments

Comments
 (0)