metasploit-framework/lib/msf/core/auxiliary/web.rb

294 lines
7.2 KiB
Ruby

# -*- coding: binary -*-
module Msf
###
#
# This module provides methods for brute forcing authentication
#
###
module Auxiliary::Web
module Analysis
end
require 'msf/core/auxiliary/web/http'
require 'msf/core/auxiliary/web/fuzzable'
require 'msf/core/auxiliary/web/form'
require 'msf/core/auxiliary/web/path'
require 'msf/core/auxiliary/web/target'
include Auxiliary::Report
attr_reader :target
attr_reader :http
attr_reader :parent
attr_reader :page
def initialize( info = {} )
super
end
# String id to push to the #checklist
def checked( id )
parent.checklist << "#{shortname}#{id}".hash
end
# String id to check against the #checklist
def checked?( id )
parent.checklist.include? "#{shortname}#{id}".hash
end
#
# Called directly before 'run'
#
def setup( opts = {} )
@parent = opts[:parent]
@target = opts[:target]
@page = opts[:page]
@http = opts[:http]
end
# Should be overridden to return the exploits to use for this
# vulnerability type as an Array of Strings.
def self.exploits
end
# Must return a configuration Hash for the given exploit and vulnerability.
def self.configure_exploit( exploit, vuln )
end
# Should be overridden to return the payloads used for this
# vulnerability type as an Array of Strings.
def payloads
end
def token
"xssmsfpro"
end
#
# Should be overridden to return a pattern to be matched against response
# bodies in order to identify a vulnerability.
#
# You can go one deeper and override #find_proof for more complex processing.
#
def signature
end
#
# Default #run, will audit all elements using taint analysis and log
# results based on #find_proof return values.
#
def run
auditable.each { |element| element.taint_analysis }
end
# Returns an Array of elements prepared to be audited.
def auditable
target.auditable.map do |element|
element.fuzzer = self
element
end
end
# Checks whether a resource exists based on a path String.
def resource_exist?( path )
res = http.get( path )
res.code.to_i == 200 && !http.custom_404?( path, res.body )
end
alias :file_exist? :resource_exist?
# Checks whether a directory exists based on a path String.
def directory_exist?( path )
dir = path.dup
dir << '/' if !dir.end_with?( '/' )
resource_exist?( dir )
end
# Logs the existence of a resource in the path String.
def log_resource_if_exists( path )
log_resource( :location => path ) if resource_exist?( path )
end
alias :log_file_if_exists :log_resource_if_exists
# Logs the existence of the directory in the path String.
def log_directory_if_exists( path )
dir = path.dup
dir << '/' if !dir.end_with?( '/' )
log_resource_if_exists( dir )
end
# Matches fingerprint pattern against the current page's body and logs matches
def match_and_log_fingerprint( fingerprint, options = {} )
return if (match = page.body.to_s.match( fingerprint ).to_s).empty?
log_fingerprint( options.merge( :fingerprint => match ) )
end
#
# Serves as a default detection method for when performing taint analysis.
#
# Uses the Regexp in #signature against the response body in order to
# identify vulnerabilities and return a String that proves it.
#
# Override it if you need more complex processing, but remember to return
# the proof as a String.
#
# response - Auxiliary::Web::HTTP::Response
# element - the submitted element
#
def find_proof( response, element )
return if !signature
m = response.body.match( signature ).to_s
return if !m || m.size < 1
m.gsub( /[\r\n]/, ' ' )
end
def increment_request_counter
parent.increment_request_counter
end
# Should be overridden and return an Integer (0-100) denoting the confidence
# in the accuracy of the logged vuln.
def calculate_confidence( vuln )
100
end
def log_fingerprint( opts = {} )
mode = name
vhash = [target.to_url, opts[:fingerprint], mode, opts[:location]].
map { |x| x.to_s }.join( '|' ).hash
parent.vulns[mode] ||= {}
return if parent.vulns[mode].include?( vhash )
location = opts[:location] ?
page.url.merge( URI( opts[:location].to_s )) : page.url
info = {
:web_site => target.site,
:path => location.path,
:query => location.query,
:method => 'GET',
:params => [],
:pname => 'path',
:proof => opts[:fingerprint],
:risk => details[:risk],
:name => details[:name],
:blame => details[:blame],
:category => details[:category],
:description => details[:description],
:owner => self
}
info[:confidence] = calculate_confidence( info )
parent.vulns[mode][vhash] = info
report_web_vuln( info )
opts[:print_fingerprint] = true if !opts.include?( :print_fingerprint )
print_good " FOUND(#{mode.to_s}) URL(#{location})"
print_good " PROOF(#{opts[:fingerprint]})" if opts[:print_fingerprint]
end
def log_resource( opts = {} )
mode = name
vhash = [target.to_url, mode, opts[:location]].
map { |x| x.to_s }.join( '|' ).hash
parent.vulns[mode] ||= {}
return if parent.vulns[mode].include?( vhash )
location = URI( opts[:location].to_s )
info = {
:web_site => target.site,
:path => location.path,
:query => location.query,
:method => 'GET',
:params => [],
:pname => 'path',
:proof => opts[:location],
:risk => details[:risk],
:name => details[:name],
:blame => details[:blame],
:category => details[:category],
:description => details[:description],
:owner => self
}
info[:confidence] = calculate_confidence( info )
parent.vulns[mode][vhash] = info
report_web_vuln( info )
print_good " VULNERABLE(#{mode.to_s}) URL(#{target.to_url})"
print_good " PROOF(#{opts[:location]})"
end
def process_vulnerability( element, proof, opts = {} )
mode = name
vhash = [target.to_url, mode, element.altered].
map{ |x| x.to_s }.join( '|' ).hash
parent.vulns[mode] ||= {}
return parent.vulns[mode][vhash] if parent.vulns[mode][vhash]
parent.vulns[mode][vhash] = {
:target => target,
:method => element.method.to_s.upcase,
:params => element.params.to_a,
:mode => mode,
:pname => element.altered,
:proof => proof.to_s,
:form => element.model,
:risk => details[:risk],
:name => details[:name],
:blame => details[:blame],
:category => details[:category],
:description => details[:description]
}
confidence = calculate_confidence( parent.vulns[mode][vhash] )
parent.vulns[mode][vhash].merge!( :confidence => confidence )
if !(payload = opts[:payload])
if payloads
payload = payloads.select { |p|
element.altered_value.include?( p )
}.sort_by { |p| p.size }.last
end
end
uri = URI( element.action )
info = {
:web_site => element.model.web_site,
:path => uri.path,
:query => uri.query,
:method => element.method.to_s.upcase,
:params => element.params.to_a,
:pname => element.altered,
:proof => proof.to_s,
:risk => details[:risk],
:name => details[:name],
:blame => details[:blame],
:category => details[:category],
:description => details[:description],
:confidence => confidence,
:payload => payload,
:owner => self
}
report_web_vuln( info )
print_good " VULNERABLE(#{mode.to_s}) URL(#{target.to_url})" +
" PARAMETER(#{element.altered}) VALUES(#{element.params})"
print_good " PROOF(#{proof})"
end
end
end