-
Notifications
You must be signed in to change notification settings - Fork 765
REST API
For server configuration please consult the relevant page.
Scans are identified by their IDs, a list of which can be retrieved with:
GET /scans
{
"02aa00c5c3ddb8c34a19e97c9a4e8db8" : {},
"2f0982cd68caa7fc46f56b07bd695cb8" : {}
}
Information about all active scans, grouped by their id
.
Currently no scan-related information is provided but that may change in the future.
Scans will run in parallel, each in its own process.
POST /scans
Default options are:
{
"url" : null,
"http" : {
"user_agent" : "Arachni/v2.0dev",
"request_timeout" : 10000,
"request_redirect_limit" : 5,
"request_concurrency" : 20,
"request_queue_size" : 100,
"request_headers" : {},
"response_max_size" : 500000,
"cookies" : {}
},
"audit" : {
"parameter_values" : true,
"exclude_vector_patterns" : [],
"include_vector_patterns" : [],
"link_templates" : []
},
"input" : {
"values" : {},
"default_values" : {
"(?i-mx:name)" : "arachni_name",
"(?i-mx:user)" : "arachni_user",
"(?i-mx:usr)" : "arachni_user",
"(?i-mx:pass)" : "5543!%arachni_secret",
"(?i-mx:txt)" : "arachni_text",
"(?i-mx:num)" : "132",
"(?i-mx:amount)" : "100",
"(?i-mx:mail)" : "[email protected]",
"(?i-mx:account)" : "12",
"(?i-mx:id)" : "1"
},
"without_defaults" : false,
"force" : false
},
"browser_cluster" : {
"wait_for_elements" : {},
"pool_size" : 6,
"job_timeout" : 25,
"worker_time_to_live" : 100,
"ignore_images" : false,
"screen_width" : 1600,
"screen_height" : 1200
},
"scope" : {
"redundant_path_patterns" : {},
"dom_depth_limit" : 5,
"exclude_path_patterns" : [],
"exclude_content_patterns" : [],
"include_path_patterns" : [],
"restrict_paths" : [],
"extend_paths" : [],
"url_rewrites" : {}
},
"session" : {},
"checks" : [],
"platforms" : [],
"plugins" : {},
"no_fingerprinting" : false,
"authorized_by" : null
}
- Only the
url
option is mandatory. - These options are passed to Arachni::Options#update.
- Options expecting a type of
Regexp
(unavailable in JSON) can be specified as typeString
.- The string should not be enclosed in
/
; for example, usetest.*
instead of/test.*/
.
- The string should not be enclosed in
Currently, the response only contains the scan's ID.
{
"id" : "1a34b6aca50bcf0065aca0a06a8d21ba"
}
A 500
error will be returned on invalid options:
{
"error" : "Arachni::RPC::Exceptions::RemoteException: undefined method `stuff=' for #<Arachni::Options:0x00000001fa0dd8>",
"backtrace" : [
"/home/zapotek/workspace/arachni/lib/arachni/options.rb:276:in `block in update'",
"/home/zapotek/workspace/arachni/lib/arachni/options.rb:271:in `each'",
"/home/zapotek/workspace/arachni/lib/arachni/options.rb:271:in `update'",
"/home/zapotek/workspace/arachni/lib/arachni/rpc/server/active_options.rb:34:in `set'",
"/home/zapotek/workspace/arachni/lib/arachni/rpc/server/instance.rb:584:in `scan'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-rpc-0.2.1.2/lib/arachni/rpc/server.rb:207:in `call'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-rpc-0.2.1.2/lib/arachni/rpc/server/handler.rb:57:in `receive_request'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-rpc-0.2.1.2/lib/arachni/rpc/server/handler.rb:96:in `receive_object'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-rpc-0.2.1.2/lib/arachni/rpc/protocol.rb:52:in `on_read'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor/connection.rb:255:in `block in _read'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor/connection/error.rb:26:in `call'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor/connection/error.rb:26:in `translate'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor/connection.rb:254:in `_read'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor/connection/tls.rb:115:in `_read'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:574:in `each'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:574:in `block in process_connections'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:574:in `each'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:574:in `process_connections'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:316:in `block in run'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:307:in `loop'",
"/home/zapotek/.rvm/gems/ruby-2.2.0/gems/arachni-reactor-0.1.0/lib/arachni/reactor.rb:307:in `run'",
"/home/zapotek/workspace/arachni/lib/arachni/rpc/server/instance.rb:152:in `initialize'",
"/home/zapotek/workspace/arachni/lib/arachni/processes/executables/instance.rb:13:in `new'",
"/home/zapotek/workspace/arachni/lib/arachni/processes/executables/instance.rb:13:in `<top (required)>'",
"/home/zapotek/workspace/arachni/lib/arachni/processes/executables/base.rb:9:in `load'",
"/home/zapotek/workspace/arachni/lib/arachni/processes/executables/base.rb:9:in `<main>'"
]
}
GET /scans/:id
{
"status": "scanning",
"busy": true,
"seed": "c0c039750bef4f5688da4fba929b06ac",
"statistics": {
"http": {
"request_count": 1312,
"response_count": 1208,
"time_out_count": 0,
"total_responses_per_second": 145.55173283136,
"burst_response_time_sum": 0,
"burst_response_count": 0,
"burst_responses_per_second": 0,
"burst_average_response_time": 0,
"total_average_response_time": 0.12118887582781,
"max_concurrency": 20,
"original_max_concurrency": 20
},
"browser_cluster": {
"seconds_per_job": 1.6666666666667,
"total_job_time": 25,
"queued_job_count": 31,
"completed_job_count": 15
},
"runtime": 9.251885252,
"found_pages": 10,
"audited_pages": 2,
"current_page": "http:\/\/testhtml5.vulnweb.com\/ajax\/popular?offset=0"
},
"errors": [],
"messages": [],
"issues": [],
"sitemap": {}
}
-
status
can be:-
ready
-- Initialised and waiting for instructions. -
preparing
-- Getting ready to start (i.e. initializing plugins etc.). -
scanning
-- The instance is currently scanning the webapp. -
pausing
-- The instance is being paused. -
paused
-- The instance has been paused. -
cleanup
-- The scan has completed and the instance is cleaning up after itself (i.e. waiting for plugins to finish etc.). -
aborted
-- The scan has been aborted, you can grab the report and shutdown. -
done
-- The scan has completed, you can grab the report and shutdown.
-
-
busy
-
true
-- The scan is still in progress. -
false
-- The scan has finished, it is safe to grab the report and shutdown.
-
-
errors
-- Recoverable runtime errors. -
issues
-- Identified issues. -
sitemap
-- Scanned pages by URL and their HTTP status code.-
url
:code
-
-
messages
-- Status messages.
So long as the client maintains a session with the service, only new issues
, sitemap
entries and errors
will be returned.
If no session is being maintained, each call will always return all data.
Returns the same data as "Monitor scan progress" but without issues
, errors
and sitemap
.
GET /scans/:id/summary
{
"status": "scanning",
"busy": true,
"seed": "c0c039750bef4f5688da4fba929b06ac",
"statistics": {
"http": {
"request_count": 1312,
"response_count": 1208,
"time_out_count": 0,
"total_responses_per_second": 145.55173283136,
"burst_response_time_sum": 0,
"burst_response_count": 0,
"burst_responses_per_second": 0,
"burst_average_response_time": 0,
"total_average_response_time": 0.12118887582781,
"max_concurrency": 20,
"original_max_concurrency": 20
},
"browser_cluster": {
"seconds_per_job": 1.6666666666667,
"total_job_time": 25,
"queued_job_count": 31,
"completed_job_count": 15
},
"runtime": 9.251885252,
"found_pages": 10,
"audited_pages": 2,
"current_page": "http:\/\/testhtml5.vulnweb.com\/ajax\/popular?offset=0"
},
"messages": []
}
This is a soft pause, it will not kill the scanner process but merely make it wait for a resume signal in order to continue the scan.
PUT /scans/:id/pause
PUT /scans/:id/resume
GET /scans/:id/report
GET /scans/:id/report.json
GET /scans/:id/report.xml
GET /scans/:id/report.yaml
GET /scans/:id/report.html.zip
When the extension is missing, it will default to json
.
DELETE /scans/:id
This call needs to take place after each scan is done in order to prevent zombie processes.
Once that call is made, the scan process will be killed and removed from the service, if you wish to retrieve the report you will need to do so prior to performing this call.
#!/usr/bin/env ruby
require 'ap'
require 'typhoeus'
require 'json'
# Base URL of the REST service.
URL = 'http://localhost:7331'
# Cookie-Jar for the session.
#
# Allows for optimizations such as scan progress calls only returning issues not
# previously seen by previous calls, instead of all issues every single time.
COOKIE_JAR = '/tmp/arachni_rest_client.cookiejar'
#
# HTTP helpers
###############
def request( path, options = {} )
if (data = options.delete(:data))
options[:body] = JSON.dump( data )
end
response = Typhoeus::Request.new(
"#{URL}/#{path}",
options.merge(
# Maintain a session.
cookiefile: COOKIE_JAR,
cookiejar: COOKIE_JAR,
# Enable compression.
accept_encoding: 'gzip, deflate',
)
).run
fail response.return_message if response.code == 0
JSON.load( response.body )
end
def get( path )
request( path )
end
def post( path, data = nil )
request( path, data: data, method: :post )
end
def delete( path )
request( path, method: :delete )
end
#
# Usage example
###############
# Start a new scan with the given options.
#
# The `id` included in the response data will allow us to manage it.
id = post( '/scans',
url: 'http://testhtml5.vulnweb.com',
# Only scan a few pages.
scope: {
page_limit: 10
},
audit: {
elements: ['link', 'form', 'cookie']
},
# Load all checks.
checks: ['*']
)['id']
# Poll until the scan is finished.
loop do
print '.'
# Get the scan's progress.
#
# Status messages, runtime statistics, new issues, new errors etc.
progress = get( "/scans/#{id}" )
# Status messages (initializing something, pausing in a bit, etc.).
if progress['messages'].any?
puts
puts 'Messages:'
puts progress['messages'].join( "\n" )
end
# Because we're maintaining a session with the REST server, only issues
# which have not been previously seen will be returned by each call.
if progress['issues'].any?
puts
puts 'Issues:'
progress['issues'].each do |issue|
summary = "#{issue['name']} in '#{issue['vector']['type']}'"
# Passive issues don't have this.
if issue['affected_input_name']
summary << " input '#{issue['affected_input_name'].inspect}'"
summary << " using #{issue['affected_input_value'].inspect}"
end
summary << " at: #{issue['page']['dom']['url']}"
puts summary
end
end
# Same thing as before, only new sitemap entries will be returned for each call.
if progress['sitemap'].any?
puts
puts 'Scanned pages:'
progress['sitemap'].each do |url, code|
puts "[#{code}] #{url}"
end
end
# Same thing as before, only new errors will be returned for each call.
if progress['errors'].any?
puts
puts 'Errors:'
puts progress['errors'].join( "\n" )
end
# When `busy` is set to `false`, it means that the scan has completed.
break if !progress['busy']
sleep 1
end
puts
# Get the full scan report.
ap get( "/scans/#{id}/report" )
# Get a list of all living scan processes, of course, it will include ours.
puts 'Scan list:'
ap get( '/scans' )
# Since we're done with this one, kill it.
#
# Don't forget this, we don't want any zombie processes laying around.
print 'Shutting down scan...'
delete "/scans/#{id}"
puts '... done!'
# Lo and behold, our scan is no longer listed.
puts 'Scan list:'
ap get( '/scans' )
Pages [all]
Can't find what you're looking for? Why not have a look at the support portal?