Skip to content

Commit 3439310

Browse files
THREAT-411 ZIA AdminAuditRules - Password, Log, Backup (panther-labs#1425)
Co-authored-by: Ariel Ropek <[email protected]>
1 parent c9724bf commit 3439310

11 files changed

+718
-0
lines changed

packs/zscaler_zia.yml

+5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ PackDefinition:
66
IDs:
77
- ZIA.Account.Access.Removed
88
- ZIA.Additional.Cloud.Roles
9+
- ZIA.Backup.Deleted
910
- ZIA.Cloud.Account.Created
11+
- ZIA.Golden.Restore.Point.Dropped
12+
- ZIA.Insecure.Password.Settings
13+
- ZIA.Logs.Downloaded
14+
- ZIA.Log.Streaming.Disabled
1015
- ZIA.Password.Expiration
1116
- ZIA.Trust.Modification
1217
- panther_zscaler_helpers
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from panther_zscaler_helpers import zia_alert_context, zia_success
2+
3+
4+
def rule(event):
5+
if not zia_success(event):
6+
return False
7+
action = event.deep_get("event", "action", default="ACTION_NOT_FOUND")
8+
category = event.deep_get("event", "category", default="CATEGORY_NOT_FOUND")
9+
if action == "DELETE" and category == "BACKUP_AND_RESTORE":
10+
return True
11+
return False
12+
13+
14+
def title(event):
15+
return (
16+
f"[Zscaler.ZIA]: Backup was deleted by admin with id "
17+
f"[{event.deep_get('event', 'adminid', default='<ADMIN_ID_NOT_FOUND>')}]"
18+
)
19+
20+
21+
def alert_context(event):
22+
return zia_alert_context(event)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
AnalysisType: rule
2+
RuleID: ZIA.Backup.Deleted
3+
Description: This rule detects when ZIA backup data was deleted.
4+
DisplayName: ZIA Backup Deleted
5+
Runbook: Verify that this change was planned. If not, make sure to restore the backup.
6+
Reference: https://help.zscaler.com/zia/about-backup-and-restore
7+
Enabled: true
8+
Filename: zia_backup_deleted.py
9+
Severity: Medium
10+
Reports:
11+
MITRE ATT&CK:
12+
- TA0005:T1562.008 # Disable or Modify Cloud Logs
13+
LogTypes:
14+
- Zscaler.ZIA.AdminAuditLog
15+
DedupPeriodMinutes: 60
16+
Threshold: 1
17+
Tests:
18+
- Name: Backup deleted
19+
ExpectedResult: true
20+
Log:
21+
{
22+
"event": {
23+
"action": "DELETE",
24+
"adminid": "[email protected]",
25+
"auditlogtype": "ZIA",
26+
"category": "BACKUP_AND_RESTORE",
27+
"clientip": "1.2.3.4",
28+
"errorcode": "None",
29+
"interface": "UI",
30+
"postaction": { },
31+
"preaction": {
32+
"adminLogin": "[email protected]",
33+
"goldenRestorePoint": false,
34+
"id": 163372,
35+
"name": "test-restore-2",
36+
"time": 1730737925000
37+
},
38+
"recordid": "366",
39+
"resource": "test-restore-2",
40+
"result": "SUCCESS",
41+
"subcategory": "BACKUP_AND_RESTORE",
42+
"time": "2024-11-04 16:32:18.000000000"
43+
},
44+
"sourcetype": "zscalernss-audit"
45+
}
46+
- Name: Backup created
47+
ExpectedResult: false
48+
Log:
49+
{
50+
"event": {
51+
"action": "CREATE",
52+
"adminid": "[email protected]",
53+
"auditlogtype": "ZIA",
54+
"category": "BACKUP_AND_RESTORE",
55+
"clientip": "1.2.3.4",
56+
"errorcode": "None",
57+
"interface": "UI",
58+
"postaction": {
59+
"adminLogin": "[email protected]",
60+
"goldenRestorePoint": false,
61+
"id": 163372,
62+
"name": "test-restore-2",
63+
"time": 1730737925000
64+
},
65+
"preaction": {
66+
"goldenRestorePoint": false,
67+
"id": 0,
68+
"name": "test-restore-2",
69+
"time": 0
70+
},
71+
"recordid": "365",
72+
"resource": "test-restore-2",
73+
"result": "SUCCESS",
74+
"subcategory": "BACKUP_AND_RESTORE",
75+
"time": "2024-11-04 16:32:05.000000000"
76+
},
77+
"sourcetype": "zscalernss-audit"
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from panther_zscaler_helpers import zia_alert_context, zia_success
2+
3+
4+
def rule(event):
5+
if not zia_success(event):
6+
return False
7+
action = event.deep_get("event", "action", default="ACTION_NOT_FOUND")
8+
category = event.deep_get("event", "category", default="CATEGORY_NOT_FOUND")
9+
golden_restore_point_pre = event.deep_get(
10+
"event",
11+
"preaction",
12+
"goldenRestorePoint",
13+
default="<PRE_RESTORE_POINT_NOT_FOUND>",
14+
)
15+
golden_restore_point_post = event.deep_get(
16+
"event",
17+
"postaction",
18+
"goldenRestorePoint",
19+
default="<POPT_RESTORE_POINT_NOT_FOUND>",
20+
)
21+
if (
22+
action == "UPDATE"
23+
and category == "BACKUP_AND_RESTORE"
24+
and golden_restore_point_pre is True
25+
and golden_restore_point_post is False
26+
):
27+
return True
28+
return False
29+
30+
31+
def title(event):
32+
return (
33+
f"[Zscaler.ZIA]: goldenRestorePoint was dropped by admin with id "
34+
f"[{event.deep_get('event', 'adminid', default='<ADMIN_ID_NOT_FOUND>')}]"
35+
)
36+
37+
38+
def alert_context(event):
39+
return zia_alert_context(event)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
AnalysisType: rule
2+
RuleID: ZIA.Golden.Restore.Point.Dropped
3+
Description: This rule detects when ZIA goldenRestorePoint was dropped.
4+
It means that some piece of information that was impossible to delete before, now is deletable
5+
DisplayName: ZIA Golden Restore Point Dropped
6+
Runbook: Verify that this change was planned. If not, revert the change.
7+
Reference: https://help.zscaler.com/zia/about-backup-and-restore
8+
Enabled: true
9+
Filename: zia_golden_restore_point_dropped.py
10+
Severity: Medium
11+
Reports:
12+
MITRE ATT&CK:
13+
- TA0005:T1562.008 # Disable or Modify Cloud Logs
14+
LogTypes:
15+
- Zscaler.ZIA.AdminAuditLog
16+
DedupPeriodMinutes: 60
17+
Threshold: 1
18+
Tests:
19+
- Name: goldenRestorePoint dropped
20+
ExpectedResult: true
21+
Log:
22+
{
23+
"event": {
24+
"action": "UPDATE",
25+
"adminid": "[email protected]",
26+
"auditlogtype": "ZIA",
27+
"category": "BACKUP_AND_RESTORE",
28+
"clientip": "1.2.3.4",
29+
"errorcode": "None",
30+
"interface": "UI",
31+
"postaction": {
32+
"adminLogin": "[email protected]",
33+
"goldenRestorePoint": false,
34+
"id": 163371,
35+
"name": "test-restore",
36+
"time": 1730737915000
37+
},
38+
"preaction": {
39+
"adminLogin": "[email protected]",
40+
"goldenRestorePoint": true,
41+
"id": 163371,
42+
"name": "test-restore",
43+
"time": 1730737915000
44+
},
45+
"recordid": "367",
46+
"resource": "test-restore",
47+
"result": "SUCCESS",
48+
"subcategory": "BACKUP_AND_RESTORE",
49+
"time": "2024-11-04 16:32:28.000000000"
50+
},
51+
"sourcetype": "zscalernss-audit"
52+
}
53+
- Name: Backup created
54+
ExpectedResult: false
55+
Log:
56+
{
57+
"event": {
58+
"action": "CREATE",
59+
"adminid": "[email protected]",
60+
"auditlogtype": "ZIA",
61+
"category": "BACKUP_AND_RESTORE",
62+
"clientip": "1.2.3.4",
63+
"errorcode": "None",
64+
"interface": "UI",
65+
"postaction": {
66+
"adminLogin": "[email protected]",
67+
"goldenRestorePoint": false,
68+
"id": 163372,
69+
"name": "test-restore-2",
70+
"time": 1730737925000
71+
},
72+
"preaction": {
73+
"goldenRestorePoint": false,
74+
"id": 0,
75+
"name": "test-restore-2",
76+
"time": 0
77+
},
78+
"recordid": "365",
79+
"resource": "test-restore-2",
80+
"result": "SUCCESS",
81+
"subcategory": "BACKUP_AND_RESTORE",
82+
"time": "2024-11-04 16:32:05.000000000"
83+
},
84+
"sourcetype": "zscalernss-audit"
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from panther_zscaler_helpers import zia_alert_context, zia_success
2+
3+
4+
def rule(event):
5+
if not zia_success(event):
6+
return False
7+
auth_frequency = event.deep_get(
8+
"event",
9+
"postaction",
10+
"authFrequency",
11+
default="<AUTH_FREQUENCY_NOT_FOUND>",
12+
)
13+
password_expiry = event.deep_get(
14+
"event",
15+
"postaction",
16+
"passwordExpiry",
17+
default="<PASSWORD_EXPIRY_NOT_FOUND>",
18+
)
19+
password_strength = event.deep_get(
20+
"event",
21+
"postaction",
22+
"passwordStrength",
23+
default="<PASSWORD_STRENGTH_NOT_FOUND>",
24+
)
25+
if (
26+
auth_frequency == "PERMANENT_COOKIE"
27+
or password_expiry == "NEVER" # nosec bandit B105
28+
or password_strength == "NONE" # nosec bandit B105
29+
):
30+
return True
31+
return False
32+
33+
34+
def dedup(event):
35+
return event.deep_get("event", "adminid", default="<ADMIN_ID_NOT_FOUND>")
36+
37+
38+
def title(event):
39+
return (
40+
f"[Zscaler.ZIA]: Password settings are insecure for admin with id "
41+
f"[{event.deep_get('event', 'adminid', default='<ADMIN_ID_NOT_FOUND>')}]"
42+
)
43+
44+
45+
def alert_context(event):
46+
return zia_alert_context(event)

0 commit comments

Comments
 (0)