Téléverser les fichiers vers "/"
This commit is contained in:
commit
02de241319
1 file changed
+289
@@ -0,0 +1,289 @@
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from setuphelpers import *
|
||||
import json
|
||||
import subprocess
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
AUDIT_CATEGORY = "Microsoft Defender"
|
||||
HISTORY_DAYS = 30
|
||||
SIGNATURE_MAX_AGE = 3
|
||||
MAX_DETECTIONS = 100
|
||||
|
||||
THREAT_STATUSES = {
|
||||
0: "Unknown",
|
||||
1: "Detected",
|
||||
2: "Cleaned",
|
||||
3: "Quarantined",
|
||||
4: "Removed",
|
||||
5: "Allowed",
|
||||
6: "Blocked",
|
||||
102: "QuarantineFailed",
|
||||
103: "RemoveFailed",
|
||||
104: "AllowFailed",
|
||||
105: "Abandoned",
|
||||
107: "BlockedFailed",
|
||||
}
|
||||
|
||||
ACTIVE_STATUSES = {1, 5, 105}
|
||||
FAILED_STATUSES = {102, 103, 104, 107}
|
||||
RESOLVED_STATUSES = {2, 3, 4, 6}
|
||||
|
||||
|
||||
def install():
|
||||
print("Microsoft Defender audit package installed")
|
||||
|
||||
|
||||
def powershell_json(script):
|
||||
powershell = os.path.join(
|
||||
os.environ.get("SystemRoot", r"C:\Windows"),
|
||||
"System32",
|
||||
"WindowsPowerShell",
|
||||
"v1.0",
|
||||
"powershell.exe"
|
||||
)
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
powershell,
|
||||
"-NoProfile",
|
||||
"-NonInteractive",
|
||||
"-ExecutionPolicy", "Bypass",
|
||||
"-Command", script,
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=90,
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(
|
||||
result.stderr.decode("utf-8", errors="replace")
|
||||
)
|
||||
|
||||
output = result.stdout.decode(
|
||||
"utf-8-sig", errors="replace"
|
||||
).strip()
|
||||
|
||||
if not output:
|
||||
raise RuntimeError("Empty PowerShell response")
|
||||
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def collect_defender():
|
||||
script = r"""
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$status = Get-MpComputerStatus
|
||||
$cutoff = (Get-Date).AddDays(-30)
|
||||
|
||||
$threats = @(
|
||||
Get-MpThreatDetection |
|
||||
Where-Object {
|
||||
$_.InitialDetectionTime -ge $cutoff
|
||||
} |
|
||||
Sort-Object InitialDetectionTime -Descending |
|
||||
Select-Object -First 100 |
|
||||
ForEach-Object {
|
||||
[PSCustomObject]@{
|
||||
threat_id = $_.ThreatID
|
||||
status_id = [int]$_.ThreatStatusID
|
||||
detected_at = if ($_.InitialDetectionTime) {
|
||||
$_.InitialDetectionTime.ToString("o")
|
||||
} else { $null }
|
||||
changed_at = if ($_.LastThreatStatusChangeTime) {
|
||||
$_.LastThreatStatusChangeTime.ToString("o")
|
||||
} else { $null }
|
||||
error_code = $_.ThreatStatusErrorCode
|
||||
resources = @($_.Resources)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
$threatNames = @{}
|
||||
Get-MpThreat | ForEach-Object {
|
||||
$threatNames[[string]$_.ThreatID] = $_.ThreatName
|
||||
}
|
||||
|
||||
foreach ($threat in $threats) {
|
||||
$id = [string]$threat.threat_id
|
||||
$name = $threatNames[$id]
|
||||
|
||||
$threat | Add-Member -NotePropertyName "name" `
|
||||
-NotePropertyValue $name
|
||||
}
|
||||
|
||||
$result = [PSCustomObject]@{
|
||||
collected_at = (Get-Date).ToUniversalTime().ToString("o")
|
||||
computer_name = $env:COMPUTERNAME
|
||||
running_mode = $status.AMRunningMode
|
||||
antivirus_enabled = $status.AntivirusEnabled
|
||||
realtime_enabled = $status.RealTimeProtectionEnabled
|
||||
behavior_monitor_enabled = $status.BehaviorMonitorEnabled
|
||||
ioav_enabled = $status.IoavProtectionEnabled
|
||||
signature_age = $status.AntivirusSignatureAge
|
||||
signature_version = $status.AntivirusSignatureVersion
|
||||
engine_version = $status.AMEngineVersion
|
||||
threats = @($threats)
|
||||
}
|
||||
|
||||
ConvertTo-Json -InputObject $result -Depth 8 -Compress
|
||||
"""
|
||||
return powershell_json(script)
|
||||
|
||||
|
||||
def normalize_threats(data):
|
||||
result = []
|
||||
|
||||
for threat in data.get("threats", []):
|
||||
status_id = int(threat.get("status_id", 0))
|
||||
|
||||
if status_id in ACTIVE_STATUSES:
|
||||
severity = "ERROR"
|
||||
elif status_id in FAILED_STATUSES:
|
||||
severity = "ERROR"
|
||||
elif status_id in RESOLVED_STATUSES:
|
||||
severity = "RESOLVED"
|
||||
else:
|
||||
severity = "WARNING"
|
||||
|
||||
result.append({
|
||||
"id": threat.get("threat_id"),
|
||||
"name": threat.get("name") or "Unknown threat",
|
||||
"status_id": status_id,
|
||||
"status": THREAT_STATUSES.get(
|
||||
status_id, "Unknown"
|
||||
),
|
||||
"severity": severity,
|
||||
"detected_at": threat.get("detected_at"),
|
||||
"changed_at": threat.get("changed_at"),
|
||||
"resources": threat.get("resources") or [],
|
||||
"error_code": threat.get("error_code"),
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def save_audit(key, value):
|
||||
WAPT.write_audit_data_if_changed(
|
||||
AUDIT_CATEGORY,
|
||||
key,
|
||||
value,
|
||||
keep_days=90
|
||||
)
|
||||
|
||||
|
||||
def audit():
|
||||
try:
|
||||
data = collect_defender()
|
||||
threats = normalize_threats(data)
|
||||
|
||||
active = [
|
||||
t for t in threats
|
||||
if t["severity"] == "ERROR"
|
||||
]
|
||||
uncertain = [
|
||||
t for t in threats
|
||||
if t["severity"] == "WARNING"
|
||||
]
|
||||
resolved = [
|
||||
t for t in threats
|
||||
if t["severity"] == "RESOLVED"
|
||||
]
|
||||
|
||||
status = "OK"
|
||||
problems = []
|
||||
|
||||
mode = data.get("running_mode")
|
||||
|
||||
if mode != "Normal":
|
||||
problems.append(
|
||||
"Defender mode: %s" % mode
|
||||
)
|
||||
status = "WARNING"
|
||||
|
||||
if mode == "Normal":
|
||||
if not data.get("antivirus_enabled"):
|
||||
problems.append("Antivirus disabled")
|
||||
status = "ERROR"
|
||||
|
||||
if not data.get("realtime_enabled"):
|
||||
problems.append("Realtime protection disabled")
|
||||
status = "ERROR"
|
||||
|
||||
age = data.get("signature_age")
|
||||
|
||||
if age is None:
|
||||
problems.append("Unknown signature age")
|
||||
if status == "OK":
|
||||
status = "WARNING"
|
||||
elif int(age) > SIGNATURE_MAX_AGE:
|
||||
problems.append(
|
||||
"Signatures outdated: %s days" % age
|
||||
)
|
||||
if status == "OK":
|
||||
status = "WARNING"
|
||||
|
||||
if active:
|
||||
problems.append(
|
||||
"%d unresolved or failed detections" %
|
||||
len(active)
|
||||
)
|
||||
status = "ERROR"
|
||||
|
||||
if uncertain and status == "OK":
|
||||
problems.append(
|
||||
"%d detections require review" %
|
||||
len(uncertain)
|
||||
)
|
||||
status = "WARNING"
|
||||
|
||||
summary = {
|
||||
"status": status,
|
||||
"computer_name": data.get("computer_name"),
|
||||
"running_mode": mode,
|
||||
"antivirus_enabled": data.get(
|
||||
"antivirus_enabled"
|
||||
),
|
||||
"realtime_enabled": data.get(
|
||||
"realtime_enabled"
|
||||
),
|
||||
"signature_age": data.get("signature_age"),
|
||||
"signature_version": data.get(
|
||||
"signature_version"
|
||||
),
|
||||
"engine_version": data.get("engine_version"),
|
||||
"detection_count": len(threats),
|
||||
"active_count": len(active),
|
||||
"review_count": len(uncertain),
|
||||
"resolved_count": len(resolved),
|
||||
"problems": problems,
|
||||
}
|
||||
|
||||
save_audit("summary", summary)
|
||||
save_audit("detections", threats)
|
||||
save_audit("active_threats", active)
|
||||
|
||||
print(json.dumps(
|
||||
summary,
|
||||
indent=2,
|
||||
ensure_ascii=False
|
||||
))
|
||||
|
||||
return status
|
||||
|
||||
except Exception as exc:
|
||||
error = {
|
||||
"status": "ERROR",
|
||||
"error": str(exc)
|
||||
}
|
||||
|
||||
print("Defender audit error: %s" % exc)
|
||||
|
||||
save_audit("audit_error", error)
|
||||
return "ERROR"
|
||||
|
||||
Reference in new issue
Block a user