public IEnumerable <(IcsMitreTechnique, IcsMitreTactic, string, string, string)> ParsePEEvent(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { if (!noticeLine.Value.Any()) { return(null); } var ftpLine = noticeLine.Value.Where(line => line is FtpDataLine).FirstOrDefault(); if (!(ftpLine is FtpDataLine ftpDataLine)) { return(null); } var results = new List <(IcsMitreTechnique, IcsMitreTactic, string, string, string)>(); // Checks for the use of default FTP credentials (user: Anonymous, password: anonymous) if (string.Equals(ftpDataLine.User, "Anonymous") && string.Equals(ftpDataLine.Password, "anonymous")) { if (decimal.TryParse(ftpLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var ftpResult)) { var timeString = TimeConverter.UnixTimeToString(ftpResult); results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DefaultCredentials, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeResult)) { var timeString = TimeConverter.UnixTimeToString(noticeResult); results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DefaultCredentials, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DefaultCredentials, IcsMitreTactic.LateralMovement, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } } else { if (decimal.TryParse(ftpLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var ftpResult)) { var timeString = TimeConverter.UnixTimeToString(ftpResult); results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeResult)) { var timeString = TimeConverter.UnixTimeToString(noticeResult); results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, timeString, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PersistenceModuleFirmware, IcsMitreTactic.Persistence, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlModuleFirmware, IcsMitreTactic.ImpairProcessControl, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.PersistenceSystemFirmware, IcsMitreTactic.Persistence, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionSystemFirmware, IcsMitreTactic.InhibitResponseFunction, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, string.Empty, ftpDataLine.OriginAddress, ftpDataLine.ResponderAddress)); } } return(results.Any() ? results : null); }
private (IcsMitreTechnique, IcsMitreTactic, string, string, string)? ConstructTechnique(ConnDataLine connDataLine, NoticeDataLine key) { if (decimal.TryParse(connDataLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var dnsResult)) { return(IcsMitreTechnique.CommonlyUsedPort, IcsMitreTactic.CommandAndControl, TimeConverter.UnixTimeToString(dnsResult), connDataLine.OriginAddress, connDataLine.ResponderAddress); } if (decimal.TryParse(key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeResult)) { return(IcsMitreTechnique.CommonlyUsedPort, IcsMitreTactic.CommandAndControl, TimeConverter.UnixTimeToString(noticeResult), connDataLine.OriginAddress, connDataLine.ResponderAddress); } return(IcsMitreTechnique.CommonlyUsedPort, IcsMitreTactic.CommandAndControl, string.Empty, connDataLine.OriginAddress, connDataLine.ResponderAddress); }
public static (IcsMitreTechnique, IcsMitreTactic, string, string, string) ParsePortScanSummary(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { var firstNoticeLineValue = noticeLine.Value.FirstOrDefault(); var noticeLineKey = noticeLine.Key; var match = Regex.Match(noticeLineKey.Message, "(.*) scanned"); var originAddress = match.Groups[1].Value; // Any detected TCP scan by Zeek is an anomaly, so should always be mapped to a technique. // The network service scanning technique is not returned with a destination address, // as obviously, there are multiple destinations for a network service scan. if (firstNoticeLineValue != null && decimal.TryParse(firstNoticeLineValue.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { return(IcsMitreTechnique.NetworkServiceScanning, IcsMitreTactic.Discovery, TimeConverter.UnixTimeToString(result), originAddress, string.Empty); } else if (decimal.TryParse(noticeLineKey.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var keyResult)) { return(IcsMitreTechnique.NetworkServiceScanning, IcsMitreTactic.Discovery, TimeConverter.UnixTimeToString(keyResult), originAddress, string.Empty); } return(IcsMitreTechnique.NetworkServiceScanning, IcsMitreTactic.Discovery, string.Empty, originAddress, string.Empty); }
public IEnumerable <(IcsMitreTechnique, IcsMitreTactic, string, string, string)> ParseS7CommEvent(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { if (!noticeLine.Value.Any()) { return(null); } var s7CommLine = noticeLine.Value.Where(line => line is S7CommDataLine).FirstOrDefault(); if (!(s7CommLine is S7CommDataLine s7CommDataLine)) { return(null); } string actionType = null; foreach (var parameter in s7CommDataLine.Parameter) { // Loops over all the parameters in the S7Comm data, grabbing // either the type parameter or the sub parameter. Both represent // an S7Comm action, with the type parameter being a main action // and the sub parameter being a secondary (CPU) action. If either is found, // the loop is stopped. var typeMatch = Regex.Match(parameter, @"type=(.+)"); var subMatch = Regex.Match(parameter, @"sub=(.+)"); if (typeMatch.Success) { actionType = typeMatch.Groups[1].Value; break; } else if (subMatch.Success) { actionType = subMatch.Groups[1].Value; break; } } var results = new List <(IcsMitreTechnique, IcsMitreTactic, string, string, string)>(); // Matches the S7Comm action to the corresponding techniques, based on the ICS MITRE framework switch (actionType) { case "Read Variable": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommReadResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommReadResult); results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeReadResult)) { var timeString = TimeConverter.UnixTimeToString(noticeReadResult); results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "PI Service": case "PLC Control": case "PLC Stop": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommChangeModeResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommChangeModeResult); results.Add((IcsMitreTechnique.EvasionUtilizeOrChangeOperatingMode, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionUtilizeOrChangeOperatingMode, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeChangeModeResult)) { var timeString = TimeConverter.UnixTimeToString(noticeChangeModeResult); results.Add((IcsMitreTechnique.EvasionUtilizeOrChangeOperatingMode, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionUtilizeOrChangeOperatingMode, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.EvasionUtilizeOrChangeOperatingMode, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionUtilizeOrChangeOperatingMode, IcsMitreTactic.ImpairProcessControl, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "Write Variable": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommWriteResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommWriteResult); results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeWriteResult)) { var timeString = TimeConverter.UnixTimeToString(noticeWriteResult); results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "Request Download": case "Download Block": case "Download Ended": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommDownloadResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommDownloadResult); results.Add((IcsMitreTechnique.PersistenceProgramDownload, IcsMitreTactic.Persistence, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionProgramDownload, IcsMitreTactic.InhibitResponseFunction, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlProgramDownload, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeDownloadResult)) { var timeString = TimeConverter.UnixTimeToString(noticeDownloadResult); results.Add((IcsMitreTechnique.PersistenceProgramDownload, IcsMitreTactic.Persistence, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionProgramDownload, IcsMitreTactic.InhibitResponseFunction, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlProgramDownload, IcsMitreTactic.ImpairProcessControl, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PersistenceProgramDownload, IcsMitreTactic.Persistence, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.InhibitResponseFunctionProgramDownload, IcsMitreTactic.InhibitResponseFunction, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlProgramDownload, IcsMitreTactic.ImpairProcessControl, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "Start Upload": case "Upload": case "End Upload": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommUploadResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommUploadResult); results.Add((IcsMitreTechnique.ProgramUpload, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeUploadResult)) { var timeString = TimeConverter.UnixTimeToString(noticeUploadResult); results.Add((IcsMitreTechnique.ProgramUpload, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.ProgramUpload, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "Read SZL": { if (decimal.TryParse(s7CommLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var s7CommReadSZLResult)) { var timeString = TimeConverter.UnixTimeToString(s7CommReadSZLResult); results.Add((IcsMitreTechnique.DetectOperatingMode, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeReadSZLResult)) { var timeString = TimeConverter.UnixTimeToString(noticeReadSZLResult); results.Add((IcsMitreTechnique.DetectOperatingMode, IcsMitreTactic.Collection, timeString, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.DetectOperatingMode, IcsMitreTactic.Collection, string.Empty, s7CommDataLine.OriginAddress, s7CommDataLine.ResponderAddress)); } break; } case "CPU Services": case "Setup Communication": default: break; } return(results.Any() ? results : null); }
public IEnumerable <(IcsMitreTechnique, IcsMitreTactic, string, string, string)> ParseHttpEvent(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine, IEnumerable <DataLine> filesDataLines) { if (!noticeLine.Value.Any()) { return(null); } var httpLine = noticeLine.Value.Where(line => line is HttpDataLine).FirstOrDefault(); if (!(httpLine is HttpDataLine httpDataLine)) { return(null); } if (string.IsNullOrEmpty(httpDataLine.HttpPostBody)) { return(null); } using (var ms = GenerateStreamFromString(httpDataLine.HttpPostBody)) { // Reads the POST body into an XDocument to parse, grabbing the <action> element var body = XDocument.Load(ms); var actionTag = body.Descendants(). Where(element => element.Name.LocalName.Equals("action")). FirstOrDefault(); if (actionTag == null) { return(null); } var results = new List <(IcsMitreTechnique, IcsMitreTactic, string, string, string)>(); // Matches the value of the action to its corresponding ICS MITRE techniques. // Proprietary protocol with (little to) no documentation, so only observed values // are added to this switch switch (actionTag.Value) { case "Read": { if (decimal.TryParse(httpLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var microBrowserReadResult)) { var timeString = TimeConverter.UnixTimeToString(microBrowserReadResult); results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeReadResult)) { var timeString = TimeConverter.UnixTimeToString(noticeReadResult); results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, timeString, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, string.Empty, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.DetectProgramState, IcsMitreTactic.Collection, string.Empty, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); results.Add((IcsMitreTechnique.RoleIdentification, IcsMitreTactic.Collection, string.Empty, httpDataLine.OriginAddress, httpDataLine.ResponderAddress)); } break; } default: break; } return(results.Any() ? results : null); } }
public IEnumerable <(IcsMitreTechnique, IcsMitreTactic, string, string, string)> ParseModbusEvent(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { if (!noticeLine.Value.Any()) { return(null); } var modbusLines = noticeLine.Value.Where(line => line is ModbusDataLine); if (!modbusLines.Any()) { return(null); } var modbusLine = modbusLines.FirstOrDefault() as ModbusDataLine; var results = new List <(IcsMitreTechnique, IcsMitreTactic, string, string, string)>(); // Constants taken from https://docs.zeek.org/en/current/scripts/base/protocols/modbus/consts.zeek.html // Matches the Modbus function to its corresponding ICS MITRE techniques switch (modbusLine.Function) { case "READ_DISCRETE_INPUTS": case "READ_COILS": case "READ_INPUT_REGISTERS": case "READ_HOLDING_REGISTERS": case "READ_FIFO_QUEUE": case "READ_FILE_RECORD": { if (decimal.TryParse(modbusLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var modbusReadResult)) { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, TimeConverter.UnixTimeToString(modbusReadResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeReadResult)) { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, TimeConverter.UnixTimeToString(noticeReadResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); } break; } case "WRITE_SINGLE_COIL": case "WRITE_MULTIPLE_COILS": case "WRITE_SINGLE_REGISTER": case "WRITE_MULTIPLE_REGISTERS": case "MASK_WRITE_REGISTER": case "WRITE_FILE_RECORD": { if (decimal.TryParse(modbusLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var modbusWriteResult)) { results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, TimeConverter.UnixTimeToString(modbusWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, TimeConverter.UnixTimeToString(modbusWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeWriteResult)) { results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, TimeConverter.UnixTimeToString(noticeWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, TimeConverter.UnixTimeToString(noticeWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); } break; } case "READ_WRITE_MULTIPLE_REGISTERS": { if (decimal.TryParse(modbusLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var modbusReadWriteResult)) { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, TimeConverter.UnixTimeToString(modbusReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, TimeConverter.UnixTimeToString(modbusReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, TimeConverter.UnixTimeToString(modbusReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeReadWriteResult)) { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, TimeConverter.UnixTimeToString(noticeReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, TimeConverter.UnixTimeToString(noticeReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, TimeConverter.UnixTimeToString(noticeReadWriteResult), modbusLine.OriginAddress, modbusLine.ResponderAddress)); } else { results.Add((IcsMitreTechnique.PointAndTagIdentification, IcsMitreTactic.Collection, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ExecutionChangeProgramState, IcsMitreTactic.Execution, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); results.Add((IcsMitreTechnique.ImpairProcessControlChangeProgramState, IcsMitreTactic.ImpairProcessControl, string.Empty, modbusLine.OriginAddress, modbusLine.ResponderAddress)); } break; } default: break; } return(results.Any() ? results : null); }
public (IcsMitreTechnique, IcsMitreTactic, string, string, string)? ParseDnsTunnel(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { if (!noticeLine.Value.Any()) { return(null); } var dnsLine = noticeLine.Value.Where(line => line is DnsDataLine).FirstOrDefault(); if (!(dnsLine is DnsDataLine dnsDataLine)) { return(null); } // Calculates the Shannon entropy over the DNS query. If // the entropy is higher than 4, it gets marked as an anomaly. // This is on the higher end of normal (english) text. var query = dnsDataLine.Query; if (ShannonEntropy(query) > 4.0) { _timeStamps.Add(dnsDataLine.TimeStamp); } if (_timeStamps.Count < 2) { return(null); } if (!(decimal.TryParse(_timeStamps.First(), NumberStyles.Any, CultureInfo.InvariantCulture, out var firstTimeStamp) && decimal.TryParse(_timeStamps.Last(), NumberStyles.Any, CultureInfo.InvariantCulture, out var lastTimeStamp))) { _timeStamps.Clear(); return(null); } // Calculates the difference between the first and the last timestamps // that were marked as anomalies var difference = lastTimeStamp - firstTimeStamp; if (lastTimeStamp - firstTimeStamp > 30) { // If the difference is higher than 30 seconds, the timestamps get cleared _timeStamps.Clear(); return(null); } else if (_timeStamps.Count > 15) { // Otherwise, if at least 16 anomalies have been spotted in 30 seconds, // the decision gets made that this is a DNS tunnel. So that means: // - At least 16 queries // - Length > 52 // - Shannon entropy > 4 // - Within 30 seconds _timeStamps.Clear(); return(IcsMitreTechnique.ConnectionProxy, IcsMitreTactic.CommandAndControl, TimeConverter.UnixTimeToString(firstTimeStamp), dnsDataLine.OriginAddress, dnsDataLine.ResponderAddress); } return(null); }
public (IcsMitreTechnique, IcsMitreTactic, string, string, string)? ParseSmb2Event(KeyValuePair <NoticeDataLine, IEnumerable <DataLine> > noticeLine) { if (!noticeLine.Value.Any()) { return(null); } var smbFileLine = noticeLine.Value.Where(line => line is SmbFilesDataLine).FirstOrDefault(); if (!(smbFileLine is SmbFilesDataLine smbFilesDataLine)) { return(null); } switch (smbFilesDataLine.Action) { case "SMB::PIPE_WRITE": case "SMB::FILE_WRITE": case "SMB::PRINT_WRITE": { if (decimal.TryParse(smbFileLine.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var smbResult)) { return(IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, TimeConverter.UnixTimeToString(smbResult), smbFilesDataLine.OriginAddress, smbFilesDataLine.ResponderAddress); } if (decimal.TryParse(noticeLine.Key.TimeStamp, NumberStyles.Any, CultureInfo.InvariantCulture, out var noticeResult)) { return(IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, TimeConverter.UnixTimeToString(noticeResult), smbFilesDataLine.OriginAddress, smbFilesDataLine.ResponderAddress); } return(IcsMitreTechnique.RemoteFileCopy, IcsMitreTactic.LateralMovement, string.Empty, smbFilesDataLine.OriginAddress, smbFilesDataLine.ResponderAddress); } default: return(null); } }