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
11 changes: 11 additions & 0 deletions .tests/sharry-bf/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
parsers:
- crowdsecurity/syslog-logs
- crowdsecurity/dateparse-enrich
- ./parsers/s01-parse/plague-doctor/sharry-logs.yaml
scenarios:
- ./scenarios/plague-doctor/sharry-bf.yaml
postoverflows:
- ""
log_file: sharry.log
log_type: sharry
ignore_parsers: true
Empty file added .tests/sharry-bf/parser.assert
Empty file.
44 changes: 44 additions & 0 deletions .tests/sharry-bf/scenario.assert
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
len(results) == 1
"1.136.110.240" in results[0].Overflow.GetSources()
results[0].Overflow.Sources["1.136.110.240"].IP == "1.136.110.240"
results[0].Overflow.Sources["1.136.110.240"].Range == ""
results[0].Overflow.Sources["1.136.110.240"].GetScope() == "Ip"
results[0].Overflow.Sources["1.136.110.240"].GetValue() == "1.136.110.240"
results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "sharry.log"
results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "sharry_failed_auth"
results[0].Overflow.Alert.Events[0].GetMeta("service") == "sharry"
results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "1.136.110.240"
results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-02-12T12:50:22+11:00"
results[0].Overflow.Alert.Events[0].GetMeta("username") == "Thgg"
results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "sharry.log"
results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "sharry_failed_auth"
results[0].Overflow.Alert.Events[1].GetMeta("service") == "sharry"
results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "1.136.110.240"
results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-02-12T12:50:25+11:00"
results[0].Overflow.Alert.Events[1].GetMeta("username") == "Thgg"
results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "sharry.log"
results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "sharry_failed_auth"
results[0].Overflow.Alert.Events[2].GetMeta("service") == "sharry"
results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "1.136.110.240"
results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-02-12T12:50:27+11:00"
results[0].Overflow.Alert.Events[2].GetMeta("username") == "Thgg"
results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "sharry.log"
results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "sharry_failed_auth"
results[0].Overflow.Alert.Events[3].GetMeta("service") == "sharry"
results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "1.136.110.240"
results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-02-12T12:50:29+11:00"
results[0].Overflow.Alert.Events[3].GetMeta("username") == "Thgg"
results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "sharry.log"
results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "sharry_failed_auth"
results[0].Overflow.Alert.Events[4].GetMeta("service") == "sharry"
results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "1.136.110.240"
results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-02-12T12:50:31+11:00"
results[0].Overflow.Alert.Events[4].GetMeta("username") == "Thgg"
results[0].Overflow.Alert.GetScenario() == "plague-doctor/sharry-bf"
results[0].Overflow.Alert.Remediation == true
results[0].Overflow.Alert.GetEventsCount() == 5
5 changes: 5 additions & 0 deletions .tests/sharry-bf/sharry.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
2026.02.12 12:50:22:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:50:25:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:50:27:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:50:29:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:50:31:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
10 changes: 10 additions & 0 deletions .tests/sharry-logs/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
parsers:
- crowdsecurity/syslog-logs
- crowdsecurity/dateparse-enrich
- ./parsers/s01-parse/plague-doctor/sharry-logs.yaml
scenarios:
- ""
postoverflows:
- ""
log_file: sharry.log
log_type: sharry
81 changes: 81 additions & 0 deletions .tests/sharry-logs/parser.assert
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
len(results) == 4
len(results["s00-raw"]["crowdsecurity/non-syslog"]) == 3
results["s00-raw"]["crowdsecurity/non-syslog"][0].Success == true
results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["message"] == "2026.02.12 12:50:22:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["program"] == "sharry"
results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_path"] == "sharry.log"
results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_type"] == "file"
results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Whitelisted == false
results["s00-raw"]["crowdsecurity/non-syslog"][1].Success == true
results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["message"] == "2026.02.12 12:50:25:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["program"] == "sharry"
results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_path"] == "sharry.log"
results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_type"] == "file"
results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Whitelisted == false
results["s00-raw"]["crowdsecurity/non-syslog"][2].Success == true
results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["message"] == "2026.02.12 12:45:23:0001 [io-comp...] [INFO ] org.http4s.server.middleware.Logger - HTTP/1.1 200 OK"
results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["program"] == "sharry"
results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_path"] == "sharry.log"
results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_type"] == "file"
results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Whitelisted == false
len(results["s00-raw"]["crowdsecurity/syslog-logs"]) == 3
results["s00-raw"]["crowdsecurity/syslog-logs"][0].Success == false
results["s00-raw"]["crowdsecurity/syslog-logs"][1].Success == false
results["s00-raw"]["crowdsecurity/syslog-logs"][2].Success == false
len(results["s01-parse"]["plague-doctor/sharry-logs"]) == 3
results["s01-parse"]["plague-doctor/sharry-logs"][0].Success == true
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Parsed["message"] == "2026.02.12 12:50:22:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Parsed["program"] == "sharry"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Parsed["source_ip"] == "1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Parsed["timestamp"] == "2026.02.12 12:50:22:0000"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Parsed["username"] == "Thgg"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["datasource_path"] == "sharry.log"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["datasource_type"] == "file"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["log_type"] == "sharry_failed_auth"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["service"] == "sharry"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["source_ip"] == "1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Meta["username"] == "Thgg"
results["s01-parse"]["plague-doctor/sharry-logs"][0].Evt.Whitelisted == false
results["s01-parse"]["plague-doctor/sharry-logs"][1].Success == true
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Parsed["message"] == "2026.02.12 12:50:25:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Parsed["program"] == "sharry"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Parsed["source_ip"] == "1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Parsed["timestamp"] == "2026.02.12 12:50:25:0000"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Parsed["username"] == "Thgg"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["datasource_path"] == "sharry.log"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["datasource_type"] == "file"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["log_type"] == "sharry_failed_auth"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["service"] == "sharry"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["source_ip"] == "1.136.110.240"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Meta["username"] == "Thgg"
results["s01-parse"]["plague-doctor/sharry-logs"][1].Evt.Whitelisted == false
results["s01-parse"]["plague-doctor/sharry-logs"][2].Success == false
len(results["s02-enrich"]["crowdsecurity/dateparse-enrich"]) == 2
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Success == true
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["message"] == "2026.02.12 12:50:22:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["program"] == "sharry"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["source_ip"] == "1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["timestamp"] == "2026.02.12 12:50:22:0000"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["username"] == "Thgg"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_path"] == "sharry.log"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_type"] == "file"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["log_type"] == "sharry_failed_auth"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["service"] == "sharry"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["source_ip"] == "1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["timestamp"] == "2026-02-12T12:50:22+11:00"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["username"] == "Thgg"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Whitelisted == false
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Success == true
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["message"] == "2026.02.12 12:50:25:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["program"] == "sharry"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["source_ip"] == "1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["timestamp"] == "2026.02.12 12:50:25:0000"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["username"] == "Thgg"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_path"] == "sharry.log"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_type"] == "file"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["log_type"] == "sharry_failed_auth"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["service"] == "sharry"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["source_ip"] == "1.136.110.240"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["timestamp"] == "2026-02-12T12:50:25+11:00"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["username"] == "Thgg"
results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Whitelisted == false
3 changes: 3 additions & 0 deletions .tests/sharry-logs/sharry.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2026.02.12 12:50:22:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:50:25:0000 [io-comp...] [INFO ] sharry.restserver.routes.LoginRoutes.makeResponse:232 - Authentication attempt failure for username Thgg from ip 1.136.110.240
2026.02.12 12:45:23:0001 [io-comp...] [INFO ] org.http4s.server.middleware.Logger - HTTP/1.1 200 OK
19 changes: 19 additions & 0 deletions collections/plague-doctor/sharry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Description

