Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/pymetasploit3' into agen…
Browse files Browse the repository at this point in the history
…t_core

# Conflicts:
#	tools/pymetasploit3/tests/test_db.py
  • Loading branch information
ostorlab committed Nov 1, 2023
2 parents e7713c3 + 2744ea0 commit 71a8147
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 13 deletions.
23 changes: 12 additions & 11 deletions agent/metasploit_agent.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Ostorlab Agent implementation for metasploit"""
import json
import logging
import socket
import time
Expand All @@ -24,7 +25,6 @@
)
logger = logging.getLogger(__name__)

AGENT_ARGS = ["module", "RHOSTS", "VHOST", "RPORT"]
SCHEME_TO_PORT = {"http": 80, "https": 443}
DEFAULT_PORT = 443
MODULE_TIMEOUT = 180
Expand Down Expand Up @@ -59,8 +59,8 @@ def __init__(
agent.Agent.__init__(self, agent_definition, agent_settings)
vuln_mixin.AgentReportVulnMixin.__init__(self)
persist_mixin.AgentPersistMixin.__init__(self, agent_settings)
self.client = utils.initialize_msf_rpc()
self.cid = self.client.consoles.console().cid
self._client = utils.initialize_msf_rpc()
self._cid = self._client.consoles.console().cid

def process(self, message: m.Message) -> None:
"""Trigger Source map enumeration and emit found findings
Expand All @@ -77,7 +77,7 @@ def process(self, message: m.Message) -> None:

module_type, module_name = module.split("/", 1)
try:
selected_module = self.client.modules.use(module_type, module_name)
selected_module = self._client.modules.use(module_type, module_name)
except msfrpc.MsfRpcError as exc:
raise ModuleError("Specified module does not exist") from exc

Expand All @@ -97,7 +97,7 @@ def process(self, message: m.Message) -> None:
started_timestamp = time.time()
results = None
while True:
job_result = self.client.jobs.info_by_uuid(job_uuid)
job_result = self._client.jobs.info_by_uuid(job_uuid)
status = job_result["status"]
if status == "completed":
results = job_result["result"]
Expand All @@ -118,8 +118,8 @@ def process(self, message: m.Message) -> None:
if isinstance(results, dict) and results.get("code") == "vulnerable":
technical_detail += f'Message: {results["message"]}'
else:
console_output = self.client.consoles.console(
self.cid
console_output = self._client.consoles.console(
self._cid
).run_module_with_output(selected_module, mode=mode)
module_output = console_output.split("WORKSPACE => Ostorlab")[1]
if "[-]" in module_output:
Expand Down Expand Up @@ -148,10 +148,11 @@ def _set_module_args(
if "RPORT" in selected_module.missing_required:
selected_module["RPORT"] = rport

extra_args = [arg_name for arg_name in self.args if arg_name not in AGENT_ARGS]
for arg in extra_args:
if arg in selected_module.required:
selected_module[arg] = self.args.get(arg)
msf_options = json.loads(self.args.get("options") or "[]")
for arg in msf_options:
arg_name = arg["name"]
if arg_name in selected_module.options:
selected_module[arg_name] = arg["value"]

if len(selected_module.missing_required) > 0:
raise ArgumentError(
Expand Down
5 changes: 4 additions & 1 deletion ostorlab.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,7 @@ args:
- name: "module"
type: "string"
description: "Metasploit module."

- name: "options"
type: "string"
description: "Metasploit module options"
value: '[]'
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from ostorlab.agent import definitions as agent_definitions
from ostorlab.agent.message import message
from ostorlab.runtimes import definitions as runtime_definitions
from pymetasploit3 import msfrpc
from pytest_mock import plugin

from agent import metasploit_agent as msf_agent
from pymetasploit3 import msfrpc

MSFRPCD_PWD = "Ostorlab123"

Expand Down
35 changes: 35 additions & 0 deletions tests/metasploit_agent_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,38 @@ def testExploitCheck_whenVulnerable_returnConsoleOutput(
"Message: \n"
"[+] 192.168.1.17:3632 - The target is vulnerable.\n"
)


def testAuxiliaryPortScan_whenResultsFound_returnOpenPorts(
agent_instance: msf_agent.MetasploitAgent,
mocker: plugin.MockerFixture,
agent_mock: list[message.Message],
scan_message: message.Message,
exploit_console_output: str,
) -> None:
"""Unit test for agent metasploit"""
agent_instance.settings.args = [
utils_definitions.Arg(
name="module",
type="string",
value=json.dumps("auxiliary/scanner/portscan/tcp").encode(),
),
utils_definitions.Arg(
name="options",
type="string",
value=json.dumps('[{"name": "PORTS", "value": "443,80"}]').encode(),
),
]

agent_instance.process(scan_message)

assert len(agent_mock) == 1
vulnerability_finding = agent_mock[0].data
assert vulnerability_finding["title"] == "Metasploit vulnerability detection"
assert vulnerability_finding["risk_rating"] == "HIGH"
assert "443 - TCP OPEN" in vulnerability_finding["technical_detail"]
assert "Target: www.google.com" in vulnerability_finding["technical_detail"]
assert (
"[*] Auxiliary module execution completed"
in vulnerability_finding["technical_detail"]
)

0 comments on commit 71a8147

Please sign in to comment.