Add fileserver context and map controls
All checks were successful
OfficeCom Sentinel Client / validate-client (push) Successful in 23s
OfficeCom Sentinel Client / build-client-windows (push) Successful in 49s

This commit is contained in:
OfficeCom Codex
2026-07-31 00:39:36 +02:00
parent 0207d84775
commit b97f8819f6
8 changed files with 129 additions and 26 deletions

View File

@@ -34,6 +34,8 @@ internal sealed record ScannerConfiguration
public int RansomwareCriticalSignalCount { get; init; } = 3;
public bool RansomwareCaptureSmbSessions { get; init; } = true;
public List<string> RansomwareExcludedProcesses { get; init; } = [];
public List<string> FtpRoots { get; init; } = [];

View File

@@ -126,6 +126,19 @@ internal sealed record RansomwareBetaSummary
public int LookbackMinutes { get; init; }
public List<RansomwareSignal> Signals { get; init; } = [];
public List<RansomwareSmbSession> SmbSessions { get; init; } = [];
}
internal sealed record RansomwareSmbSession
{
public string ClientComputerName { get; init; } = string.Empty;
public string ClientUserName { get; init; } = string.Empty;
public long SessionId { get; init; }
public long OpenFileCount { get; init; }
}
internal sealed record RansomwareSignal

View File

@@ -1,5 +1,7 @@
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Runtime.Versioning;
using System.Text.Json;
namespace OCSentinelCli;
@@ -42,13 +44,17 @@ internal static class RansomwareBetaDetector
_ => $"Ransomware beta found no suspicious process activity in the last {lookbackMinutes} minutes."
};
List<RansomwareSmbSession> smbSessions = state is "warning" or "critical" && configuration.RansomwareCaptureSmbSessions
? CaptureSmbSessions(errors)
: [];
return new RansomwareBetaSummary
{
Enabled = true,
State = state,
Reason = reason,
LookbackMinutes = lookbackMinutes,
Signals = distinctSignals
Signals = distinctSignals,
SmbSessions = smbSessions
};
}
@@ -169,4 +175,49 @@ internal static class RansomwareBetaDetector
return string.Empty;
}
}
private static List<RansomwareSmbSession> CaptureSmbSessions(List<string> errors)
{
try
{
using var process = Process.Start(new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = "-NoProfile -NonInteractive -Command \"Get-SmbSession | Select-Object ClientComputerName,ClientUserName,SessionId,NumOpens | ConvertTo-Json -Compress\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
});
if (process is null || !process.WaitForExit(5000) || process.ExitCode != 0)
{
return [];
}
string json = process.StandardOutput.ReadToEnd();
if (string.IsNullOrWhiteSpace(json))
{
return [];
}
JsonElement root = JsonSerializer.Deserialize<JsonElement>(json, JsonOptions.Default);
IEnumerable<JsonElement> rows = root.ValueKind == JsonValueKind.Array ? root.EnumerateArray().ToArray() : [root];
return rows.Take(100).Select(row => new RansomwareSmbSession
{
ClientComputerName = GetJsonString(row, "ClientComputerName"),
ClientUserName = GetJsonString(row, "ClientUserName"),
SessionId = GetJsonLong(row, "SessionId"),
OpenFileCount = GetJsonLong(row, "NumOpens")
}).ToList();
}
catch (Exception exception)
{
errors.Add($"Ransomware beta SMB snapshot failed: {exception.Message}");
return [];
}
}
private static string GetJsonString(JsonElement value, string name) => value.TryGetProperty(name, out JsonElement property) ? property.ToString() : string.Empty;
private static long GetJsonLong(JsonElement value, string name) => value.TryGetProperty(name, out JsonElement property) && property.TryGetInt64(out long result) ? result : 0;
}