class Rex::Parser::MbsaDocument
Public Instance Methods
characters(text)
click to toggle source
This breaks xml-encoded characters, so need to append
# File lib/rex/parser/mbsa_nokogiri.rb, line 38 def characters(text) return unless @state[:has_text] @text ||= "" @text << text end
collect_advice_data()
click to toggle source
So far, just care about Host OS There is assuredly more interesting things going on in here.
# File lib/rex/parser/mbsa_nokogiri.rb, line 153 def collect_advice_data return unless in_tag("SecScan") return unless in_tag("Check") collect_os_name @text = nil end
collect_bulletin_title()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 120 def collect_bulletin_title return unless @state[:check_state]["ID"] == 500.to_s return unless in_tag("UpdateData") return unless @state[:update] return if @text.to_s.strip.empty? @state[:update]["Title"] = @text.to_s.strip end
collect_check_data()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 191 def collect_check_data return unless in_tag("SecScan") @state[:check_state] = {} end
collect_detail_data()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 183 def collect_detail_data return unless in_tag("SecScan") return unless in_tag("Check") if @report_data[:missing_updates] @report_data[:vulns] = @report_data[:missing_updates] end end
collect_host_data()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 196 def collect_host_data return unless @state[:address] return if @state[:address].strip.empty? @report_data[:host] = @state[:address].strip if @state[:hostname] && !@state[:hostname].empty? @report_data[:name] = @state[:hostname] end @report_data[:state] = Msf::HostState::Alive end
collect_missing_update()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 136 def collect_missing_update return unless @state[:check_state]["ID"] == 500.to_s return if @state[:update]["IsInstalled"] == "true" @report_data[:missing_updates] ||= [] this_update = {} this_update[:name] = @state[:update]["Title"].to_s.strip this_update[:refs] = [] if @state[:update]["BulletinID"].empty? this_update[:refs] << "URL-#{@state[:update][:url]}" else this_update[:refs] << "MSB-#{@state[:update]["BulletinID"]}" end @report_data[:missing_updates] << this_update end
collect_os_name()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 160 def collect_os_name return unless @state[:check_state]["ID"] == 10101.to_s return unless @text return if @text.strip.empty? os_match = @text.match(/Computer is running (.*)/) return unless os_match os_info = os_match[1] os_vendor = os_info[/Microsoft/] os_family = os_info[/Windows/] os_version = os_info[/(XP|2000 Advanced Server|2000|2003|2008|SBS|Vista|7 .* Edition|7)/] if os_info @report_data[:os_fingerprint] = {} @report_data[:os_fingerprint][:type] = "host.os.mbsa_fingerprint" @report_data[:os_fingerprint][:data] = { :os_vendor => os_vendor, :os_family => os_family, :os_version => os_version, :os_accuracy => 100, :os_match => os_info.gsub(/\x2e$/n,"") } end end
collect_title()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 113 def collect_title return unless in_tag("SecScan") return unless in_tag("Check") collect_bulletin_title @text = nil end
collect_updatedata()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 128 def collect_updatedata return unless in_tag("SecScan") return unless in_tag("Check") return unless in_tag("Detail") collect_missing_update @state[:updates] = {} end
collect_url()
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 88 def collect_url return unless in_tag("References") return unless in_tag("UpdateData") return unless in_tag("Detail") return unless in_tag("Check") @state[:update][:url] = @text.to_s.strip @text = nil end
end_element(name=nil)
click to toggle source
When we exit a tag, this is triggered.
# File lib/rex/parser/mbsa_nokogiri.rb, line 45 def end_element(name=nil) block = @block case name when "SecScan" # Wrap it up collect_host_data host_object = report_host &block if host_object db.report_import_note(@args[:wspace],host_object) report_fingerprint(host_object) report_vulns(host_object,&block) end # Reset the state once we close a host @state.delete_if {|k| k != :current_tag} when "Check" collect_check_data when "Advice" @state[:has_text] = false collect_advice_data when "Detail" collect_detail_data when "UpdateData" collect_updatedata when "Title" @state[:has_text] = false collect_title when "InformationURL" collect_url @state[:has_text] = false end @state[:current_tag].delete name end
host_is_okay()
click to toggle source
We need to override the usual host_is_okay
because MBSA apparently doesn’t report on open ports at all.
# File lib/rex/parser/mbsa_nokogiri.rb, line 241 def host_is_okay return false unless @report_data[:host] return false unless valid_ip(@report_data[:host]) return false unless @report_data[:state] == Msf::HostState::Alive if @args[:blacklist] return false if @args[:blacklist].include?(@report_data[:host]) end return true end
record_check(attrs)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 228 def record_check(attrs) return unless in_tag("SecScan") @state[:check_state] = attr_hash(attrs) end
record_detail(attrs)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 233 def record_detail(attrs) return unless in_tag("SecScan") return unless in_tag("Check") @state[:detail_state] = attr_hash(attrs) end
record_host(attrs)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 222 def record_host(attrs) host_attrs = attr_hash(attrs) @state[:address] = host_attrs["IP"] @state[:hostname] = host_attrs["Machine"] end
record_updatedata(attrs)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 214 def record_updatedata(attrs) return unless in_tag("SecScan") return unless in_tag("Check") return unless in_tag("Detail") update_attrs = attr_hash(attrs) @state[:update] = attr_hash(attrs) end
report_fingerprint(host_object)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 77 def report_fingerprint(host_object) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:os_fingerprint] fp_note = @report_data[:os_fingerprint].merge( { :workspace => host_object.workspace, :host => host_object }) db_report(:note, fp_note) end
report_host(&block)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 206 def report_host(&block) if host_is_okay db.emit(:address,@report_data[:host],&block) if block host_info = @report_data.merge(:workspace => @args[:wspace]) db_report(:host, host_info) end end
report_vulns(host_object, &block)
click to toggle source
# File lib/rex/parser/mbsa_nokogiri.rb, line 97 def report_vulns(host_object, &block) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:vulns] return if @report_data[:vulns].empty? @report_data[:vulns].each do |vuln| next unless vuln[:refs] if vuln[:refs].empty? next end if block db.emit(:vuln, ["Missing #{vuln[:name]}",1], &block) if block end db_report(:vuln, vuln.merge(:host => host_object)) end end
start_element(name=nil,attrs=[])
click to toggle source
Triggered every time a new element is encountered. We keep state ourselves with the @state variable, turning things on when we get here (and turning things off when we exit in end_element
()).
# File lib/rex/parser/mbsa_nokogiri.rb, line 14 def start_element(name=nil,attrs=[]) attrs = normalize_attrs(attrs) block = @block @state[:current_tag][name] = true case name when "SecScan" record_host(attrs) when "IP" # TODO: Check to see if IPList/IP is useful to import when "Check" # A list of MBSA checks. They have an ID and a Name. record_check(attrs) when "Advice" # Check advice. Free form text about the check @state[:has_text] = true when "Detail" # Check/Detail is where missing fixes are. record_detail(attrs) when "UpdateData" # Info about installed/missing hotfixes record_updatedata(attrs) when "Title" # MSB Title @state[:has_text] = true when "InformationURL" # Only use this if we don't have a Bulletin ID @state[:has_text] = true end end