Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/integration/msfmcpd/tool_execution_module_info_spec.rb
70330 views
1
# frozen_string_literal: true
2
3
require 'msf/core/mcp'
4
require 'webmock/rspec'
5
6
RSpec.describe 'Tool Execution End-to-End - Module Info' do
7
before(:all) do
8
WebMock.disable_net_connect!(allow_localhost: false)
9
end
10
11
after(:all) do
12
WebMock.allow_net_connect!
13
end
14
15
let(:host) { 'localhost' }
16
let(:port) { 55553 }
17
let(:endpoint) { '/api/' }
18
let(:api_url) { "https://#{host}:#{port}#{endpoint}" }
19
let(:user) { 'test_user' }
20
let(:password) { 'test_password' }
21
22
let(:limiter) { Msf::MCP::Security::RateLimiter.new(requests_per_minute: 60, burst_size: 10) }
23
let(:client) do
24
c = Msf::MCP::Metasploit::MessagePackClient.new(host: host, port: port, endpoint: endpoint)
25
c.authenticate(user, password)
26
c
27
end
28
let(:server_context) { { msf_client: client, rate_limiter: limiter } }
29
30
before do
31
stub_request(:post, api_url)
32
.with(body: ['auth.login', user, password].to_msgpack)
33
.to_return(
34
status: 200,
35
body: { 'result' => 'success', 'token' => 'test_token' }.to_msgpack,
36
headers: { 'Content-Type' => 'binary/message-pack' }
37
)
38
end
39
40
describe 'Module Info Integration with HTTP' do
41
it 'retrieves module info through complete HTTP request flow' do
42
info_stub = stub_request(:post, api_url)
43
.with(body: ['module.info', 'test_token', 'exploit', 'windows/smb/ms17_010_eternalblue'].to_msgpack)
44
.to_return(
45
status: 200,
46
body: {
47
'type' => 'exploit',
48
'name' => 'MS17-010 EternalBlue',
49
'fullname' => 'exploit/windows/smb/ms17_010_eternalblue',
50
'rank' => 'excellent',
51
'disclosuredate' => '2017-03-14',
52
'description' => 'MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption',
53
'license' => 'MSF_LICENSE',
54
'filepath' => '/opt/metasploit-framework/modules/exploits/windows/smb/ms17_010_eternalblue.rb',
55
'arch' => ['x64', 'x86'],
56
'platform' => ['windows'],
57
'authors' => ['Author1', 'Author2'],
58
'privileged' => true,
59
'check' => true,
60
'references' => [['CVE', '2017-0144'], ['URL', 'https://example.com']],
61
'targets' => { 0 => 'Windows 7', 1 => 'Windows 8' },
62
'default_target' => 0,
63
'options' => { 'RHOSTS' => { 'type' => 'address', 'required' => true } }
64
}.to_msgpack,
65
headers: { 'Content-Type' => 'binary/message-pack' }
66
)
67
68
result = Msf::MCP::Tools::ModuleInfo.call(
69
type: 'exploit',
70
name: 'windows/smb/ms17_010_eternalblue',
71
server_context: server_context
72
)
73
74
expect(info_stub).to have_been_requested.once
75
76
expect(result).to be_a(MCP::Tool::Response)
77
expect(result.error?).to be false
78
79
data = result.structured_content[:data]
80
expect(data[:fullname]).to eq('exploit/windows/smb/ms17_010_eternalblue')
81
expect(data[:rank]).to eq('excellent')
82
expect(data[:architectures]).to eq(['x64', 'x86'])
83
expect(data[:has_check_method]).to be true
84
85
# Verify filepath is stripped of install path
86
expect(data[:filepath]).to eq('modules/exploits/windows/smb/ms17_010_eternalblue.rb')
87
expect(data[:filepath]).not_to include('/opt/metasploit-framework/')
88
89
# Verify references are transformed
90
expect(data[:references]).to eq([
91
{ type: 'CVE', value: '2017-0144' },
92
{ type: 'URL', value: 'https://example.com' }
93
])
94
95
# Verify metadata
96
expect(result.structured_content[:metadata][:query_time]).to be_a(Float)
97
end
98
99
it 'handles module not found through HTTP' do
100
stub_request(:post, api_url)
101
.with(body: ['module.info', 'test_token', 'exploit', 'nonexistent/module'].to_msgpack)
102
.to_return(
103
status: 500,
104
body: { 'error_message' => 'Module not found' }.to_msgpack
105
)
106
107
result = Msf::MCP::Tools::ModuleInfo.call(
108
type: 'exploit',
109
name: 'nonexistent/module',
110
server_context: server_context
111
)
112
113
expect(result.error?).to be true
114
expect(result.content.first[:text]).to include('Metasploit API error')
115
end
116
117
it 'validates module type before making HTTP request' do
118
result = Msf::MCP::Tools::ModuleInfo.call(
119
type: 'invalid_type',
120
name: 'windows/smb/ms17_010_eternalblue',
121
server_context: server_context
122
)
123
124
expect(result.error?).to be true
125
expect(result.content.first[:text]).to include('Module type')
126
end
127
end
128
end
129
130