Skip to content

Commit 32b1a5e

Browse files
David MaloneyDavid Maloney
authored andcommitted
add ipboard loginscanner
add loginscanner class for IPBoard with specs this should replicate the functionality originally written by Chris Truncer, but move it into a testable, reusable class
1 parent c3213a7 commit 32b1a5e

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
require 'metasploit/framework/login_scanner/http'
2+
3+
module Metasploit
4+
module Framework
5+
module LoginScanner
6+
7+
# IP Board login scanner
8+
class IPBoard < HTTP
9+
10+
# (see Base#attempt_login)
11+
def attempt_login(credential)
12+
http_client = Rex::Proto::Http::Client.new(
13+
host, port, {}, ssl, ssl_version
14+
)
15+
16+
result_opts = {
17+
credential: credential,
18+
host: host,
19+
port: port,
20+
protocol: 'tcp'
21+
}
22+
if ssl
23+
result_opts[:service_name] = 'https'
24+
else
25+
result_opts[:service_name] = 'http'
26+
end
27+
28+
begin
29+
http_client.connect
30+
31+
nonce_request = http_client.request_cgi(
32+
'uri' => uri,
33+
'method' => 'GET'
34+
)
35+
36+
nonce_response = http_client.send_recv(nonce_request)
37+
38+
if nonce_response.body =~ /name='auth_key'\s+value='.*?((?:[a-z0-9]*))'/i
39+
server_nonce = $1
40+
41+
auth_uri = "#{uri}/index.php?app=core&module=global&section=login&do=process"
42+
43+
request = http_client.request_cgi(
44+
'uri' => auth_uri,
45+
'method' => 'POST',
46+
'vars_post' => {
47+
'auth_key' => server_nonce,
48+
'ips_username' => credential.public,
49+
'ips_password' => credential.private
50+
},
51+
)
52+
53+
response = http_client.send_recv(request)
54+
55+
if response && response.code == 200 && response.get_cookies.include?('ipsconnect') && response.get_cookies.include?('coppa')
56+
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: response)
57+
else
58+
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: response)
59+
end
60+
61+
else
62+
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: "Server nonce not present, potentially not an IP Board install or bad URI.")
63+
end
64+
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error
65+
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
66+
end
67+
68+
Result.new(result_opts)
69+
70+
end
71+
72+
73+
# (see Base#set_sane_defaults)
74+
def set_sane_defaults
75+
self.uri = "/forum/" if self.uri.nil?
76+
@method = "POST".freeze
77+
78+
super
79+
end
80+
81+
# The method *must* be "POST", so don't let the user change it
82+
# @raise [RuntimeError]
83+
def method=(_)
84+
raise RuntimeError, "Method must be POST for IPBoard"
85+
end
86+
87+
end
88+
end
89+
end
90+
end
91+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
require 'spec_helper'
2+
require 'metasploit/framework/login_scanner/ipboard'
3+
4+
describe Metasploit::Framework::LoginScanner::IPBoard do
5+
6+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
7+
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
8+
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
9+
10+
end

0 commit comments

Comments
 (0)