Metasploit Deep Dive Part 13: Database, Workspaces, Loot, and Credential Tracking
Every RPC method Part 11 read from lib/msf/core/rpc/v10/rpc_db.rb, and every read-only tool Part 12 read from msfmcpd’s documentation, points at the same underlying layer: Metasploit’s database. This post is about what that layer actually holds and how it’s organized, the piece that turns a single msfconsole session’s findings into something that persists across sessions, gets shared across a team, and stays queryable months later.
Workspaces: the top-level container
rpc_workspaces, rpc_current_workspace, and rpc_get_workspace, all real methods in rpc_db.rb, expose what’s structurally the top of the hierarchy: a workspace is an isolated container for everything discovered during an engagement, hosts, services, vulnerabilities, credentials, notes, loot. Every other database-backed RPC method and MCP tool takes an optional workspace parameter, defaulting to default when omitted. This isn’t an organizational nicety bolted on afterward; it’s the mechanism that lets one Metasploit installation cleanly track multiple concurrent or sequential engagements without one client’s findings bleeding into another’s. msf_host_info, msf_service_info, msf_vulnerability_info, msf_note_info, msf_credential_info, and msf_loot_info, the six read-only MCP tools Part 12 named that specifically require a running database, all filter by workspace first.
Hosts and services: what the recon layer feeds
rpc_hosts and rpc_services back the same data an nmap import or a live auxiliary scanner module writes into the database as it runs. A host record tracks address, OS fingerprint, and up/down state; a service record tracks port, protocol, and the service name Metasploit’s own scanners or an imported scan identified. This is the layer that makes Metasploit’s own module search genuinely situational rather than generic: msf_search_modules combined with msf_service_info (from Part 12’s read-only tier) is how an agent, human or automated, narrows five thousand modules down to the small number relevant to what’s actually running on a specific target, rather than searching in the abstract.
Vulnerabilities and notes
rpc_vulns tracks confirmed or suspected vulnerabilities per host and service, typically populated by a module’s check method (the same CheckCode result Part 12’s msf_module_check tool surfaces: Vulnerable, Safe, Detected, Appears, Unknown) or by an imported vulnerability scan. Notes are a more general-purpose bucket, real note types seen in msfmcpd’s own documentation include things like ssl.certificate and smb.fingerprint, structured metadata that doesn’t fit neatly into the host/service/vuln schema but is still worth persisting and querying later.
Credentials: create, invalidate, never silently overwrite
rpc_create_credential, rpc_create_cracked_credential, rpc_invalidate_login, and rpc_del_creds are the real methods governing this table, and the naming is deliberate. Credentials aren’t just inserted and left; they can be explicitly marked invalid (a login that stopped working, a password that got rotated mid-engagement) without deleting the historical record, which matters for anyone reconstructing an engagement’s timeline afterward. rpc_create_cracked_credential is a distinct method from plain credential creation, specifically for recording a credential recovered by cracking rather than found directly, a distinction this site’s own Password Cracking and Wordlist Engineering series covered from the cracking side without touching how Metasploit specifically tracks the result afterward.
Loot: the actual files
Loot is the odd one out in this schema, because everything else described so far is structured metadata, while loot is Metasploit’s mechanism for storing actual recovered artifacts: a dumped SAM hive, a stolen document, a memory dump, a captured screenshot. msf_loot_info, the corresponding read-only MCP tool, queries the metadata (what was collected, from where, when) rather than streaming the file contents themselves through the MCP layer, keeping potentially large binary artifacts out of a protocol built around structured JSON responses.
Getting the database running
msfdb init and msfdb start are the two real commands governing this layer’s own lifecycle, both referenced directly in msfmcpd’s own setup documentation: without a running database, the six read-only tools this post has been describing simply don’t work, and msfmcpd prints an explicit warning to that effect rather than failing silently. This is worth noting because it’s a real operational dependency this entire series has been assuming without stating outright: msfconsole and the RPC layer both function without a database, in a degraded mode where nothing persists past the current session, but the value Part 12’s read-only MCP tools provide, situational awareness for an agent working across multiple queries, is entirely dependent on this layer actually being up.
Why this is the right note to end the non-lab material on
Everything in Parts 1 through 12 has been about generating, transporting, and executing capability: modules, payloads, protocols, transports, evasion, RPC, and now a first-party MCP layer sitting on top of all of it. This post is the one piece of the framework whose entire job is remembering what happened. It’s also, not coincidentally, the layer every one of Part 12’s read-only MCP tools depends on to be useful at all, an agent asking msf_host_info about a target it scanned three tool calls ago only gets a sensible answer because this database, not the agent’s own context window, is what actually persisted that finding.
Parts 6, 7, and 8 have since run against a real lab, and Part 14 closes the series with a retrospective against them, but worth flagging now rather than leaving it as a surprise: none of those three parts, or Part 14 itself, actually used this layer. msfdb init was never run against that lab, and every finding, target-win2022’s identity, target-wordpress’s exploitation path, hidden-target’s IP, lives in this blog’s drafts and a status document instead of an actual workspace. The persistence layer described above is real and it works exactly as documented; it just never got exercised here, which says more about how a single evening of hands-on testing differs from a sustained engagement than it does about the framework.