Skip to content

Commit

Permalink
Add Audiobookshelf collection (#1153)
Browse files Browse the repository at this point in the history
* Add Audiobookshelf collection

* enhance: Add tests and extend parser to support non json output also

* enhance: Since we are parsing the application logs we can be more restrictive on failed attempts

* chore: run index workflow manually

---------

Co-authored-by: Laurence <[email protected]>
  • Loading branch information
plague-doctor and LaurenceJJones authored Nov 14, 2024
1 parent be8d557 commit 238067b
Show file tree
Hide file tree
Showing 14 changed files with 470 additions and 0 deletions.
62 changes: 62 additions & 0 deletions .index.json
Original file line number Diff line number Diff line change
Expand Up @@ -2999,6 +2999,27 @@
"MariuszKociubinski/bitwarden-bf"
]
},
"PlagueDoctor/audiobookshelf": {
"path": "collections/PlagueDoctor/audiobookshelf.yaml",
"version": "0.1",
"versions": {
"0.1": {
"digest": "8b710f122d03ec1c714045c90bc76df4b23817d7ff5a55f364f6f3dc79ed021f",
"deprecated": false
}
},
"long_description": "IyBEZXNjcmlwdGlvbgoKQSBjb2xsZWN0aW9uIHRvIGRlZmVuZCBbQXVkaW9ib29rc2hlbGYgU2VsZiBIb3N0ZWRdKGh0dHBzOi8vZ2l0aHViLmNvbS9hZHZwbHlyL2F1ZGlvYm9va3NoZWxmKQpkZXBsb3ltZW50cyBhZ2FpbnN0IGNvbW1vbiBhdHRhY2tzOgoKLSBBdWRpb2Jvb2tzaGVsZiBwYXJzZXIKLSBBdWRpb2Jvb2tzaGVsZiBicnV0ZWZvcmNlIGRldGVjdGlvbgoKIyMgQWNxdWlzaXRpb24gdGVtcGxhdGUKCkV4YW1wbGUgYWNxdWlzaXRpb24gZm9yIHRoaXMgY29sbGVjdGlvbjoKCmBgYHlhbWwKLS0tCmZpbGVuYW1lczoKICAtIC92YXIvbG9nL2F1ZGlvYm9va3NoZWxmLyoudHh0CmxhYmVsczoKICB0eXBlOiBhdWRpb2Jvb2tzaGVsZgpgYGAK",
"content": "cGFyc2VyczoKICAgIC0gUGxhZ3VlRG9jdG9yL2F1ZGlvYm9va3NoZWxmLWxvZ3MKc2NlbmFyaW9zOgogICAgLSBQbGFndWVEb2N0b3IvYXVkaW9ib29rc2hlbGYtYmYKZGVzY3JpcHRpb246ICJBdWRpb2Jvb2tzaGVsZjogcGFyc2VyIGFuZCBicnV0ZS1mb3JjZSBkZXRlY3Rpb24iCmF1dGhvcjogUGxhZ3VlRG9jdG9yCnRhZ3M6CiAgICAtIGxpbnV4CiAgICAtIGJydXRlLWZvcmNlCiAgICAtIGF1ZGlvYm9va3NoZWxmCg==",
"description": "Audiobookshelf: parser and brute-force detection",
"author": "PlagueDoctor",
"labels": null,
"parsers": [
"PlagueDoctor/audiobookshelf-logs"
],
"scenarios": [
"PlagueDoctor/audiobookshelf-bf"
]
},
"ZoeyVid/npmplus": {
"path": "collections/ZoeyVid/npmplus.yaml",
"version": "0.3",
Expand Down Expand Up @@ -6625,6 +6646,22 @@
"author": "MariuszKociubinski",
"labels": null
},
"PlagueDoctor/audiobookshelf-logs": {
"path": "parsers/s01-parse/PlagueDoctor/audiobookshelf-logs.yaml",
"stage": "s01-parse",
"version": "0.1",
"versions": {
"0.1": {
"digest": "6b086296359e15379dcfde0ebd430101088f8225601666959f03f93e9baf0442",
"deprecated": false
}
},
"long_description": "IyBEZXNjcmlwdGlvbgoKQSBwYXJzZXIgdGhhdCB3aWxsIHNlYXJjaCBmb3IgdW5hdXRob3JpemVkIGFjY2VzcyB0byBBdWRpb2Jvb2tzaGVsZi4KCiMjIEFjcXVpc2l0aW9uIHRlbXBsYXRlCgpFeGFtcGxlIGFjcXVpc2l0aW9uIGZvciB0aGlzIGNvbGxlY3Rpb246CgpgYGB5YW1sCi0tLQpmaWxlbmFtZXM6CiAgLSAvdmFyL2xvZy9hdWRpb2Jvb2tzaGVsZi8qLnR4dApsYWJlbHM6CiAgdHlwZTogYXVkaW9ib29rc2hlbGYKYGBgCg==",
"content": "b25zdWNjZXNzOiBuZXh0X3N0YWdlCiNkZWJ1ZzogdHJ1ZQpmaWx0ZXI6ICJVcHBlcihldnQuUGFyc2VkLnByb2dyYW0pID09ICdBVURJT0JPT0tTSEVMRiciCm5hbWU6IFBsYWd1ZURvY3Rvci9hdWRpb2Jvb2tzaGVsZi1sb2dzCmRlc2NyaXB0aW9uOiAiUGFyc2UgQXVkaW9ib29rc2hlbGYgbG9ncyIKcGF0dGVybl9zeW50YXg6CiAgICBBQlNfRkFJTEVEX0FVVEg6ICdcW0F1dGhcXSBGYWlsZWQgbG9naW4gYXR0ZW1wdCBmb3IgdXNlcm5hbWUgXFw/IiV7VVNFUk5BTUU6dXNlcm5hbWV9XFw/IiBmcm9tIGlwICV7SVA6c291cmNlX2lwfSBcKCV7REFUQTpyZWFzb259XCknCm5vZGVzOgogICAgLSBncm9rOgogICAgICAgIHBhdHRlcm46ICdcWyV7VElNRVNUQU1QX0lTTzg2MDE6dGltZXN0YW1wfVxdIEVSUk9SOiAle0FCU19GQUlMRURfQVVUSH0nCiAgICAgICAgYXBwbHlfb246IG1lc3NhZ2UKICAgICAgc3RhdGljczoKICAgICAgICAtIG1ldGE6IGxvZ190eXBlCiAgICAgICAgICB2YWx1ZTogYWJzX2ZhaWxlZF9hdXRoCiAgICAtIGZpbHRlcjogJ1VubWFyc2hhbEpTT04oZXZ0LlBhcnNlZC5tZXNzYWdlLCBldnQuVW5tYXJzaGFsZWQsICJhYnMiKSBpbiBbIiIsIG5pbF0nCiAgICAgIGdyb2s6CiAgICAgICAgcGF0dGVybjogIiV7QUJTX0ZBSUxFRF9BVVRIfSIKICAgICAgICBleHByZXNzaW9uOiBldnQuVW5tYXJzaGFsZWQuYWJzLm1lc3NhZ2UKICAgICAgICBzdGF0aWNzOgogICAgICAgICAgLSBtZXRhOiBsb2dfdHlwZQogICAgICAgICAgICB2YWx1ZTogYWJzX2ZhaWxlZF9hdXRoCnN0YXRpY3M6CiAgICAtIG1ldGE6IHNlcnZpY2UKICAgICAgdmFsdWU6IGF1ZGlvYm9va3NoZWxmCiAgICAtIG1ldGE6IHNvdXJjZV9pcAogICAgICBleHByZXNzaW9uOiAiZXZ0LlBhcnNlZC5zb3VyY2VfaXAiCiAgICAtIHRhcmdldDogZXZ0LlN0clRpbWUKICAgICAgZXhwcmVzc2lvbjogJ2V2dC5QYXJzZWQudGltZXN0YW1wICE9ICIiID8gZXZ0LlBhcnNlZC50aW1lc3RhbXAgOiBldnQuVW5tYXJzaGFsZWQuYWJzLnRpbWVzdGFtcCcKICAgICMjIFdlIGNoZWNrIGlmIHRoZSBwYXJzZXIgcGFyc2VkIHRoZSB0aW1lc3RhbXAgb3IgaWYgaXQgd2l0aGluIHRoZSBqc29uIG91dHB1dAogICAgLSBtZXRhOiB1c2VybmFtZQogICAgICBleHByZXNzaW9uOiAiZXZ0LlBhcnNlZC51c2VybmFtZSIK",
"description": "Parse Audiobookshelf logs",
"author": "PlagueDoctor",
"labels": null
},
"Zaulao/aws-alb": {
"path": "parsers/s01-parse/Zaulao/aws-alb.yaml",
"stage": "s01-parse",
Expand Down Expand Up @@ -10138,6 +10175,31 @@
"spoofable": 0
}
},
"PlagueDoctor/audiobookshelf-bf": {
"path": "scenarios/PlagueDoctor/audiobookshelf-bf.yaml",
"version": "0.1",
"versions": {
"0.1": {
"digest": "cce65b68389215d3f755b28d0ebe22a30da59e054e1abcb81209ae74dd4563cd",
"deprecated": false
}
},
"long_description": "IyBEZXNjcmlwdGlvbgoKRGV0ZWN0IGZhaWxlZCBBdWRpb2Jvb2tzaGVsZiBhdXRoZW50aWNhdGlvbnM6CgotIDMgZmFpbGVkIGF1dGhlbnRpY2F0aW9uIGF0dGVtcHRzIHdpdGhpbiAxIG1pbnV0ZSBsZWFrc3BlZWQK",
"content": "IyBBdWRpb2Jvb2tzaGVsZiBicnV0ZWZvcmNlCnR5cGU6IGxlYWt5Cm5hbWU6IFBsYWd1ZURvY3Rvci9hdWRpb2Jvb2tzaGVsZi1iZgpkZXNjcmlwdGlvbjogIkRldGVjdCBBdWRpb2Jvb2tzaGVsZiBicnV0ZWZvcmNlIGF0dGFja3MiCmZpbHRlcjogImV2dC5NZXRhLnNlcnZpY2UgPT0gJ2F1ZGlvYm9va3NoZWxmJyAmJiBldnQuTWV0YS5sb2dfdHlwZSA9PSAnYWJzX2ZhaWxlZF9hdXRoJyIKbGVha3NwZWVkOiAxbQpjYXBhY2l0eTogMwpncm91cGJ5OiBldnQuTWV0YS5zb3VyY2VfaXAKYmxhY2tob2xlOiA1bQpyZXByb2Nlc3M6IHRydWUKbGFiZWxzOgogICAgc2VydmljZTogYXVkaW9ib29rc2hlbGYKICAgIHR5cGU6IGJydXRlZm9yY2UKICAgIGNsYXNzaWZpY2F0aW9uOgogICAgICAgIC0gYXR0YWNrLlQxMTEwCiAgICByZW1lZGlhdGlvbjogdHJ1ZQogICAgYmVoYXZpb3I6IGh0dHA6YnJ1dGVmb3JjZQogICAgc3Bvb2ZhYmxlOiAwCiAgICBjb25maWRlbmNlOiAzCg==",
"description": "Detect Audiobookshelf bruteforce attacks",
"author": "PlagueDoctor",
"labels": {
"behavior": "http:bruteforce",
"classification": [
"attack.T1110"
],
"confidence": 3,
"remediation": true,
"service": "audiobookshelf",
"spoofable": 0,
"type": "bruteforce"
}
},
"a1ad/meshcentral-bf": {
"path": "scenarios/a1ad/meshcentral-bf.yaml",
"version": "0.2",
Expand Down
4 changes: 4 additions & 0 deletions .tests/audiobookshelf-bf/audiobookshelf.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"timestamp":"2024-11-13 09:07:04.784","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"test\" from ip 192.168.1.1 (Invalid password)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 09:07:05.896","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"Hfhh\" from ip 192.168.1.1 (User not found)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 09:07:07.896","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"Hfhh\" from ip 192.168.1.1 (User not found)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 09:07:10.784","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"test\" from ip 192.168.1.1 (Invalid password)","levelName":"ERROR","level":4}
12 changes: 12 additions & 0 deletions .tests/audiobookshelf-bf/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
parsers:
- crowdsecurity/syslog-logs
- crowdsecurity/dateparse-enrich
- ./parsers/s01-parse/PlagueDoctor/audiobookshelf-logs.yaml
scenarios:
- ./scenarios/PlagueDoctor/audiobookshelf-bf.yaml
postoverflows:
- ""
log_file: audiobookshelf.log
log_type: audiobookshelf
ignore_parsers: true

