-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
141 lines (122 loc) Β· 5.71 KB
/
Copy pathProgram.cs
File metadata and controls
141 lines (122 loc) Β· 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using Checksec.Mac.Collectors;
using Checksec.Mac.Core;
using Checksec.Mac.Mscp;
// βββ MacSecCheck β CLI d'audit de posture de securite macOS ββββββββββββββββββββ
// Usage : macseccheck [--json <chemin>] [--quiet] [--baseline <nom>] [--mscp <dir>] [--list-baselines]
// --json <chemin> : ecrit le rapport JSON forensique (defaut : ~/Desktop ou repertoire courant)
// --quiet : n'affiche pas le tableau, ecrit seulement le JSON
// --baseline <nom> : baseline mSCP a evaluer (defaut : cis_lvl1 ; ex. cis_lvl2, disa_stig, 800-53r5_high)
// --mscp <dir> : utilise un checkout externe du depot mSCP au lieu des donnees embarquees
// --list-baselines : liste les baselines disponibles puis quitte
var jsonPath = GetOption(args, "--json");
var quiet = args.Contains("--quiet");
var baseline = GetOption(args, "--baseline") ?? "cis_lvl1";
var mscpDir = GetOption(args, "--mscp");
// Detection de la version majeure de macOS (pour resoudre les regles mSCP versionnees).
var macMajor = GetOption(args, "--os-version")
?? await ProcessRunner.MacOsMajorAsync(CancellationToken.None)
?? "26";
// Chargement des donnees mSCP (embarquees par defaut, ou depuis --mscp).
var mscp = mscpDir is not null
? MscpDataLoader.FromDirectory(mscpDir, macMajor)
: MscpDataLoader.FromEmbedded(macMajor);
if (args.Contains("--list-baselines"))
{
Console.WriteLine("Baselines mSCP disponibles :");
foreach (var b in mscp.BaselineNames.OrderBy(x => x))
Console.WriteLine($" - {b}");
return 0;
}
// Diagnostic : affiche la resolution d'une regle mSCP (check/attendu/fix) pour la version cible.
if (GetOption(args, "--dump-rule") is { } dumpId)
{
var section = mscp.ResolveBaseline(baseline).SelectMany(s => s.Rules)
.FirstOrDefault(r => string.Equals(r.Id, dumpId, StringComparison.OrdinalIgnoreCase));
if (section is null) { Console.WriteLine($"Regle '{dumpId}' absente de la baseline {baseline}."); return 1; }
Console.WriteLine($"Id : {section.Id}");
Console.WriteLine($"Titre : {section.Title}");
Console.WriteLine($"CIS : {section.CisBenchmark}");
Console.WriteLine($"DISA sev. : {section.DisaSeverity}");
Console.WriteLine($"Attendu : {section.Expected}");
Console.WriteLine($"Check : {section.CheckShell}");
Console.WriteLine($"Fix : {section.FixShell}");
return 0;
}
// Collecteurs natifs (equivalent BuildCollectors() cote Windows).
var collectors = new List<IMacCollector>
{
new FileVaultCollector(),
new GatekeeperCollector(),
new SipCollector(),
new FirewallCollector(),
new XProtectCollector(),
new SharingCollector(),
new SoftwareUpdateCollector(),
};
// Collecteurs pilotes par la baseline mSCP (un par section).
var sections = mscp.ResolveBaseline(baseline);
foreach (var section in sections)
collectors.Add(new MscpSectionCollector(section, baseline));
var mscpRuleCount = sections.Sum(s => s.Rules.Count);
if (!quiet)
{
Console.WriteLine("MacSecCheck β auditeur de securite macOS v0.2.0");
Console.WriteLine(new string('=', 48));
Console.WriteLine($"Baseline mSCP : {baseline} (macOS {macMajor}) β " +
$"{mscpRuleCount} regles sur {sections.Count} sections, {mscp.RuleCount} regles indexees.");
if (mscpRuleCount == 0)
Console.WriteLine($"β Baseline '{baseline}' inconnue. Essayez --list-baselines.");
if (!ProcessRunner.IsMacOs)
Console.WriteLine("β Hote non-macOS : collecteurs compiles mais non evalues (NotApplicable).");
Console.WriteLine();
}
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
var engine = new ScanEngine(collectors);
var result = await engine.RunAsync(cts.Token);
if (!quiet)
PrintReport(result);
// Ecriture du rapport JSON.
var json = JsonReportBuilder.Build(result);
var outPath = jsonPath ?? DefaultOutputPath();
await File.WriteAllTextAsync(outPath, json, cts.Token);
Console.WriteLine($"\nπ Rapport JSON : {outPath}");
return result.GlobalScore < 40 ? 2 : 0; // code retour exploitable en CI
// βββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
static string? GetOption(string[] args, string name)
{
var i = Array.IndexOf(args, name);
return i >= 0 && i + 1 < args.Length ? args[i + 1] : null;
}
static string DefaultOutputPath()
{
var stamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
var file = $"MacSecCheck_{Environment.MachineName}_{stamp}.json";
var desktop = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Desktop");
var dir = Directory.Exists(desktop) ? desktop : Directory.GetCurrentDirectory();
return Path.Combine(dir, file);
}
static void PrintReport(ScanResult r)
{
Console.WriteLine($"\nHote : {r.HostName} ({r.OsVersion})");
Console.WriteLine($"Elevation: {(r.Elevated ? "root" : "utilisateur standard")}");
Console.WriteLine($"Score : {r.GlobalScore}/100\n");
foreach (var report in r.Reports.OrderBy(x => x.Category))
{
Console.WriteLine($"ββ {report.Category} / {report.Collector} " +
$"({report.DurationMs:F0} ms)");
foreach (var f in report.Findings)
Console.WriteLine($" {Icon(f.Severity)} [{f.Severity,-11}] {f.Title} : {f.Observed}");
}
}
static string Icon(Severity s) => s switch
{
Severity.Ok => "β",
Severity.Critical => "β",
Severity.High => "β",
Severity.Medium => "β²",
Severity.Low => "β’",
Severity.Error => "!",
Severity.NotApplicable => "β",
_ => "βΉ"
};