Skip navigation
All Places > Metasploit > Blog > Authors shuckins


3 Posts authored by: shuckins Employee


A vulnerability in Metasploit Pro, Express, and Community was patched in Metasploit v4.14.0 (Update 2017061301). Routes used to stop running tasks (either particular ones or all tasks) allowed GET requests. Only POST requests should have been allowed, as the stop/stop_all routes change the state of the service. This could have allowed an attacker to stop currently-running Metasploit tasks by getting an authenticated user to execute JavaScript (example below). As of Metasploit 4.14.0 (Update 2017061301), the routes for stopping tasks only allow POST requests, which validate the presence of a secret token to prevent CSRF attacks.


CVE-2017-5244 is classified as CWE-352 (Cross-Site Request Forgery), and its CVSSv3 base score is 3.1. This is a lower severity issue due to the complexity of deployment and the lack of data exposure, but we nevertheless strongly encourage Metasploit users to update their instances using the steps outlined under “Remediation” below. In addition, Rapid7 will be doing further review of other important routes to verify they properly restrict access.



Rapid7 warmly thanks Mohamed A. Baset (Founder and Cyber Security Advisor at SAS de C.V. Mexico; @SymbianSyMoh) for reporting this vulnerability to us, as well as providing information to help us resolve the issue and protect Metasploit users. You can read his report on the issue here.


Am I affected?

Versions of Metasploit Pro, Express, and Community editions before 4.14.0 (Update 2017061301) are vulnerable to CVE-2017-5244, regardless of operating system.


Additional details and exploitation

While POST requests go through normal Rails anti-CSRF verification, this doesn’t apply to GET requests. Routes that aren’t idempotent (i.e. they make changes) need to be limited to POST only. Since that was not the case before this patch, and the stop action could be triggered through GET requests, an attacker able to trick an authenticated user to request a URL which runs JavaScript could trigger the same action. It may also be possible to exploit this vulnerability by injecting network traffic impersonating the same request. This video shows the reporter exploiting this vulnerability to stop a running discovery scan.


Example exploitation Javascript calling the affected route after 5 seconds:

setInterval(function(){ window.location.replace(""); }, 5000); 


Regardless of vector, the result of that route being called by an authenticated user would be to stop all running tasks (e.g. discovery scans, report generation). This should show up in UI notifications and task logs. In terms of impact, while some tasks can be replayed (i.e. restarted with the same configuration), there’s no way to resume the stopped tasks; thus data limited to that task may be not be saved to the database, and therefore lost.



We strongly encourage Metasploit users to update their instances to the latest version (Metasploit 4.14.0 (Update 2017061301) or above). You can find detailed update steps here. Release notes and offline installers are available here.


Disclosure Timeline

  • Sat, May 27, 2017: Vulnerability reported to Rapid7 by Mohamed A. Baset
  • Tue, May 30, 2017: Vulnerability confirmed by Rapid7
  • Fri, June 9, 2017: Vulnerability fixed by Rapid7
  • Sun, June 11, 2017: Rapid7 assigned CVE-2017-5244 to this vulnerability
  • Wed, June 14, 2017: Rapid7 released patch; public disclosure
  • Wed, June 14, 2017: Rapid7 reported vulnerability to MITRE

Merry HaXmas to you! Each year we mark the 12 Days of HaXmas with 12 blog posts on hacking-related topics and roundups from the year. This year, we’re highlighting some of the “gifts” we want to give back to the community. And while these gifts may not come wrapped with a bow, we hope you enjoy them.


Breaking Records and Breaking Business

2016 brought plenty of turmoil, and InfoSec was no exception:

  • Largest data breach: Largest breach ever, affecting more than 1 billion Yahoo users. And they were not alone: Oracle, LinkedIn, the Department of Justice, SnapChat, Verizon, DropBox, the IRS --- many organizations experienced, or discovered (or finally revealed the true extent of...), massive breaches this year.
  • Record-breaking denial of service attacks: law enforcement efforts targeting DDoS-as-a-Service providers are encouraging, but Mirai achieved record-breaking DDoS attacks this year. It turns out those easy-to-take-for-granted devices joining the Internet of Things in droves can pack quite a punch.
  • Ransomware: the end of 2015 saw a meteoritic rise in the prevalence of ransomware, and this continued in 2016. Healthcare and other targeted industries have faced 2-4x as many related attacks this year, some via increased coverage of ransomware in exploits kits, but mostly through plain old phishing.


Businesses and individuals continue to face new and increasing threats in keeping their essential systems and data secure. A static defense will not suffice: they must increase in both awareness and capability regularly in order to form a robust security program.


Metasploit Framework has grown in many ways during 2016, both through the broader community and through Rapid7 support. Let's look back through some of the highlights:


More exploits

A surprisingly wide range of exploits were added to Metasploit Framework in 2016:

  • Network management: NetGear, OpenNMS, webNMS, Dell, and more
  • Monitoring and backup: Nagios XI, Exagrid
  • Security: ClamAV, TrendMicro, Panda, Hak5 Pineapple, Dell SonicWall, Symantec -- and Metasploit itself!
  • Mainframes, SCADA dashboards
  • Exploit Kits: Dark Comet, Phoenix
  • ExtraBACON; StageFright
  • Content management/web applications: Joomla, TikiWiki, Ruby on Rails, Drupal, Wordpress forms
  • Docker, Linux kernel, SugarCRM, Oracle test suite, Apache Struts, exim, Postgres, and many more!


More flexibility

Metasploit Framework provides many supporting tools, aside from those designed to get a session on a target. These help in collecting information from a wide variety of systems, staying resilient to unknown and changing network environments, and looking like you belong.


Some expansions to the toolbox in 2016 included:


By the Numbers

Nearly 400 people have contributed code to Metasploit Framework during its history. And speaking of history: Metasploit Framework turned 13 this year! Long long ago, in a console (probably not too) far away:


Metasploit Framework 2.2 - 30 exploits


Has much changed in the last 12 years? Indeed!


Metasploit Framework 4.13.8 - 1607 exploits


In 2016, Metasploit contributors added over 150 new modules. Metasploit Framework's growth is powered by Rapid7, and especially by the community of users that give back by helping the project in a variety of ways, from landing pull requests to finding flags.


Topping the list of code contributors in 2016: Wei Chen (sinn3r), Brent Cook, William Vu (wvu), Dave Maloney (thelightcosine), h00die, OJ Reeves, nixawk, James Lee (egypt), Jon Hart, Tim Wright, Brendan Watters, Adam Cammack, Pedro Ribeiro, Josh Hale (sn0wfa11), and Nate Caroe (TheNaterz).


The Metasploit Framework GitHub project is approaching 4700 forks, and ranks in the top 10 for Ruby projects once again. It's also the second most starred security project on GitHub. None of this would have been possible if not for the dedication and drive of the Metasploit community. Together, we can continue to highlight flaws in existing systems, and better test the essential software of tomorrow. John Locke voiced in 1693 what open source security supporters continue to know well today: "The only fence against the world is a thorough knowledge of it."


So what about you?

The Metasploit RPC API provides a straightforward, programmatic way to accomplish basic tasks with your Metasploit Pro instance. Two of the key capabilities are export generation to backup your data and report generation to summarize and share your findings. The RPC API docs are currently undergoing a major overhaul and are a bit out of date for reports and export generation. This post will provide all the examples and configuration options you need to get running.


Setting up a client to make the API calls is simple:


# This class is defined under pro/api-example
require_relative 'metasploit_rpc_client'
client =, token:api_token, ssl:false, port:50505)


Note that there are example scripts shipped with Metasploit Pro that show these examples and more. They can be found inside the install directory (on *nix systems /opt/metasploit) under apps/pro/api-example. They are simple wrappers that allow you to pass in required arguments, so good for getting a feel for things. In addition to the API calling code, however you implement that, you need to have the Metasploit Pro instance running and you need to generate an API key. This can be done from Administration -> Global Settings.



Listing existing reports

report_list displays all reports that have been generated in the workspace you specify:


report_list ='pro.report_list', workspace_name)
puts "Existing Reports: #{report_list}"

Sample output:

Existing Reports: {7=>[{"id"=>6, "report_id"=>7, "file_path"=>"/Users/shuckins/rapid7/pro/reports/artifacts/CredentialMetaModule-20140912105153.pdf", 
"created_at"=>1410537159, "updated_at"=>1410537159, "accessed_at"=>nil, "workspace_id"=>2, "created_by"=>"shuckins", "report_type"=>"mm_auth", "file_size"=>34409}],

The keys of the Hash are the report IDs, needed for download as will be seen below. The value Array contains all the artifacts that were generated. An artifact is simply a particular file in a particular format. For example, when you generate an Audit report and select file formats PDF, HTML, and Doc, this results in a single report with three child artifacts.

Getting information on available reports to generate

type_list ='pro.list_report_types')
puts "Allowed Report types: #{type_list}"


Sample output (snipped, full output includes every report type):

Allowed Report types:
{"activity"=>{"required_data"=>"tasks", "file_formats"=>"pdf, html, rtf", "options"=>"include_task_logs",
"sections"=>"cover, project_summary, task_details", "report_directory"=>"/Users/shuckins/rapid7/pro/reports/activity/", "parent_template_file"=>"/Users/shuckins/rapid7/pro/reports/activity/main.jrxml"},


Downloading a report (all child artifacts)

report_id = 1 # Get this from report_list call
report ='pro.report_download', report_id)
report['report_artifacts'].each_with_index do |a, i|
    tmp_path = "/tmp/report_test_#{i}_#{}#{File.extname(a['file_path'])}", 'w') {|c| c.write a['data']}
    puts "Wrote report artifact #{report_id} to #{tmp_path}"


