# frozen_string_literal: true # This will check microsoft security portal for the kbs assosicated with an operating system for a given CVE. # # end goal usage: --cve CVE-2020-1234 --os "Windows Server 2012 R2" # require 'json' require 'rest-client' require 'pry' class MicrosoftKbChecker attr_accessor :options # options hash {:cve_id => 'cve-2020-1234', :os_name => 'Windows Server 2012'} def initialize(options) @options = options end AVAILABLE_OS = [ 'Windows 10 Version 2004 for 32-bit Systems', 'Windows 10 Version 2004 for ARM64-based Systems', 'Windows 10 Version 2004 for x64-based Systems', 'Windows Server, version 2004 (Server Core installation)', 'Windows 10 Version 1803 for 32-bit Systems', 'Windows 10 Version 1803 for x64-based Systems', 'Windows 10 Version 1803 for ARM64-based Systems', 'Windows 10 Version 1809 for 32-bit Systems', 'Windows 10 Version 1809 for x64-based Systems', 'Windows 10 Version 1809 for ARM64-based Systems', 'Windows Server 2019', 'Windows Server 2019 (Server Core installation)', 'Windows 10 Version 1909 for 32-bit Systems', 'Windows 10 Version 1909 for x64-based Systems', 'Windows 10 Version 1909 for ARM64-based Systems', 'Windows Server, version 1909 (Server Core installation)', 'Windows 10 Version 1709 for 32-bit Systems', 'Windows 10 Version 1709 for x64-based Systems', 'Windows 10 Version 1709 for ARM64-based Systems', 'Windows 10 Version 1903 for 32-bit Systems', 'Windows 10 Version 1903 for x64-based Systems', 'Windows 10 Version 1903 for ARM64-based Systems', 'Windows Server, version 1903 (Server Core installation)', 'Windows 10 for 32-bit Systems', 'Windows 10 for x64-based Systems', 'Windows 10 Version 1607 for 32-bit Systems', 'Windows 10 Version 1607 for x64-based Systems', 'Windows Server 2016', 'Windows Server 2016 (Server Core installation)', 'Windows 7 for 32-bit Systems Service Pack 1', 'Windows 7 for x64-based Systems Service Pack 1', 'Windows 8.1 for 32-bit systems', 'Windows 8.1 for x64-based systems', 'Windows RT 8.1', 'Windows Server 2008 for 32-bit Systems Service Pack 2', 'Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)', 'Windows Server 2008 for x64-based Systems Service Pack 2', 'Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)', 'Windows Server 2008 R2 for x64-based Systems Service Pack 1', 'Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)', 'Windows Server 2012', 'Windows Server 2012 (Server Core installation)', 'Windows Server 2012 R2', 'Windows Server 2012 R2 (Server Core installation)' ].freeze def cve_url cve = options[:cve_id] "https://portal.msrc.microsoft.com/api/security-guidance/en-US/CVE/#{cve}" end def make_request RestClient::Request.execute( method: :get, headers: { Host: 'portal.msrc.microsoft.com' }, url: cve_url ) end def parse_json(response) JSON.parse(response) end def os_available? AVAILABLE_OS.include?(options[:os_name]) end def query_cve if os_available? response = make_request json = parse_json(response) os_results = select_os(json) kbs_for_os(os_results) if os_results else 'Operating system not found.' end end def select_os(json) json.dig('affectedProducts').select do |os| os['name'] == options[:os_name] end.first end def kbs_for_os(os_json) supersedence = os_json.values_at('supersedence') articles = article_title_keys(os_json) kbs = articles.map do |article_info| num = article_info[:article_num] os_json.values_at("articleTitle#{num}") end { os_name: os_json['name'], kbs: kbs, supersedence_kb: supersedence } end def article_title_keys(json) # let us know if we have a kb article in our json response data # the json response is made up of 4 articleTitle keys # i have this looping through 99 in case there are more articles from the ones ive manually looked at results = (1..99).map { |index| { article_num: index, has_key?: json.key?("articleTitle#{index}") } } results.select { |r| r if r[:has_key?] == true } end end