Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
            }
        }