An API is essential for any useful product. It allows developers to expand on something that already has value. In this post I'll be explaining some use cases for the ControlsInsight REST API (v1.0). I'll also be showing what information you can pull in from the API and explain how to get started using the Ruby client.

Documentation

Resources

These endpoints should be appended to your Nexpose console's address (i.e. https://nexpose.local:3780. The endpoints below are in the format of RFC 6570 - URI Templates.

  • Resource/URL listing:                  /insight/controls/api/1.0/
  • Assessments endpoint:               /insight/controls/api/1.0/assessments{/assessment_id}
  • Assets endpoint:                         /insight/controls/api/1.0/assets/{asset_uuid}
  • Guidance endpoint:                    /insight/controls/api/1.0/guidance/{guidance}
  • Threats endpoint:                       /insight/controls/api/1.0/threats{/threat_name}
  • Threat Vectors endpoint:            /insight/controls/api/1.0/threat_vectors{/vector_name}
  • Security Controls endpoint:       /insight/controls/api/1.0/security_controls{/control_name}
  • Configurations endpoint:           /insight/controls/api/1.0/configurations{/configuration_name}

It's also worth noting that /uncovered_assets, /misconfigured_assets, /undefended_assets, and /prioritized_guidance are unique in that they can be appended to a threat/threat_vector/security_control/configuration URLs to get either prioritized guidance or uncovered/misconfigured/undefended assets.

Use Cases

  • Automation (a few scripts are included below)
  • Metasploit Integration, on the way!

Ruby Client

Installation

Ruby versions 1.9.3 and greater (2.0.0 is better!) are what the gem supports today. To manage your ruby versions the recommended way would be installing RVM: Ruby Version Manager. After you have an up to date version of Ruby installed you can simply run:

gem install --pre controls  # Install the latest version of the gem, including prerelease versions  
irb -r controls             # Open up an interative Ruby REPL  

Usage

To authenticate create a new client instance like so:

client = Controls::Client.new(  
  verify_ssl: false,                                                      # Allow Nexpose's self-signed certificate and authenticate with ControlsInsight  
  username: 'johndoe',                                                    # The user to authenticate with   
  password: 'P@s$w0rD123',                                                # The password to authenticate with  
  api_endpoint: 'https://nexpose.local:3780/insight/controls/api/1.0',  
  web_endpoint: 'https://nexpose.local:3780/insight/controls'  
)  

Post-authentication check that the client is working by running a test call:

client.assessments  
# => [  
#      {"id"=>1, "timestamp"=>1380030655328, "highRiskAssetCount"=>169, "mediumRiskAssetCount"=>0, "lowRiskAssetCount"=>0, "totalAssetCount"=>169, "overallRiskScore"=>1.9621629169050667, "assessing"=>false, "url"=>"https://nexpose.local:3780/insight/controls/api/1.0/assessments/1"},  
#      {"id"=>2, "timestamp"=>1380033682843, "highRiskAssetCount"=>169, "mediumRiskAssetCount"=>0, "lowRiskAssetCount"=>0, "totalAssetCount"=>169, "overallRiskScore"=>1.9621629169050667, "assessing"=>false, "url"=>"https://nexpose.local:3780/insight/controls/api/1.0/assessments/2"},  
#      {"id"=>3, "timestamp"=>1380038017343, "highRiskAssetCount"=>169, "mediumRiskAssetCount"=>0, "lowRiskAssetCount"=>0, "totalAssetCount"=>169, "overallRiskScore"=>1.9621629169050667, "assessing"=>false, "url"=>"https://nexpose.local:3780/insight/controls/api/1.0/assessments/3"}  
#    ]  

Proof of Concept Scripts

Assessment Monitoring

Monitoring assessments through the web console for ControlsInsight requires knowing about the Nexpose scan's run/integration time. Once Nexpose has finished scanning you'll be able to see results in ControlsInsight given that the assessment has finished. To continuously see the status of your latest assessment you can do the following near the end of a scan.

# To tell the status of the last assessment:  
assessment = client.assessments.last  
# => {  
#      "id"=>1,  
#      "timestamp"=>1380030655328,  
#      "highRiskAssetCount"=>169,  
#      "mediumRiskAssetCount"=>0,  
#      "lowRiskAssetCount"=>0,  
#      "totalAssetCount"=>169,  
#      "overallRiskScore"=>1.9621629169050667,  
#      "assessing"=>false,  
#      "url"=>"https://nexpose.local:3780/insight/controls/api/1.0/assessments/1"  
#    }  
  
assessment['assessing']  
# => false  
  
# Update the assessment while it is assessing  
until assessment['assessing'].eql?(true)  
  sleep 15  
  assessment = client.assessments(assessment['id'])  
puts JSON.pretty_generate(assessment)  
end  

Trending is a great feature to have and in the UI we've started to implement features such as deltas that show the improvement between two assessments. How can you show improvement over a different period of time now though? Simple enough, use the /assessments endpoint. This example assumes you've installed and loaded the "colorize" gem or added my string extensions from this gist.

assessments = client.assessments  
assessments.each do |assessment|  
  risk_color = if assessment['overallRiskScore'] <= 3  
   :red  
  elsif assessment['overallRiskScore'] <= 6  
   :yellow  
  else  
   :green  
  end  
  
  puts "Assessment #{ "%02d" % assessment['id'] } #{ assessment['assessing'] ? '(started) '.cyan : '(completed)'.green } on %s %s" % [Time.at(assessment['timestamp'] / 1000).strftime("%X - %b %d %Y"), ('#' * (assessment['overallRiskScore'] * 10)).send(risk_color)]  
end  

If all goes well you should see information about your assessments and a pretty color coded bar chart like so: