Metasploit Framework is an open-source penetration testing and exploitation framework written in Ruby. It provides infrastructure for developing, testing, and executing exploit code against remote targets.
- Prefer writing modules in Ruby. Go and Python modules are accepted, but their external runtimes don't support the full framework API (e.g. network pivoting). Ruby modules do not have this limitation
- Before writing a new module, check that there is not an existing module or open pull request that already covers the same functionality
- Each module should be in its own file under the appropriate `modules/` subdirectory. In some scenarios adding module actions or targets is preferred.
- Exploits require a `DisclosureDate` field
- Exploits, auxiliary, and post modules require `Notes` with `SideEffects`
- Use the module mixin APIs — don't reinvent the wheel
- Use `create_process(executable, args: [], time_out: 15, opts: {})` instead of the deprecated `cmd_exec` with separate arguments
- License new code with `MSF_LICENSE` (the project default, defined in `lib/msf/core/constants.rb`)
- When overriding `cleanup`, always call `super` to ensure the parent mixin chain cleans up connections and sessions properly
- When possible don't set a default payload (`DefaultOptions` with `'PAYLOAD'`) in modules — let the framework choose the most appropriate payload automatically
- New modules require an associated markdown file in the `documentation/modules` folder with the same structure, including steps to set up the vulnerable environment for testing
- Module descriptions or documentation should list the range of vulnerable versions and the fixed version of the affected software, when known
- Use the TEST-NET-1 range for example / non-routeable IP addresses in unit tests and spec files: `192.0.2.0`. Local/private IPs are fine in module documentation scenarios.
- Use fetch payload instead of command stagers when only options that request the stage are available (i.e. don’t use a cmd stager and only allow curl/wget).
- Define bad characters instead of explicitly base-64 encoding payloads
- Use `ARCH_CMD` payloads instead of command stagers when only curl/wget and other download mechanisms would be available
- Don’t check the number of sessions at the end of an exploit and report success based on that, not all payloads open sessions
- Don’t submit any kind of opaque binary blob, everything must include source code and build instructions
- Don’t print host information like `#{ip}:#{port}` because it doesn’t handle IPv6 addresses, instead use `#{Rex::Socket.to_authority(ip, port)}`
- Use `fail_with(Failure::UnexpectedReply, '...')` (and other `Failure::*` constants) to bail out of `exploit`/`run` methods — don't use `raise` or bare `return` for error conditions
- Use specific regular expressions or `res.get_html_document` for version extraction with CSS selectors. Don't use a generic selectors like `href .*` dot star to grab the version, be more precise.
- Do catch exceptions that may be raised and ensure a valid Check Code is returned
- Do research and determine a minimum version where the application is vulnerable, mark prior versions as safe
- Check helper methods that are used by both `#check` and `#exploit` (or `#run`) and make sure there is no condition (exception, return, etc) where `#check` could return something else than CheckCode.
- When adding complex binary or protocol parsing (e.g. BinData, RASN1, Rex::Struct2), include a code comment linking to the specification or RFC that defines the format being implemented
- Use the `Rex::MIME::Message` class for MIME messages instead of hardcoding XML
- When creating random variable names prefer `Rex::RandomIdentifier::Generator` and specify the runtime language used. This avoids generating langauge keywords that would break the script.