private static void SetCommonCveValueToWorkRow(DataRow workRow, SecurityGuidance sg) { workRow[Constants.SummaryTableColumn.CveTitle] = sg.CveTitle; workRow[Constants.SummaryTableColumn.Description] = sg.Description .Replace("<p>", "") .Replace("</p>", Environment.NewLine); workRow[Constants.SummaryTableColumn.PubliclyDisclosed] = sg.PubliclyDisclosed; // 悪用ありの場合は攻撃しやすさ列へ(+)として設定 workRow[Constants.SummaryTableColumn.Exploited] = sg.Exploited; if (sg.Exploited == "あり") { workRow[Constants.SummaryTableColumn.EaseOfAttack] += "(+)悪用あり" + Environment.NewLine; } // 最新及び過去のソフトウェアリリース情報を作成して格納する var LatestRelease = CreateStringOfReleaseValueForTable(sg.ExploitabilityAssessment.LatestReleaseExploitability); var OlderRelease = CreateStringOfReleaseValueForTable(sg.ExploitabilityAssessment.OlderReleaseExploitability); workRow[Constants.SummaryTableColumn.LatestReleaseExploitability] = LatestRelease; workRow[Constants.SummaryTableColumn.OlderReleaseExploitability] = OlderRelease; // サービス拒否を日本語表記へ変換する。APIの表記は以下の通り。 // 対象外:<DenialOfServiceExploitability i:nil="true"/> // 永続的:<DenialOfServiceExploitability>永続的</DenialOfServiceExploitability> workRow[Constants.SummaryTableColumn.DenialOfService] = String.IsNullOrEmpty((string)sg.ExploitabilityAssessment.DenialOfServiceExploitability) ? "対象外" : sg.ExploitabilityAssessment.DenialOfServiceExploitability; }
public static void Main(string[] args) { //Application.Run(new CveSummaryGeneratorForm()); // まとめ作成対象CVE一覧を取得 var targetCVEs = GetTargetCVEs(); // まとめ対象CVEを分割してリスト化 string[] targetCVElist = targetCVEs.Split(' '); // 対象製品リストを取得 var targetProducts = GetTargetProducts(); // メモリ上のデータベースを作成 DataSet dataSet = new DataSet(); // まとめデータを扱うテーブルを作成 DataTable summaryTable = new DataTable("SummaryTable"); // まとめテーブルにカラム名の追加 SetColumnsToSummaryTable(targetProducts, summaryTable); // DBにまとめテーブルを追加 dataSet.Tables.Add(summaryTable); // 影響対象製品のデータを扱うテーブルを作成 DataTable affectedTargetProductsTable = new DataTable("AffectedTargetProducts"); // 影響対象製品のデータを扱うテーブルにカラム名を設定 SetColumnsToAffectedTargetProductsTable(affectedTargetProductsTable); foreach (var cve in targetCVElist) { // サーバアクセスの間隔を1秒以上空けるようにする Thread.Sleep(1000); // CVEに対応する行を作成 DataRow workRow = summaryTable.NewRow(); // CVENumberを格納 workRow[Constants.SummaryTableColumn.CveNumber] = cve; Console.WriteLine(cve); // 正規表現とマッチするかチェックする if (!Regex.IsMatch(cve, @"^(CVE-20[0-9][0-9]-\d{4}$|^ADV\d{6}$)")) { workRow[Constants.SummaryTableColumn.Remarks] = "CVEの正規表現と一致しません"; summaryTable.Rows.Add(workRow); continue; } //json形式CVE情報を取得する var JsonCveInfo = GetJsonCveInfo(cve); if (String.IsNullOrEmpty(JsonCveInfo)) { // TODO:エラーをそのまま出力できるようにメソッドを変更する workRow[Constants.SummaryTableColumn.Remarks] = "404 Not Found"; summaryTable.Rows.Add(workRow); continue; } // supply settings to JsonConvert.DeserializeObject to handle null values var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore }; // JSONを.NETのクラスにデシリアライズ SecurityGuidance sg = JsonConvert.DeserializeObject <SecurityGuidance>(JsonCveInfo, settings); // 共通項目のデータを格納する SetCommonCveValueToWorkRow(workRow, sg); // 対象とする製品のデータを抽出する var affectedTargetProducts = sg.AffectedProducts.Where(n => n.Name == Constants.ProductName.Win_2012_R2_SeverCore || n.Name == Constants.ProductName.Win_2012_R2 || n.Name == Constants.ProductName.Win_2016_ServerCore || n.Name == Constants.ProductName.Win_2016 || n.Name.Contains(Constants.ProductName.MS_NET_Framework_4_x) || n.Name.Contains(Constants.ProductName.MS_SQL_Server_2014_x) || n.Name == Constants.ProductName.IE_11 ); // targetProductsの有無を判別し、なければ処理終了 if (!affectedTargetProducts.Any()) { workRow[Constants.SummaryTableColumn.Remarks] = "CVEの対象製品の中に目的の製品が含まれていません"; summaryTable.Rows.Add(workRow); continue; } // まとめデータ格納用クラスの初期化 AffectedProduct summaryOfTargetProducts = new AffectedProduct(); // ループに用いる変数を初期化 bool isFirst = true; // 対象製品を有無を表すハッシュテーブルを作成する Hashtable TableRepresentingPresenceOfTargetProduct = CreateTableRepresentingPresenceOfTargetProduct(targetProducts); // 対象製品データのうち値が同じ項目は一つにまとめる foreach (var affectedTargetProduct in affectedTargetProducts) { // Tableに新しい行を作成してaffectedTargetProduct情報をセット SetAffectedTargetProductsRow(affectedTargetProductsTable, affectedTargetProduct, cve); // CVEの影響対象製品と一致する目的製品を確認する CheckIfContainToProductName(affectedTargetProduct.Name, TableRepresentingPresenceOfTargetProduct); if (isFirst) { // 1番目のデータは丸ごと代入する summaryOfTargetProducts = affectedTargetProduct; isFirst = false; continue; } else { // 2番目以降のデータは1番目と一致するか確認する CheckIfEqualToAssignedData(summaryOfTargetProducts, affectedTargetProduct); } } // ループで作成した対象製品データのまとめを格納する SetSummaryOfTargetProductsToWorkRow(workRow, summaryOfTargetProducts, TableRepresentingPresenceOfTargetProduct); // CVSSからCVEの攻撃のしやすさを判別する CheckEaseOfAttack(workRow); // Rows.Addメソッドを使ってデータを追加 summaryTable.Rows.Add(workRow); } // TODO:CVEの脅威レベル(自作)で優先度順に並べられるようにする // CSVファイル保存先の完全パスを取得 string csvPath = GetFullPathWithCurrentDirectoryAndCurrentTimeAsCSVFileName(); Console.WriteLine(csvPath); // CSVコンバーターを呼び出す DatatableToCSVConverter csv = new DatatableToCSVConverter(); // DistinctなダウンロードURLを取得する // TODO:ADV系の記事を集計から除去する or ADV系であることがわかるようにする DataTable distinctUrlForEachName = affectedTargetProductsTable.DefaultView.ToTable(true, "Name", "ArticleUrl1", "DownloadTitle1", "DownloadUrl1", "ArticleUrl2", "DownloadTitle2", "DownloadUrl2", "ArticleUrl3", "DownloadTitle3", "DownloadUrl3", "ArticleUrl4", "DownloadTitle4", "DownloadUrl4"); // DataTableをCSVで保存する csv.ConvertDataTableToCsv(summaryTable, csvPath, true); csv.ConvertDataTableToCsv(affectedTargetProductsTable, csvPath + "_affectedTargetProducts.csv", true); csv.ConvertDataTableToCsv(distinctUrlForEachName, csvPath + "_distinctUrlForEachName.csv", true); Console.ReadLine(); }
static void Main(string[] args) { string WIN2008 = "Windows Server 2008 for 32-bit Systems Service Pack 2"; string WIN2012 = "Windows Server 2012 R2 (Server Core installation)"; string WIN2016 = "Windows Server 2016 (Server Core installation)"; var wc = new WebClient(); wc.Encoding = Encoding.UTF8; // TODO:取得するCVE一覧を取得 // TODO:CVE一覧から取得するCVEを一つずつ取得 var cve = "CVE-2018-8308"; // TODO:正規表現で正しいCVEかチェックする // (CVE - 20[0 - 9][0 - 9] -\d{ 4}|ADV\d{ 6}) if (Regex.IsMatch(cve, @"(CVE-20[0-9][0-9]-\d{4}|ADV\d{6})")) { Console.WriteLine("正規表現と一致します"); } else { Console.WriteLine("一致しません"); } // APIからjson形式の文字列を取得 var jsonString = wc.DownloadString(@"https://portal.msrc.microsoft.com/api/security-guidance/ja-JP/CVE/" + cve); // ダウンロードしたjson文字列を出力 Console.WriteLine(jsonString); // JSONを.NETのクラスにデシリアライズ SecurityGuidance sg = JsonConvert.DeserializeObject <SecurityGuidance>(jsonString); // まとめデータを格納するテーブルを作成 DataSet dataSet = new DataSet(); // 表形式のデータをメモリ領域へ格納するクラス DataTable table = new DataTable("SummaryTable"); // 表形式のデータを扱う // カラム名の追加 table.Columns.Add("CVE"); table.Columns.Add("概要"); table.Columns.Add("詳細"); table.Columns.Add("一般に公開"); table.Columns.Add("悪用"); table.Columns.Add("最新のソフトウェア リリース"); table.Columns.Add("過去のソフトウェア リリース"); table.Columns.Add("VectorString"); table.Columns.Add("BaseScore", Type.GetType("System.Double")); table.Columns.Add("TemporalScore", Type.GetType("System.Double")); table.Columns.Add("Severity"); table.Columns.Add(WIN2008); table.Columns.Add(WIN2012); table.Columns.Add(WIN2016); // DataSetにDataTableを追加 dataSet.Tables.Add(table); // TODO:「サービス拒否」の項目はjsonにないのか確認 // 対象とする製品のデータを抽出する var targetProducts = sg.AffectedProducts.Where(n => n.Name == WIN2008 || n.Name == WIN2012 || n.Name == WIN2016); // まとめデータ格納用クラスの初期化 AffectedProduct summaryOfTargetProducts = new AffectedProduct(); // ループに用いる変数を初期化 bool isFirst = true; string containsWIN2008 = "☓"; string containsWIN2012 = "☓"; string containsWIN2016 = "☓"; // 対象製品データのうち値が同じ項目は一つにまとめる foreach (var product in targetProducts) { // CVEの対象製品が以下の製品のどれに該当するかチェックする if (product.Name == WIN2008) { containsWIN2008 = "○"; } if (product.Name == WIN2012) { containsWIN2012 = "○"; } if (product.Name == WIN2016) { containsWIN2016 = "○"; } if (isFirst) { summaryOfTargetProducts = product; isFirst = false; continue; } if (!summaryOfTargetProducts.VectorString.Equals(product.VectorString)) { summaryOfTargetProducts.VectorString = "vectorStringの中に一致しないものがあります"; Console.WriteLine(summaryOfTargetProducts.VectorString); } if (!summaryOfTargetProducts.BaseScore.Equals(product.BaseScore)) { summaryOfTargetProducts.BaseScore = 0; Console.WriteLine("baseScoreの中に一致しないものがあります"); } if (!summaryOfTargetProducts.TemporalScore.Equals(product.TemporalScore)) { summaryOfTargetProducts.TemporalScore = 0; Console.WriteLine("temporalScoreの中に一致しないものがあります"); } if (!summaryOfTargetProducts.Severity.Equals(product.Severity)) { summaryOfTargetProducts.Severity = "severityの中に一致しないものがあります"; Console.WriteLine("severityの中に一致しないものがあります"); } } // tableへのデータ追加用文字列を作成 var LatestReleaseExploitability = sg.ExploitabilityAssessment.LatestReleaseExploitability.Id.ToString() + "-" + sg.ExploitabilityAssessment.LatestReleaseExploitability.Name; // 最新のソフトウェア リリース var OlderReleaseExploitability = sg.ExploitabilityAssessment.OlderReleaseExploitability.Id.ToString() + "-" + sg.ExploitabilityAssessment.OlderReleaseExploitability.Name; // 過去のソフトウェア リリース // Rows.Addメソッドを使ってデータを追加 table.Rows.Add(cve , sg.CveTitle , sg.Description.Replace("\n", "") , sg.PubliclyDisclosed , sg.Exploited , LatestReleaseExploitability , OlderReleaseExploitability , summaryOfTargetProducts.VectorString , summaryOfTargetProducts.BaseScore , summaryOfTargetProducts.TemporalScore , summaryOfTargetProducts.Severity , containsWIN2008 , containsWIN2012 , containsWIN2016); Console.WriteLine("tableの中身を表示"); foreach (DataRow Row in table.Rows) { for (int i = 0; i < Row.ItemArray.Length; i++) { Console.WriteLine(Row[i].ToString() + "|"); } } // CSVコンバーターを呼び出す DatatableToCSVConverter csv = new DatatableToCSVConverter(); // カレントディレクトリのパスを取得する string CurrentDir = Directory.GetCurrentDirectory(); // ファイル名を現在時刻を「西暦月日時分秒」形式で取得する string now = DateTime.Now.ToString("yyyyMMddHHmmss"); // 保存先のCSVファイルのパス string csvPath = CurrentDir + "/" + now + ".csv"; // DataTableをCSVで保存する csv.ConvertDataTableToCsv(table, csvPath, true); Console.ReadLine(); }