Add a nokogiri xml stream parser for Burp issue xml and rename original burp parser to burp session parser so both are supported.

bug/bundler_fix
Brian Patterson 2016-02-01 16:11:06 -06:00
parent 1828b7fda6
commit 4dcbd7c1ae
No known key found for this signature in database
GPG Key ID: 79C4E4506D8A9C42
8 changed files with 175 additions and 4 deletions

View File

@ -16,7 +16,8 @@ module Msf::DBManager::Import
autoload :Acunetix, 'msf/core/db_manager/import/acunetix'
autoload :Amap, 'msf/core/db_manager/import/amap'
autoload :Appscan, 'msf/core/db_manager/import/appscan'
autoload :Burp, 'msf/core/db_manager/import/burp'
autoload :BurpIssue, 'msf/core/db_manager/import/burp_issue'
autoload :BurpSession, 'msf/core/db_manager/import/burp_session'
autoload :CI, 'msf/core/db_manager/import/ci'
autoload :Foundstone, 'msf/core/db_manager/import/foundstone'
autoload :FusionVM, 'msf/core/db_manager/import/fusion_vm'
@ -41,7 +42,8 @@ module Msf::DBManager::Import
include Msf::DBManager::Import::Acunetix
include Msf::DBManager::Import::Amap
include Msf::DBManager::Import::Appscan
include Msf::DBManager::Import::Burp
include Msf::DBManager::Import::BurpIssue
include Msf::DBManager::Import::BurpSession
include Msf::DBManager::Import::CI
include Msf::DBManager::Import::Foundstone
include Msf::DBManager::Import::FusionVM
@ -267,6 +269,9 @@ module Msf::DBManager::Import
elsif (data[0,1024] =~ /<!ATTLIST\s+items\s+burpVersion/)
@import_filedata[:type] = "Burp Session XML"
return :burp_session_xml
elsif (data[0,1024] =~ /<!ATTLIST\s+issues\s+burpVersion/)
@import_filedata[:type] = "Burp Issue XML"
return :burp_issue_xml
elsif (firstline.index("<?xml"))
# it's xml, check for root tags we can handle
line_count = 0

View File

@ -0,0 +1,20 @@
require 'rex/parser/burp_issue_nokogiri'
module Msf::DBManager::Import::BurpIssue
def import_burp_issue_xml(args={}, &block)
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
wspace = args[:wspace] || workspace
parser = "Nokogiri v#{::Nokogiri::VERSION}"
noko_args = args.dup
noko_args[:blacklist] = bl
noko_args[:wspace] = wspace
if block
yield(:parser, parser)
doc = Rex::Parser::BurpIssueDocument.new(args,framework.db) {|type, data| yield type,data }
else
doc = Rex::Parser::BurpIssueDocument.new(args,self)
end
parser = ::Nokogiri::XML::SAX::Parser.new(doc)
parser.parse(args[:data])
end
end

View File

@ -1,6 +1,6 @@
require 'rex/parser/burp_session_nokogiri'
module Msf::DBManager::Import::Burp
module Msf::DBManager::Import::BurpSession
def import_burp_session_noko_stream(args={},&block)
if block
doc = Rex::Parser::BurpSessionDocument.new(args,framework.db) {|type, data| yield type,data }

View File

@ -1647,6 +1647,7 @@ class Db
print_line " Amap Log -m"
print_line " Appscan"
print_line " Burp Session XML"
print_line " Burp Issue XML"
print_line " CI"
print_line " Foundstone"
print_line " FusionVM XML"

View File

@ -0,0 +1,139 @@
# -*- coding: binary -*-
require "rex/parser/nokogiri_doc_mixin"
require 'uri'
module Rex
module Parser
# If Nokogiri is available, define Burp Issue document class.
load_nokogiri && class BurpIssueDocument < Nokogiri::XML::SAX::Document
include NokogiriDocMixin
def start_element(name=nil,attrs=[])
attrs = normalize_attrs(attrs)
block = @block
@state[:current_tag][name] = true
case name
when "host", "name", "info", "issueDetail", "references"
@state[:has_text] = true
end
end
def end_element(name=nil)
block = @block
case name
when "issue"
report_web_host_info
report_web_service_info
report_vuln
# Reset the state once we close a host
@state = @state.select {|k| [:current_tag].include? k}
when "host"
@state[:has_text] = false
collect_host_info
@text = nil
when "name"
@state[:has_text] = false
collect_name
@text = nil
when "issueDetail"
@state[:has_text] = false
collect_issue_detail
@text = nil
when "references"
@state[:has_text] = false
collect_references
@text = nil
end
@state[:current_tag].delete name
end
def collect_host_info
return unless in_issue
return unless has_text
uri = URI(@text)
@state[:host] = uri.host
@state[:service_name] = uri.scheme
@state[:proto] = "tcp"
case @state[:service_name]
when "http"
@state[:port] = 80
when "https"
@state[:port] = 443
end
end
def collect_name
return unless in_issue
return unless has_text
@state[:vuln_name] = @text
end
def collect_issue_detail
return unless in_issue
return unless has_text
@state[:issue_detail] = @text
end
def collect_references
return unless in_issue
return unless has_text
uri = @text.match('href=[\'"]?([^\'" >]+)')[1]
@state[:refs] = ["URI-#{uri}"]
end
def report_web_host_info
return unless @state[:host]
address = Rex::Socket.resolv_to_dotted(@state[:host]) rescue nil
host_info = {:workspace => @args[:wspace]}
host_info[:address] = address
host_info[:name] = @state[:host]
db_report(:host, host_info)
end
def report_web_service_info
return unless @state[:host]
return unless @state[:port]
return unless @state[:proto]
return unless @state[:service_name]
service_info = {}
service_info[:host] = @state[:host]
service_info[:port] = @state[:port]
service_info[:proto] = @state[:proto]
service_info[:name] = @state[:service_name]
@state[:service_object] = db_report(:service, service_info)
end
def report_vuln
return unless @state[:service_object]
return unless @state[:vuln_name]
return unless @state[:issue_detail]
return unless @state[:refs]
vuln_info = {}
vuln_info[:service_id] = @state[:service_object].id
vuln_info[:host] = @state[:host]
vuln_info[:name] = @state[:vuln_name]
vuln_info[:info] = @state[:issue_detail]
vuln_info[:refs] = @state[:refs]
@state[:vuln_object] = db_report(:vuln, vuln_info)
end
def in_issue
return false unless in_tag("issue")
return false unless in_tag("issues")
return true
end
def has_text
return false unless @text
return false if @text.strip.empty?
@text = @text.strip
end
end
end
end

View File

@ -157,7 +157,7 @@ module Rex
host_info = {:workspace => @args[:wspace]}
host_info[:address] = @state[:web_site].service.host.address
host_info[:name] = @state[:uri].host
report_db(:host, host_info)
db_report(:host, host_info)
end
def report_web_service_info

View File

@ -200,6 +200,11 @@ module Parser
return attr_pairs
end
# Removes HTML from a string
def strip_html_tags(text)
return text.gsub!(/(<[^>]*>)|\n|\t/s) {" "}
end
# This breaks xml-encoded characters, so need to append.
# It's on the end_element tag name to turn the appending
# off and clear out the data.

View File

@ -340,6 +340,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do
" Amap Log",
" Amap Log -m",
" Appscan",
" Burp Issue XML",
" Burp Session XML",
" CI",
" Foundstone",