A collection to defend [Sharry](https://github.com/eikek/sharry)
deployments against common attacks:

- Sharry parser
- Sharry bruteforce detection

## Acquisition template

Example acquisition for this collection:

```yaml
---
filenames:
- /var/log/sharry/*.log
labels:
type: sharry
```
10 changes: 10 additions & 0 deletions collections/plague-doctor/sharry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
parsers:
- plague-doctor/sharry-logs
scenarios:
- plague-doctor/sharry-bf
description: "Sharry: parser and brute-force detection"
author: plague-doctor
tags:
- linux
- brute-force
- sharry
15 changes: 15 additions & 0 deletions parsers/s01-parse/plague-doctor/sharry-logs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Description

A parser that will search for unauthorized access to Sharry.

## Acquisition template

Example acquisition for this collection:

```yaml
---
filenames:
- /var/log/sharry/*.log
labels:
type: sharry
```
28 changes: 28 additions & 0 deletions parsers/s01-parse/plague-doctor/sharry-logs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
onsuccess: next_stage
#debug: true
filter: "Upper(evt.Parsed.program) == 'SHARRY'"
name: plague-doctor/sharry-logs
description: "Parse Sharry logs"
pattern_syntax:
SHARRY_DATE: "%{YEAR}\\.%{MONTHNUM2}\\.%{MONTHDAY} %{TIME}:%{INT}"
SHARRY_THREAD: "\\[%{DATA:thread}\\]"
SHARRY_LEVEL: "\\[%{LOGLEVEL:level}\\s*\\]"
SHARRY_CLASS: "%{JAVACLASS:class}:%{INT:line}"
nodes:
- grok:
pattern: "^%{SHARRY_DATE:timestamp} %{SHARRY_THREAD} %{SHARRY_LEVEL} %{SHARRY_CLASS} - Authentication attempt failure for username %{USERNAME:username} from ip %{IP:source_ip}"
apply_on: message
statics:
- meta: log_type
value: sharry_failed_auth
statics:
- meta: service
value: sharry
- meta: source_ip
expression: "evt.Parsed.source_ip"
- target: evt.StrTimeFormat
value: "2006.01.02 15:04:05:0000 -0700"
- target: evt.StrTime
expression: evt.Parsed.timestamp + " +0000"
- meta: username
expression: "evt.Parsed.username"
5 changes: 5 additions & 0 deletions scenarios/plague-doctor/sharry-bf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Description

Detect failed Sharry authentications:

- 5 failed authentication attempts within 20 second leakspeed
20 changes: 20 additions & 0 deletions scenarios/plague-doctor/sharry-bf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Sharry bruteforce
type: leaky
name: plague-doctor/sharry-bf
description: "Detect Sharry bruteforce attacks"
filter: "evt.Meta.service == 'sharry' && evt.Meta.log_type == 'sharry_failed_auth'"
leakspeed: 20s
capacity: 4
groupby: evt.Meta.source_ip
blackhole: 1m
reprocess: true
labels:
service: sharry
type: bruteforce
classification:
- attack.T1110
remediation: true
behavior: http:bruteforce
spoofable: 0
confidence: 3

Loading