Empty file.
37 changes: 37 additions & 0 deletions .tests/audiobookshelf-bf/scenario.assert
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
len(results) == 1
"192.168.1.1" in results[0].Overflow.GetSources()
results[0].Overflow.Sources["192.168.1.1"].IP == "192.168.1.1"
results[0].Overflow.Sources["192.168.1.1"].Range == ""
results[0].Overflow.Sources["192.168.1.1"].GetScope() == "Ip"
results[0].Overflow.Sources["192.168.1.1"].GetValue() == "192.168.1.1"
results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "audiobookshelf.log"
results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "abs_failed_auth"
results[0].Overflow.Alert.Events[0].GetMeta("service") == "audiobookshelf"
results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "192.168.1.1"
results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2024-11-13T09:07:04.784Z"
results[0].Overflow.Alert.Events[0].GetMeta("username") == "test"
results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "audiobookshelf.log"
results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "abs_failed_auth"
results[0].Overflow.Alert.Events[1].GetMeta("service") == "audiobookshelf"
results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "192.168.1.1"
results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2024-11-13T09:07:05.896Z"
results[0].Overflow.Alert.Events[1].GetMeta("username") == "Hfhh"
results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "audiobookshelf.log"
results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "abs_failed_auth"
results[0].Overflow.Alert.Events[2].GetMeta("service") == "audiobookshelf"
results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "192.168.1.1"
results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2024-11-13T09:07:07.896Z"
results[0].Overflow.Alert.Events[2].GetMeta("username") == "Hfhh"
results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "audiobookshelf.log"
results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file"
results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "abs_failed_auth"
results[0].Overflow.Alert.Events[3].GetMeta("service") == "audiobookshelf"
results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "192.168.1.1"
results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2024-11-13T09:07:10.784Z"
results[0].Overflow.Alert.Events[3].GetMeta("username") == "test"
results[0].Overflow.Alert.GetScenario() == "PlagueDoctor/audiobookshelf-bf"
results[0].Overflow.Alert.Remediation == true
results[0].Overflow.Alert.GetEventsCount() == 4
7 changes: 7 additions & 0 deletions .tests/audiobookshelf-logs/audiobookshelf.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{"timestamp":"2024-11-13 11:03:31.784","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"test\" from ip 192.168.1.1 (Invalid password)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 09:07:05.896","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"Hfhh\" from ip 192.168.1.1 (User not found)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 09:07:17.741","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"Hfhh\" from ip 192.168.1.1 (User not found)","levelName":"ERROR","level":4}
{"timestamp":"2024-11-13 11:03:31.784","source":"Auth.js:888","message":"[Auth] Failed login attempt for username \"test\" from ip 192.168.1.1 (Invalid password)","levelName":"ERROR","level":4}
[2024-11-13 09:54:35.882] ERROR: [Auth] Failed login attempt for username "fooobar" from ip ::1 (User not found) (Auth.js:888)
[2024-10-20 17:48:07.192] INFO: [Auth] User "test" logged in from ip 192.168.1.1
{"timestamp":"2024-11-13 11:03:31.784","source":"Auth.js:888","message":"[Auth] User \"test\" logged in from ip 192.168.1.1","levelName":"INFO","level":1}
10 changes: 10 additions & 0 deletions .tests/audiobookshelf-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/PlagueDoctor/audiobookshelf-logs.yaml
scenarios:
- ""
postoverflows:
- ""
log_file: audiobookshelf.log
log_type: audiobookshelf
Loading

0 comments on commit 238067b

Please sign in to comment.