lib/msf/core/auxiliary/web.rb
# -*- coding: binary -*-
module Msf
###
#
# This module provides methods for brute forcing authentication
#
###
module Auxiliary::Web
module Analysis
end
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(&: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.empty?
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(&: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}) 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(&: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}) 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(&: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][:confidence] = confidence
if !(payload = opts[:payload])
if payloads
payload = payloads.select do |p|
element.altered_value.include?(p)
end.max_by(&:size)
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}) URL(#{target.to_url})" \
" PARAMETER(#{element.altered}) VALUES(#{element.params})"
print_good " PROOF(#{proof})"
end
end
end