From ac3099017791ef1344284a85bd2c350dc59a664f Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Wed, 15 Oct 2014 13:55:24 -0500 Subject: [PATCH] Move libpcap helpers to Libpcap module MSP-11124 --- lib/msf/core/db_manager/import.rb | 94 ----------------------- lib/msf/core/db_manager/import/libpcap.rb | 94 +++++++++++++++++++++++ 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/lib/msf/core/db_manager/import.rb b/lib/msf/core/db_manager/import.rb index 39a285d692..2fa8940d9e 100644 --- a/lib/msf/core/db_manager/import.rb +++ b/lib/msf/core/db_manager/import.rb @@ -357,100 +357,6 @@ module Msf::DBManager::Import raise DBImportError.new("Could not automatically determine file type") end - # Do all the single packet analysis we can while churning through the pcap - # the first time. Multiple packet inspection will come later, where we can - # do stream analysis, compare requests and responses, etc. - def inspect_single_packet(pkt,wspace,args) - if pkt.is_tcp? or pkt.is_udp? - inspect_single_packet_http(pkt,wspace,args) - end - end - - # Checks for packets that are headed towards port 80, are tcp, contain an HTTP/1.0 - # line, contains an Authorization line, contains a b64-encoded credential, and - # extracts it. Reports this credential and solidifies the service as HTTP. - def inspect_single_packet_http(pkt,wspace,args) - task = args.fetch(:task, nil) - # First, check the server side (data from port 80). - if pkt.is_tcp? and pkt.tcp_src == 80 and !pkt.payload.nil? and !pkt.payload.empty? - if pkt.payload =~ /^HTTP\x2f1\x2e[01]/n - http_server_match = pkt.payload.match(/\nServer:\s+([^\r\n]+)[\r\n]/n) - if http_server_match.kind_of?(MatchData) and http_server_match[1] - report_service( - :workspace => wspace, - :host => pkt.ip_saddr, - :port => pkt.tcp_src, - :proto => "tcp", - :name => "http", - :info => http_server_match[1], - :state => Msf::ServiceState::Open, - :task => task - ) - # That's all we want to know from this service. - return :something_significant - end - end - end - - # Next, check the client side (data to port 80) - if pkt.is_tcp? and pkt.tcp_dst == 80 and !pkt.payload.nil? and !pkt.payload.empty? - if pkt.payload.match(/[\x00-\x20]HTTP\x2f1\x2e[10]/n) - auth_match = pkt.payload.match(/\nAuthorization:\s+Basic\s+([A-Za-z0-9=\x2b]+)/n) - if auth_match.kind_of?(MatchData) and auth_match[1] - b64_cred = auth_match[1] - else - return false - end - # If we're this far, we can surmise that at least the client is a web browser, - # he thinks the server is HTTP and he just made an authentication attempt. At - # this point, we'll just believe everything the packet says -- validation ought - # to come later. - user,pass = b64_cred.unpack("m*").first.split(/:/,2) - report_service( - :workspace => wspace, - :host => pkt.ip_daddr, - :port => pkt.tcp_dst, - :proto => "tcp", - :name => "http", - :task => task - ) - - service_data = { - address: pkt.ip_daddr, - port: pkt.tcp_dst, - service_name: 'http', - protocol: 'tcp', - workspace_id: wspace.id - } - service_data[:task_id] = task.id if task - - filename = args[:filename] - - credential_data = { - origin_type: :import, - private_data: pass, - private_type: :password, - username: user, - filename: filename - } - credential_data.merge!(service_data) - credential_core = create_credential(credential_data) - - login_data = { - core: credential_core, - status: Metasploit::Model::Login::Status::UNTRIED - } - - login_data.merge!(service_data) - - create_credential_login(login_data) - - # That's all we want to know from this service. - return :something_significant - end - end - end - # Handles timestamps from Metasploit Express/Pro imports. def msf_import_timestamps(opts,obj) obj.created_at = opts["created_at"] if opts["created_at"] diff --git a/lib/msf/core/db_manager/import/libpcap.rb b/lib/msf/core/db_manager/import/libpcap.rb index e26b83ec86..80d0259ffb 100644 --- a/lib/msf/core/db_manager/import/libpcap.rb +++ b/lib/msf/core/db_manager/import/libpcap.rb @@ -123,4 +123,98 @@ module Msf::DBManager::Import::Libpcap data = PacketFu::PcapFile.new(:filename => filename) import_libpcap(args.merge(:data => data)) end + + # Do all the single packet analysis we can while churning through the pcap + # the first time. Multiple packet inspection will come later, where we can + # do stream analysis, compare requests and responses, etc. + def inspect_single_packet(pkt,wspace,args) + if pkt.is_tcp? or pkt.is_udp? + inspect_single_packet_http(pkt,wspace,args) + end + end + + # Checks for packets that are headed towards port 80, are tcp, contain an HTTP/1.0 + # line, contains an Authorization line, contains a b64-encoded credential, and + # extracts it. Reports this credential and solidifies the service as HTTP. + def inspect_single_packet_http(pkt,wspace,args) + task = args.fetch(:task, nil) + # First, check the server side (data from port 80). + if pkt.is_tcp? and pkt.tcp_src == 80 and !pkt.payload.nil? and !pkt.payload.empty? + if pkt.payload =~ /^HTTP\x2f1\x2e[01]/n + http_server_match = pkt.payload.match(/\nServer:\s+([^\r\n]+)[\r\n]/n) + if http_server_match.kind_of?(MatchData) and http_server_match[1] + report_service( + :workspace => wspace, + :host => pkt.ip_saddr, + :port => pkt.tcp_src, + :proto => "tcp", + :name => "http", + :info => http_server_match[1], + :state => Msf::ServiceState::Open, + :task => task + ) + # That's all we want to know from this service. + return :something_significant + end + end + end + + # Next, check the client side (data to port 80) + if pkt.is_tcp? and pkt.tcp_dst == 80 and !pkt.payload.nil? and !pkt.payload.empty? + if pkt.payload.match(/[\x00-\x20]HTTP\x2f1\x2e[10]/n) + auth_match = pkt.payload.match(/\nAuthorization:\s+Basic\s+([A-Za-z0-9=\x2b]+)/n) + if auth_match.kind_of?(MatchData) and auth_match[1] + b64_cred = auth_match[1] + else + return false + end + # If we're this far, we can surmise that at least the client is a web browser, + # he thinks the server is HTTP and he just made an authentication attempt. At + # this point, we'll just believe everything the packet says -- validation ought + # to come later. + user,pass = b64_cred.unpack("m*").first.split(/:/,2) + report_service( + :workspace => wspace, + :host => pkt.ip_daddr, + :port => pkt.tcp_dst, + :proto => "tcp", + :name => "http", + :task => task + ) + + service_data = { + address: pkt.ip_daddr, + port: pkt.tcp_dst, + service_name: 'http', + protocol: 'tcp', + workspace_id: wspace.id + } + service_data[:task_id] = task.id if task + + filename = args[:filename] + + credential_data = { + origin_type: :import, + private_data: pass, + private_type: :password, + username: user, + filename: filename + } + credential_data.merge!(service_data) + credential_core = create_credential(credential_data) + + login_data = { + core: credential_core, + status: Metasploit::Model::Login::Status::UNTRIED + } + + login_data.merge!(service_data) + + create_credential_login(login_data) + + # That's all we want to know from this service. + return :something_significant + end + end + end end