Skip to content

Commit 917a7ff

Browse files
committed
Add specs for valid IPBoard application
1 parent 2ac15f2 commit 917a7ff

File tree

2 files changed

+109
-8
lines changed

2 files changed

+109
-8
lines changed

lib/metasploit/framework/login_scanner/ipboard.rb

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,22 @@ def attempt_login(credential)
4646
base_uri = uri
4747
end
4848

49-
auth_uri = "#{base_uri}/index.php?app=core&module=global&section=login&do=process"
49+
auth_uri = "#{base_uri}/index.php"
5050

5151
request = http_client.request_cgi(
52-
'uri' => auth_uri,
53-
'method' => 'POST',
54-
'vars_post' => {
55-
'auth_key' => server_nonce,
56-
'ips_username' => credential.public,
57-
'ips_password' => credential.private
58-
},
52+
'uri' => auth_uri,
53+
'method' => 'POST',
54+
'vars_get' => {
55+
'app' => 'core',
56+
'module' => 'global',
57+
'section' => 'login',
58+
'do' => 'process'
59+
},
60+
'vars_post' => {
61+
'auth_key' => server_nonce,
62+
'ips_username' => credential.public,
63+
'ips_password' => credential.private
64+
}
5965
)
6066

6167
response = http_client.send_recv(request)

spec/lib/metasploit/framework/login_scanner/ipboard_spec.rb

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,103 @@
33

44
describe Metasploit::Framework::LoginScanner::IPBoard do
55

6+
subject { described_class.new }
7+
68
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
79
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
810
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
911

12+
context "#attempt_login" do
13+
14+
let(:username) { 'admin' }
15+
let(:password) { 'password' }
16+
let(:server_nonce) { 'nonce' }
17+
18+
let(:creds) do
19+
Metasploit::Framework::Credential.new(
20+
paired: true,
21+
public: username,
22+
private: password
23+
)
24+
end
25+
26+
let(:invalid_creds) do
27+
Metasploit::Framework::Credential.new(
28+
paired: true,
29+
public: 'username',
30+
private: 'novalid'
31+
)
32+
end
33+
34+
context "when Rex::Proto::Http::Client#connect raises Rex::ConnectionError" do
35+
it 'returns status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
36+
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect).and_raise(Rex::ConnectionError)
37+
expect(subject.attempt_login(creds).status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
38+
end
39+
end
40+
41+
context "when Rex::Proto::Http::Client#connect raises Timeout::Error" do
42+
it 'returns status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
43+
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect).and_raise(Timeout::Error)
44+
expect(subject.attempt_login(creds).status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
45+
end
46+
end
47+
48+
context "when Rex::Proto::Http::Client#connect raises EOFError" do
49+
it 'returns status Metasploit::Model::Login::Status::UNABLE_TO_CONNECT' do
50+
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect).and_raise(EOFError)
51+
expect(subject.attempt_login(creds).status).to eq(Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
52+
end
53+
end
54+
55+
context "when valid IPBoard application" do
56+
before :each do
57+
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv) do |cli, req|
58+
59+
if req.opts['uri'] && req.opts['uri'].include?('index.php') &&
60+
req.opts['vars_get'] &&
61+
req.opts['vars_get']['app'] &&
62+
req.opts['vars_get']['app'] == 'core' &&
63+
req.opts['vars_get']['module'] &&
64+
req.opts['vars_get']['module'] == 'global' &&
65+
req.opts['vars_get']['section'] &&
66+
req.opts['vars_get']['section'] == 'login' &&
67+
req.opts['vars_get']['do'] &&
68+
req.opts['vars_get']['do'] == 'process' &&
69+
req.opts['vars_post'] &&
70+
req.opts['vars_post']['auth_key'] &&
71+
req.opts['vars_post']['auth_key'] == server_nonce &&
72+
req.opts['vars_post']['ips_username'] &&
73+
req.opts['vars_post']['ips_username'] == username &&
74+
req.opts['vars_post']['ips_password'] &&
75+
req.opts['vars_post']['ips_password'] == password
76+
res = Rex::Proto::Http::Response.new(200)
77+
res.headers['Set-Cookie'] = 'ipsconnect=ipsconnect_value;Path=/;,coppa=coppa_value;Path=/;'
78+
elsif req.opts['uri'] && req.opts['uri'].include?('index.php') && req.opts['method'] == 'POST'
79+
res = Rex::Proto::Http::Response.new(404)
80+
else
81+
res = Rex::Proto::Http::Response.new(200)
82+
res.body = "name='auth_key' value='#{server_nonce}'"
83+
end
84+
85+
res
86+
end
87+
end
88+
89+
context "when valid login" do
90+
it 'returns status Metasploit::Model::Login::Status::SUCCESSFUL' do
91+
expect(subject.attempt_login(creds).status).to eq(Metasploit::Model::Login::Status::SUCCESSFUL)
92+
end
93+
end
94+
95+
context "when invalid login" do
96+
it 'returns status Metasploit::Model::Login::Status::INCORRECT' do
97+
expect(subject.attempt_login(invalid_creds).status).to eq(Metasploit::Model::Login::Status::INCORRECT)
98+
end
99+
end
100+
101+
end
102+
end
103+
104+
10105
end

0 commit comments

Comments
 (0)