diff --git a/.tests/unifi-logs-s01/config.yaml b/.tests/unifi-logs-s01/config.yaml new file mode 100644 index 00000000000..0aacc54a226 --- /dev/null +++ b/.tests/unifi-logs-s01/config.yaml @@ -0,0 +1,9 @@ +parsers: + - crowdsecurity/unifi-logs + - ./parsers/s01-parse/PintjesB/unifi-logs.yaml +scenarios: + - "./scenarios/s01-parse/PintjesB/unifi-firewall-hits.yaml" +postoverflows: + - "" +log_file: s01-unifi-v1.log +log_type: unifi diff --git a/.tests/unifi-logs-s01/parser.assert b/.tests/unifi-logs-s01/parser.assert new file mode 100644 index 00000000000..1f2ce6638b9 --- /dev/null +++ b/.tests/unifi-logs-s01/parser.assert @@ -0,0 +1,47 @@ +len(results) == 3 +results["s00-raw"]["crowdsecurity/unifi-logs"][0].Success == true +results["s00-raw"]["crowdsecurity/unifi-logs"][0].Evt.Parsed["logsource"] == "syslog" +results["s00-raw"]["crowdsecurity/unifi-logs"][0].Evt.Parsed["timestamp"] == "Jun 13 23:29:15" +results["s00-raw"]["crowdsecurity/unifi-logs"][0].Evt.Meta["machine"] == "UDMP-DTC" +results["s00-raw"]["crowdsecurity/unifi-logs"][1].Success == true +results["s00-raw"]["crowdsecurity/unifi-logs"][1].Evt.Parsed["logsource"] == "syslog" +results["s00-raw"]["crowdsecurity/unifi-logs"][1].Evt.Parsed["timestamp"] == "Feb 8 18:19:31" +results["s00-raw"]["crowdsecurity/unifi-logs"][1].Evt.Meta["machine"] == "Unifi-Dream-Machine" +results["s01-parse"]["PintjesB/unifi-logs"][0].Success == true +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["action"] == "D" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["dst_ip"] == "192.168.1.25" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["dst_port"] == "54329" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["dst_zone"] == "LOCAL" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["fw_descr"] == "[WAN_LOCAL]Block All Traffic" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["if_in"] == "eth8" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["logsource"] == "syslog" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["mac"] == "74:ac:b9:1c:62:e5:00:17:10:2b:31:a9:08:00" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["proto"] == "UDP" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["remainder"] == "LEN=102 MARK=1a0000" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["rule_id"] == "2147483647" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["skip2"] == "122 TOS=00 PREC=0x00 TTL=49 ID=45366 DF" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["source_ip"] == "3.3.3.3" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["src_port"] == "38451" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Parsed["timestamp"] == "Jun 13 23:29:15" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Meta["log_type"] == "firewall_block_rule_hit" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Meta["machine"] == "UDMP-DTC" +results["s01-parse"]["PintjesB/unifi-logs"][0].Evt.Meta["source_ip"] == "3.3.3.3" +results["s01-parse"]["PintjesB/unifi-logs"][1].Success == true +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["action"] == "D" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["dst_ip"] == "10.10.10.10" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["dst_port"] == "29552" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["dst_zone"] == "LOCAL" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["fw_descr"] == "[WAN_LOCAL]Drop All Other Traf" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["if_in"] == "eth4" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["logsource"] == "syslog" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["mac"] == "fake-mac-address" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["proto"] == "TCP" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["remainder"] == "SEQ=2451790175 ACK=0 WINDOW=1024 SYN URGP=0 MARK=1a0000" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["rule_id"] == "2147483647" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["skip2"] == "40 TOS=00 PREC=0x00 TTL=239 ID=13706" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["source_ip"] == "72.60.20.10" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["src_port"] == "45584" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Parsed["timestamp"] == "Feb 8 18:19:31" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Meta["log_type"] == "firewall_block_rule_hit" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Meta["machine"] == "Unifi-Dream-Machine" +results["s01-parse"]["PintjesB/unifi-logs"][1].Evt.Meta["source_ip"] == "72.60.20.10" \ No newline at end of file diff --git a/.tests/unifi-logs-s01/s01-unifi-v1.log b/.tests/unifi-logs-s01/s01-unifi-v1.log new file mode 100644 index 00000000000..877d904e435 --- /dev/null +++ b/.tests/unifi-logs-s01/s01-unifi-v1.log @@ -0,0 +1,3 @@ +Jun 13 23:29:15 UDMP-DTC [WAN_LOCAL-D-2147483647] DESCR="[WAN_LOCAL]Block All Traffic" IN=eth8 OUT= MAC=74:ac:b9:1c:62:e5:00:17:10:2b:31:a9:08:00 SRC=3.3.3.3 DST=192.168.1.25 LEN=122 TOS=00 PREC=0x00 TTL=49 ID=45366 DF PROTO=UDP SPT=38451 DPT=54329 LEN=102 MARK=1a0000 +Feb 8 18:19:31 Unifi-Dream-Machine [WAN_LOCAL-D-2147483647] DESCR="[WAN_LOCAL]Drop All Other Traf" IN=eth4 OUT= MAC=fake-mac-address SRC=72.60.20.10 DST=10.10.10.10 LEN=40 TOS=00 PREC=0x00 TTL=239 ID=13706 PROTO=TCP SPT=45584 DPT=29552 SEQ=2451790175 ACK=0 WINDOW=1024 SYN URGP=0 MARK=1a0000 +Jun 13 23:29:15 UDMP-DTC [WAN_LOCAL-A-2147483647] DESCR="[WAN_LOCAL]Block All Traffic" IN=eth8 OUT= MAC=74:ac:b9:1c:62:e5:00:17:10:2b:31:a9:08:00 SRC=1.1.1.1 DST=20.20.20.20 LEN=122 TOS=00 PREC=0x00 TTL=49 ID=45366 DF PROTO=UDP SPT=38451 DPT=54329 LEN=102 MARK=1a0000 diff --git a/.tests/unifi-logs-s01/scenario.assert b/.tests/unifi-logs-s01/scenario.assert new file mode 100644 index 00000000000..e69de29bb2d diff --git a/parsers/s01-parse/PintjesB/unifi-logs.md b/parsers/s01-parse/PintjesB/unifi-logs.md new file mode 100644 index 00000000000..8365592adae --- /dev/null +++ b/parsers/s01-parse/PintjesB/unifi-logs.md @@ -0,0 +1,16 @@ +Parsing of Unifi firewall logs + +Example acquisition for this collection: +```yaml +--- +filenames: + - /syslog-server/unifi-firewall.log +labels: + type: unifi +``` + +TODO: +- [x] Firewall WAN rule hits +- [ ] Firewall IPS logs +- [ ] Firewall IDS logs +- [ ] Firewall auth logs (?) \ No newline at end of file diff --git a/parsers/s01-parse/PintjesB/unifi-logs.yaml b/parsers/s01-parse/PintjesB/unifi-logs.yaml new file mode 100644 index 00000000000..94af83cf960 --- /dev/null +++ b/parsers/s01-parse/PintjesB/unifi-logs.yaml @@ -0,0 +1,34 @@ +name: PintjesB/unifi-logs +description: "Parse Unifi firewall logs" +onsuccess: next_stage +pattern_syntax: + ACTION: (D|R) + ZONE: (LAN|WAN|LOCAL|VPN|DMZ) + IFACE_OR_EMPTY: (?:[a-zA-Z]+[0-9]*|) +nodes: + - grok: + pattern: '^\[WAN_%{ZONE:dst_zone}-%{ACTION:action}-%{INT:rule_id}\] DESCR="%{DATA:fw_descr}" IN=%{IFACE_OR_EMPTY:if_in} OUT=%{IFACE_OR_EMPTY:if_out} MAC=%{DATA:mac} SRC=%{IP:source_ip} DST=%{IP:dst_ip} LEN=%{DATA:skip2} PROTO=%{WORD:proto} SPT=%{INT:src_port} DPT=%{INT:dst_port} %{GREEDYDATA:remainder}' + apply_on: message + statics: + - meta: log_type + value: firewall_block_rule_hit + +statics: + - meta: action + expression: 'evt.Parsed.action == "A" ? "accept" : (evt.Parsed.action == "D" ? "drop" : (evt.Parsed.action == "R" ? "reject" : "unknown"))' + # - meta: source_zone + # expression: "evt.Parsed.src_zone" + # - meta: destination_zone + # expression: "evt.Parsed.dst_zone" + - meta: source_ip + expression: "evt.Parsed.source_ip" + - meta: destination_ip + expression: "evt.Parsed.dst_ip" + # - meta: source_port + # expression: "evt.Parsed.src_port" + # - meta: destination_port + # expression: "evt.Parsed.dst_port" + - meta: protocol + expression: "evt.Parsed.proto" + # - meta: rule_id + # expression: "evt.Parsed.rule_id" \ No newline at end of file diff --git a/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.md b/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.md new file mode 100644 index 00000000000..1e62e5d7503 --- /dev/null +++ b/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.md @@ -0,0 +1,9 @@ +Scenario to trigger when a certain IP has hit too many block/reject firewall rules. + +(over 15 hits, 10 seconds between each hit) + +TODO: +- [x] Firewall WAN rule hits +- [ ] Firewall IPS logs +- [ ] Firewall IDS logs +- [ ] Firewall auth logs (?) \ No newline at end of file diff --git a/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.yaml b/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.yaml new file mode 100644 index 00000000000..8a3a9f45b2b --- /dev/null +++ b/scenarios/PintjesB/unifi-logs/unifi-firewall-hits.yaml @@ -0,0 +1,24 @@ +type: leaky +name: PintjesB/unifi-firewall-hits +description: "Detect repeated firewall rule hits on Unifi" +filter: "evt.Meta.log_type == 'firewall_block_rule_hit' +groupby: evt.Meta.source_ip +capacity: 15 +leakspeed: 10s +blackhole: 1m +labels: + remediation: true + classification: + - attack.T1046 + - attack.T1595.002 + - attack.T1595 + - attack.TA0001 + - attack.T1190 + - attack.1133 + - attack.T1562 + - attack.TA0011 + - attack.T1071 + behavior: "tcp:scan" + label: "Unifi rule hit" + spoofable: 3 + confidence: 1