Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/metasploit/framework/credential_collection.rb
Views: 11779
require 'metasploit/framework/credential'12module Metasploit::Framework34class PrivateCredentialCollection5# @!attribute additional_privates6# Additional private values that should be tried7# @return [Array<String>]8attr_accessor :additional_privates910# @!attribute blank_passwords11# Whether each username should be tried with a blank password12# @return [Boolean]13attr_accessor :blank_passwords1415# @!attribute nil_passwords16# Whether each username should be tried with a nil password17# @return [Boolean]18attr_accessor :nil_passwords1920# @!attribute pass_file21# Path to a file containing passwords, one per line22# @return [String]23attr_accessor :pass_file2425# @!attribute password26# The password that should be tried27# @return [String]28attr_accessor :password2930# @!attribute prepended_creds31# List of credentials to be tried before any others32#33# @see #prepend_cred34# @return [Array<Credential>]35attr_accessor :prepended_creds3637# @!attribute realm38# The authentication realm associated with this password39# @return [String]40attr_accessor :realm4142# @!attribute filter43# A block that can be used to filter credential objects44attr_accessor :filter4546# @option opts [Boolean] :nil_passwords See {#nil_passwords}47# @option opts [Boolean] :blank_passwords See {#blank_passwords}48# @option opts [String] :pass_file See {#pass_file}49# @option opts [String] :password See {#password}50# @option opts [Array<Credential>] :prepended_creds ([]) See {#prepended_creds}51# @option opts [Boolean] :user_as_pass See {#user_as_pass}52# @option opts [String] :user_file See {#user_file}53# @option opts [String] :username See {#username}54# @option opts [String] :userpass_file See {#userpass_file}55# @option opts [String] :usernames_only See {#usernames_only}56def initialize(opts = {})57opts.each do |attribute, value|58public_send("#{attribute}=", value)59end60self.prepended_creds ||= []61self.additional_privates ||= []62self.filter = nil63end6465# Adds a string as an additional private credential66# to be combined in the collection.67#68# @param [String] private_str The string to use as a private credential69# @return [void]70def add_private(private_str='')71additional_privates << private_str72end7374# Add {Credential credentials} that will be yielded by {#each}75#76# @see prepended_creds77# @param [Credential] cred78# @return [self]79def prepend_cred(cred)80prepended_creds.unshift cred81self82end8384# Combines all the provided credential sources into a stream of {Credential}85# objects, yielding them one at a time86#87# @yieldparam credential [Metasploit::Framework::Credential]88# @return [void]89def each_filtered90each_unfiltered do |credential|91next unless self.filter.nil? || self.filter.call(credential)9293yield credential94end95end9697# Combines all the provided credential sources into a stream of {Credential}98# objects, yielding them one at a time99#100# @yieldparam credential [Metasploit::Framework::Credential]101# @return [void]102def each_unfiltered103if pass_file.present?104pass_fd = File.open(pass_file, 'r:binary')105end106107prepended_creds.each { |c| yield c }108109if password.present?110yield Metasploit::Framework::Credential.new(private: password, realm: realm, private_type: private_type(password))111end112if blank_passwords113yield Metasploit::Framework::Credential.new(private: "", realm: realm, private_type: :password)114end115if nil_passwords116yield Metasploit::Framework::Credential.new(private: nil, realm: realm, private_type: :password)117end118if pass_fd119pass_fd.each_line do |pass_from_file|120pass_from_file.chomp!121yield Metasploit::Framework::Credential.new(private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))122end123pass_fd.seek(0)124end125additional_privates.each do |add_private|126yield Metasploit::Framework::Credential.new(private: add_private, realm: realm, private_type: private_type(add_private))127end128129ensure130pass_fd.close if pass_fd && !pass_fd.closed?131end132133# Returns true when #each will have no results to iterate134#135# @return [Boolean]136def empty?137prepended_creds.empty? && !has_privates?138end139140# Returns true when a filter is defined141#142# @return [Boolean]143def filtered?144!self.filter.nil?145end146147# Returns true when there are any private values set148#149# @return [Boolean]150def has_privates?151password.present? || pass_file.present? || !additional_privates.empty? || blank_passwords || nil_passwords152end153154alias each each_filtered155156protected157158# Analyze a private value to determine its type by checking it against a known list of regular expressions159#160# @param [String] private The string to analyze161# @return [Symbol]162def private_type(private)163if private =~ /[0-9a-f]{32}:[0-9a-f]{32}/164:ntlm_hash165elsif private =~ /^md5([a-f0-9]{32})$/166:postgres_md5167else168:password169end170end171end172173class CredentialCollection < PrivateCredentialCollection174# @!attribute password_spray175# Whether password spray is enabled. When true, each password is tried against each username first.176# Otherwise the default bruteforce logic will attempt all passwords against the first user, before177# continuing to the next user178#179# @return [Boolean]180attr_accessor :password_spray181182# @!attribute additional_publics183# Additional public values that should be tried184#185# @return [Array<String>]186attr_accessor :additional_publics187188# @!attribute user_as_pass189# Whether each username should be tried as a password for that user190# @return [Boolean]191attr_accessor :user_as_pass192193# @!attribute user_file194# Path to a file containing usernames, one per line195# @return [String]196attr_accessor :user_file197198# @!attribute username199# The username that should be tried200# @return [String]201attr_accessor :username202203# @!attribute userpass_file204# Path to a file containing usernames and passwords separated by a space,205# one pair per line206# @return [String]207attr_accessor :userpass_file208209# @!attribute anonymous_login210# Whether to attempt an anonymous login (blank user/pass)211# @return [Boolean]212attr_accessor :anonymous_login213214# @option opts [Boolean] :blank_passwords See {#blank_passwords}215# @option opts [String] :pass_file See {#pass_file}216# @option opts [String] :password See {#password}217# @option opts [Array<Credential>] :prepended_creds ([]) See {#prepended_creds}218# @option opts [Boolean] :user_as_pass See {#user_as_pass}219# @option opts [String] :user_file See {#user_file}220# @option opts [String] :username See {#username}221# @option opts [String] :userpass_file See {#userpass_file}222def initialize(opts = {})223super224self.additional_publics ||= []225end226227# Adds a string as an additional public credential228# to be combined in the collection.229#230# @param [String] public_str The string to use as a public credential231# @return [void]232def add_public(public_str='')233additional_publics << public_str234end235236# Combines all the provided credential sources into a stream of {Credential}237# objects, yielding them one at a time238#239# @yieldparam credential [Metasploit::Framework::Credential]240# @return [void]241def each_filtered242if password_spray243each_unfiltered_password_first do |credential|244next unless self.filter.nil? || self.filter.call(credential)245246yield credential247end248else249each_unfiltered_username_first do |credential|250next unless self.filter.nil? || self.filter.call(credential)251252yield credential253end254end255end256257alias each each_filtered258259# When password spraying is enabled, do first passwords then usernames260# i.e.261# username1:password1262# username2:password1263# username3:password1264# ...265# username1:password2266# username2:password2267# username3:password2268# ...269# @yieldparam credential [Metasploit::Framework::Credential]270# @return [void]271def each_unfiltered_password_first272if user_file.present?273user_fd = File.open(user_file, 'r:binary')274end275276prepended_creds.each { |c| yield c }277278if anonymous_login279yield Metasploit::Framework::Credential.new(public: '', private: '', realm: realm, private_type: :password)280end281282if user_as_pass283if user_fd284user_fd.each_line do |user_from_file|285user_from_file.chomp!286yield Metasploit::Framework::Credential.new(public: user_from_file, private: user_from_file, realm: realm, private_type: private_type(password))287end288user_fd.seek(0)289end290end291292if password.present?293if nil_passwords294yield Metasploit::Framework::Credential.new(public: username, private: nil, realm: realm, private_type: :password)295end296if username.present?297yield Metasploit::Framework::Credential.new(public: username, private: password, realm: realm, private_type: private_type(password))298end299if user_as_pass300yield Metasploit::Framework::Credential.new(public: username, private: username, realm: realm, private_type: :password)301end302if blank_passwords303yield Metasploit::Framework::Credential.new(public: username, private: "", realm: realm, private_type: :password)304end305if user_fd306user_fd.each_line do |user_from_file|307user_from_file.chomp!308yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(password))309end310user_fd.seek(0)311end312end313314if pass_file.present?315File.open(pass_file, 'r:binary') do |pass_fd|316pass_fd.each_line do |pass_from_file|317pass_from_file.chomp!318if username.present?319yield Metasploit::Framework::Credential.new(public: username, private: pass_from_file, realm: realm, private_type: :password)320end321next unless user_fd322323user_fd.each_line do |user_from_file|324user_from_file.chomp!325yield Metasploit::Framework::Credential.new(public: user_from_file, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))326end327user_fd.seek(0)328end329end330end331332if userpass_file.present?333File.open(userpass_file, 'r:binary') do |userpass_fd|334userpass_fd.each_line do |line|335user, pass = line.split(" ", 2)336if pass.blank?337pass = ''338else339pass.chomp!340end341yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm)342end343end344end345346additional_privates.each do |add_private|347if username.present?348yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))349end350user_fd.each_line do |user_from_file|351user_from_file.chomp!352yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))353end354user_fd.seek(0)355end356357additional_publics.each do |add_public|358if password.present?359yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )360end361if user_as_pass362yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)363end364if blank_passwords365yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)366end367if nil_passwords368yield Metasploit::Framework::Credential.new(public: add_public, private: nil, realm: realm, private_type: :password)369end370if user_fd371user_fd.each_line do |user_from_file|372user_from_file.chomp!373yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: private_type(user_from_file))374end375user_fd.seek(0)376end377additional_privates.each do |add_private|378yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))379end380end381ensure382user_fd.close if user_fd && !user_fd.closed?383end384385# When password spraying is not enabled, do first usernames then passwords386# i.e.387# username1:password1388# username1:password2389# username1:password3390# ...391# username2:password1392# username2:password2393# username2:password3394# @yieldparam credential [Metasploit::Framework::Credential]395# @return [void]396def each_unfiltered_username_first397if pass_file.present?398pass_fd = File.open(pass_file, 'r:binary')399end400401prepended_creds.each { |c| yield c }402403if anonymous_login404yield Metasploit::Framework::Credential.new(public: '', private: '', realm: realm, private_type: :password)405end406407if username.present?408if nil_passwords409yield Metasploit::Framework::Credential.new(public: username, private: nil, realm: realm, private_type: :password)410end411if password.present?412yield Metasploit::Framework::Credential.new(public: username, private: password, realm: realm, private_type: private_type(password))413end414if user_as_pass415yield Metasploit::Framework::Credential.new(public: username, private: username, realm: realm, private_type: :password)416end417if blank_passwords418yield Metasploit::Framework::Credential.new(public: username, private: "", realm: realm, private_type: :password)419end420if pass_fd421pass_fd.each_line do |pass_from_file|422pass_from_file.chomp!423yield Metasploit::Framework::Credential.new(public: username, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))424end425pass_fd.seek(0)426end427additional_privates.each do |add_private|428yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))429end430end431432if user_file.present?433File.open(user_file, 'r:binary') do |user_fd|434user_fd.each_line do |user_from_file|435user_from_file.chomp!436if nil_passwords437yield Metasploit::Framework::Credential.new(public: user_from_file, private: nil, realm: realm, private_type: :password)438end439if password.present?440yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(password) )441end442if user_as_pass443yield Metasploit::Framework::Credential.new(public: user_from_file, private: user_from_file, realm: realm, private_type: :password)444end445if blank_passwords446yield Metasploit::Framework::Credential.new(public: user_from_file, private: "", realm: realm, private_type: :password)447end448if pass_fd449pass_fd.each_line do |pass_from_file|450pass_from_file.chomp!451yield Metasploit::Framework::Credential.new(public: user_from_file, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))452end453pass_fd.seek(0)454end455additional_privates.each do |add_private|456yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))457end458end459end460end461462if userpass_file.present?463File.open(userpass_file, 'r:binary') do |userpass_fd|464userpass_fd.each_line do |line|465user, pass = line.split(" ", 2)466if pass.blank?467pass = ''468else469pass.chomp!470end471yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm)472end473end474end475476additional_publics.each do |add_public|477if password.present?478yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )479end480if user_as_pass481yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)482end483if blank_passwords484yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)485end486if pass_fd487pass_fd.each_line do |pass_from_file|488pass_from_file.chomp!489yield Metasploit::Framework::Credential.new(public: add_public, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))490end491pass_fd.seek(0)492end493additional_privates.each do |add_private|494yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))495end496end497ensure498pass_fd.close if pass_fd && !pass_fd.closed?499end500501# Returns true when #each will have no results to iterate502#503# @return [Boolean]504def empty?505prepended_creds.empty? && !has_users? && !anonymous_login || (has_users? && !has_privates?)506end507508# Returns true when there are any user values set509#510# @return [Boolean]511def has_users?512username.present? || user_file.present? || userpass_file.present? || !additional_publics.empty?513end514515# Returns true when there are any private values set516#517# @return [Boolean]518def has_privates?519super || userpass_file.present? || user_as_pass520end521522end523end524525526