SBN

Managing Scans using Bash and the Acunetix API

The Acunetix API allows you to programmatically manage your Acunetix tasks, including triggering scans for targets, checking the status of your scans, and retrieving a list of vulnerabilities found by your scans. This example can serve as a primer for building such programmatic tools.

In this example, you will create a Bash script that uses cURL to make requests to the Acunetix REST API.
Every API call must be authenticated by providing the API Key in the HTTP request headers. Therefore, each request is made with the following headers:

  • Content-Type: application/json
  • X-Auth: <the_api_key>

You can get the API key from the Acunetix profile page.

Anatomy of the Script

The script has the following structure:

  • The cleanup function is a recovery function to delete the scan and target created by the script if an invalid scan status is detected:
    • The remove_scan API call requires a DELETE request to the /scans/{scan_id} endpoint; the scan ID is retrieved during the main part of the script described below
    • The remove_target API call requires a DELETE request to the /targets/{target_id} endpoint; the target ID is retrieved during the main part of the script described below
  • The starting global variables are declared to be used throughout the script:
    • MyAXURL is the base URL for your Acunetix API, which is typically:
      • On-premises: https://:3443/api/v1
      • Online: https://online.acunetix.com/api/v1
    • MyAPIKEY is the API key, which can be retrieved from the profile page
    • MyTargetURL is the URL of the target to be scanned
    • MyTargetDESC is the friendly description for the target
    • FullScanProfileID is the profile ID for the default Full Scan; this default scan profile always has a value of 11111111-1111-1111-1111-111111111111
  • The target is created:
    • The API documentation for the add_target function shows that:
      • We have to make a POST request to the /targets endpoint
      • The body should be in JSON format minimally containing 4 keys: address, description, type, criticality; in our example:
        { "address": "http://testphp.vulnweb.com/",
        "description": "Test PHP Site - created via my script",
        "type": "default",
        "criticality": 10 }
        
      • The response will also be in JSON format; the critical information we want to extract from the response is the value of the target_id key
  • The scan is scheduled:
    • The API documentation for the schedule_scan function shows that:
      • We have to make a POST request to the /scans endpoint
      • The body should be in JSON format; in our example:
        { "profile_id": "11111111-1111-1111-1111-111111111111",
        "incremental": false,
        "schedule": { "disable": false,
                      "start_date": null,
                      "time_sensitive": false },
        "user_authorized_to_scan": "yes",
        "target_id": "TargetID_from_previous_step" }
        
      • The response will be in JSON format; the critical information (the scan ID) we want to extract, however, is not delivered in the response but in the HTTP response header called Location
  • A loop is created that checks the status of the scan every 30 seconds and waits for the scan status to become completed:
    • The API documentation for the get_scan function shows that:
      • We have to make a GET request to the /scans/{scan_id} endpoint, where the scan_id is obtained from the previous step
      • The response will be in JSON format; the critical information (the scan status) we want to extract is the value of the status key inside the nested JSON object with key current_session
      • If the scan status is processing or scheduled, the script continues to wait; when the scan status changes to completed, the script continues processing; if a scan status of one of these 3 values is not received, then the scan status is considered invalid and the cleanup function is called, and the script ends
  • We need to obtain the scan session ID; the response to the get_scan API call also contains the scan session ID; the critical information we want to extract is the value of the scan_session_id key inside the nested JSON object with key current_session
  • We need to obtain the Scan Result ID; to obtain the Scan Result ID:
    • The API documentation for the get_scan_result_history API call shows that:
      • We have to make a GET request to the /scans/{scan_id}/results endpoint, where the scan_id was obtained from a previous step
      • The response is in JSON format; the critical information (the scan result ID) we want to extract is the value of the result_id key inside one of the array of JSON objects forming the value for the results key; since the script creates a single scan for a single target, the situation is simplified such that we only expect to get a single JSON object nested inside the results key
  • We need to obtain the list of vulnerabilities generated by the scan:
    • The API documentation for the get_scan_vulnerabilities api call shows that:
      • We have to make a GET request to the /scans/{scan_id}/results/{result_id}/vulnerabilities endpoint, where the scan_id and the result_id were obtained from previous steps
      • The response is in JSON format and contains 2 keys:
        • The vulnerabilities key contains an array of all the vulnerabilities (up to 100) found for the scan scheduled previously
        • The pagination key contains information about the number of pages and how to retrieve subsequent pages in the case that the number of vulnerabilities is indeed more than 100

Bash Script

  1. #!/bin/bash
  2. # requires "jq" to be installed; on a debian system, uncomment the following line
  3. # apt install -y jq > /dev/null
  4. # Declare functions
  5. cleanup(){
  6. # delete the scan
  7. Dummy=`curl -sS -k -X DELETE "$MyAXURL/scans/{$MyScanID}" -H "Accept: application/json" -H "X-Auth: $MyAPIKEY"`
  8. # delete the target
  9. Dummy=`curl -sS -k -X DELETE "$MyAXURL/targets/{$MyTargetID}" -H "Accept: application/json" -H "X-Auth: $MyAPIKEY"`
  10. }
  11. # Declare Variables
  12. MyAXURL="https://qgen-004.qgengroup.local:3443/api/v1"
  13. MyAPIKEY="1986abcdefabcdefd7028d5f3c06e936c2a54cb301c8342b8b047b25985b4205f"
  14. MyTargetURL="http://testphp.vulnweb.com/"
  15. MyTargetDESC="Test PHP Site - created via ax-bash-api.sh"
  16. FullScanProfileID="11111111-1111-1111-1111-111111111111"
  17. # Create our intended target
  18. MyTargetID=`curl -sS -k -X POST $MyAXURL/targets -H "Content-Type: application/json" -H "X-Auth: $MyAPIKEY" --data "{"address":"$MyTargetURL","description":"$MyTargetDESC","type":"default","criticality":10}" | grep -Po '"target_id": *K"[^"]*"' | tr -d '"'`
  19. # Trigger a scan on the target
  20. MyScanID=`curl -i -sS -k -X POST $MyAXURL/scans -H "Content-Type: application/json" -H "X-Auth: $MyAPIKEY" --data "{"profile_id":"$FullScanProfileID","incremental":false,"schedule":{"disable":false,"start_date":null,"time_sensitive":false},"user_authorized_to_scan":"yes","target_id":"$MyTargetID"}" | grep "Location: " | sed "s/Location: /api/v1/scans///" | sed "s/r//g" | sed -z "s/n//g"`
  21. while true; do
  22. MyScanStatus=`curl -sS -k -X GET "$MyAXURL/scans/{$MyScanID}" -H "Accept: application/json" -H "X-Auth: $MyAPIKEY"`
  23. if [[ "$MyScanStatus" == *""status": "processing""* ]]; then
  24. echo "Scan Status: Processing - waiting 30 seconds"
  25. elif [[ "$MyScanStatus" == *""status": "scheduled""* ]]; then
  26. echo "Scan Status: Scheduled - waiting 30 seconds"
  27. elif [[ "$MyScanStatus" == *""status": "completed""* ]]; then
  28. echo "Scan Status: Completed"
  29. # Break out of loop
  30. break
  31. else
  32. echo "Invalid Scan Status: Aborting"
  33. # Clean Up and Exit script
  34. cleanup
  35. exit 1
  36. fi
  37. sleep 30
  38. done
  39. # Obtain the Scan Session ID
  40. MyScanSessionID=`echo "$MyScanStatus" | grep -Po '"scan_session_id": *K"[^"]*"' | tr -d '"'`
  41. # Obtain the Scan Result ID
  42. MyScanResultID=`curl -sS -k -X GET "$MyAXURL/scans/{$MyScanID}/results" -H "Accept: application/json" -H "X-Auth: $MyAPIKEY" | grep -Po '"result_id": *K"[^"]*"' | tr -d '"'`
  43. # Obtain Scan Vulnerabilities
  44. MyScanVulnerabilities=`curl -sS -k -X GET "$MyAXURL/scans/{$MyScanID}/results/{$MyScanResultID}/vulnerabilities" -H "Accept: application/json" -H "X-Auth: $MyAPIKEY"`
  45. echo
  46. echo "Target ID: $MyTargetID"
  47. echo "Scan ID: $MyScanID"
  48. echo "Scan Session ID: $MyScanSessionID"
  49. echo "Scan Result ID: $MyScanResultID"
  50. echo
  51. echo
  52. echo "Scan Vulnerabilities"
  53. echo "===================="
  54. echo
  55. echo $MyScanVulnerabilities | jq
THE AUTHOR
Kevin Attard Compagno
Technical Writer

Kevin Attard Compagno is a Technical Writer working for Acunetix. A technical writer, translator, and general IT buff for over 30 years, Kevin used to run Technical Support teams and create training documents and other material for in-house technical staff.


*** This is a Security Bloggers Network syndicated blog from Web Security Blog – Acunetix authored by Kevin Attard Compagno. Read the original post at: http://feedproxy.google.com/~r/acunetixwebapplicationsecurityblog/~3/GzTt4Td64Ek/