This will download every artifact related to this report generation (1-4 files depending on format selection).


Downloading particular report artifacts

If you only want a particular artifact file under a report, you can download that using the artifact ID provided from the report_list call.


report_artifact_id = 1
artifact ='pro.report_artifact_download', report_artifact_id)
tmp_path = "/tmp/report_#{report_artifact_id}#{File.extname(artifact['file_path'])}", 'w') {|c| c.write artifact['data']}
puts "Wrote report artifact #{report_artifact_id} to #{tmp_path}"


Generating a report

There are a number of options available for this call, detailed below. This basic version generates a single PDF artifact of the Audit report:

report_hash = {workspace: workspace_name,
               name: "SuperTest_#{}",
               report_type: :audit,
               created_by: 'whoareyou',
               file_formats: [:pdf]
report_creation ='pro.start_report', report_hash)
puts "Created report: #{report_creation}"

There's currently no API call to provide report (or export) generation status. The time required depends entirely on your data size and complexity. One place to check for status is the reports.log file.

Configuration options

These are placed in the hash passed to the start_report call.


  • name: String, the name for the report shown in the web UI and in the file path; used in forming the filenames of the artifacts generated
  • report_type: String, must be one of those listed by list_report_types, e.g.: activity, audit, credentials, collected_evidence, compromised_hosts, custom, fisma, mm_auth, mm_pnd, mm_segment, pci, services, social_engineering, webapp_assessment
  • report_template: if type 'custom' this can be set, String, full file path to custom Jasper jrxml template. If not a custom report, do not use this.
  • workspace_name: String, name of the workspace to which the report will be scoped
  • created_by: String, username to which the report should be attributed
  • file_formats: Array, the file format(s) of the artifacts to be generated. Must specify at least one. Available types vary slightly per report, 'pdf' is present for all. See list_report_types for formats per type.


  • email_recipients: String, addresses to which the report artifact(s) should be emailed. Addresses can be separated with comma, semicolon, newlines, or spaces.
  • mask_credentials: Boolean, whether credentials shown in report artifacts should be scrubbed (replaced with '*MASKED*')
  • included_addresses: String, space-separated addresses to include in the report. Can include wildcards, ranges, CIDR.
  • excluded_addresses: String, space-separated addresses to exclude from the report. Can include wildcards, ranges, CIDR. If included and excluded are both specified, they are both expanded and the address set used is included - excluded.
  • logo_path: String, full path to image file to use on cover page of report artifacts. If not specified, the Rapid7 logo is used. Must be of type: gif, png, jpg, or jpeg
  • options: sub hash of additional configuration options:
    • include_sessions: Boolean, whether information on sessions should be included in the report if applicable
    • include_charts: Boolean, whether graphs should be included in the report if applicable
    • include_page_code: Boolean, whether HTML code of pages in SE campaigns should be included in the report versus just an image preview of the rendered page
  • se_campaign_id: Integer, the ID of the SE campaign the report should cover. Only applied to SE report.
  • sections: Array, specific sections of the report to include. If this is specified only the specified sections will be included. If not specified all sections will be included. For section names, see list_report_types.
  • usernames_reported: String, comma-separated list of users to be included as active in the report. This is usually shown in the Executive summary section.


Export coverage is nearly identical to reports.

Listing existing exports

export_list ='pro.export_list', workspace_name)
puts "Existing Exports: #{export_list}"


Generating an export

export_types = ['zip_workspace','xml','replay_scripts','pwdump’]
# NOTE: If you are not on the latest update of 4.10 (4.10.0-2014092401) this requires workspace_id with integer value of ID.
# If you've updated to this point you can use workspace with a string value of name as below.
export_config = {created_by: 'whoareyou',
                           export_type: export_types[1],
                           workspace: 'ThePlace'}
export_creation ='pro.start_export', export_config)
puts "Created export: #{export_creation}"


Downloading a generated export

export_id = 1
export ='pro.export_download', export_id)
tmp_path = "/tmp/export_test_#{export_id}#{File.extname(export['file_path'])}", 'w') {|c| c.write export['data']}
puts "Wrote export #{export_id} to #{tmp_path}"


Configuration options


  • created_by: String, username to which the export should be attributed
  • export_type: String, must be one of: zip_workspace, xml, replay_scripts, pwdump
  • workspace: String, name of the workspace to which export will be scoped


  • name: String, the name for the export shown in the web UI and in the file path; unacceptable characters are changed to underscores or removed
  • mask_credentials: Boolean, whether credentials shown in XML and other files should be scrubbed (replaced with '*MASKED*')
  • included_addresses: String, space-separated addresses to include in the export. Can include wildcards, ranges, CIDR.
  • excluded_addresses: String, space-separated addresses to exclude from the export. Can include wildcards, ranges, CIDR. If included and excluded are both specified, they are both expanded and the address set used is included – excluded.

Filter Blog

By date: By tag: