Firebind Recon RESTful API

Recon API – cURL Client Quickstart

cURL Basics

Authentication

Firebind utilizes Auth0 for authentication services. Auth0 implements OAuth2 authentication flows for token-based authentication.

Log in to the Firebind API via Auth0 to obtain an access token. You will need values for client_id and client_secret which are available from Firebind.

curl -s --request POST --url https://recon-production.auth0.com/oauth/token   --header 'content-type: application/json'   --data '{"client_id":"<CLIENT-ID>","client_secret":"<CLIENT-SECRET>","audience":"https://production-api.firebind.com","grant_type":"client_credentials"}'

A successful response will look like this:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCI2ImtpZCI6Ik9UWXdOemhHTXpZM1FrVXlPRGRFTkVKQ05qVXdPRGw4T0VOR01UHBzOi8vcHJvZHVjdGlvbi1hcGk5ZmlyZWJpbmQuY29tIiwiaWF0IjoxNTgyNDAwNzY1LCJleHAiOgE1ODI0ODcxNjUsIm86cCI6IlljQlFWRzIwc0pyd3Uu-ZGSyhelu4ePDGvBV2m6InzDY2qfO687dhqlQM-Mpd6x9LRjCdWBUTTyuVf5UeCGTXOcAHFG4Z9c5w0Tqnisdozw", 
  "expires_in": 86400, 
  "token_type": "Bearer"
}

The access_token field is what we’ll need to supply to the Firebind Recon API for authentication. For convenience we can save it in an environment variable like this:

export TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCI2ImtpZCI6Ik9UWXdOemhHTXpZM1FrVXlPRGRFTkVKQ05qVXdPRGw4T0VOR01UHBzOi8vcHJvZHVjdGlvbi1hcGk5ZmlyZWJpbmQuY29tIiwiaWF0IjoxNTgyNDAwNzY1LCJleHAiOgE1ODI0ODcxNjUsIm86cCI6IlljQlFWRzIwc0pyd3Uu-ZGSyhelu4ePDGvBV2m6InzDY2qfO687dhqlQM-Mpd6x9LRjCdWBUTTyuVf5UeCGTXOcAHFG4Z9c5w0Tqnisdozw"

We’ll use this environment variable to pass the token for each API call. Note that the token will expire in 24 hours (86400 seconds).

Listing Agents

Obtain a list of your agents with the /agent endpoint as such:

curl -s -H "Authorization: Bearer $TOKEN" 'https://api.firebind.com/v1/agent'

Notice the use of the $TOKEN environment variable in the authorization header, this is the token obtained during the previous Log In step and must be present on every API call. You can also ask for a specific agent by ID like this:

curl -s -H "Authorization: Bearer $TOKEN" 'https://api.firebind.com/v1/agent/RHV3X93G37EN69E5ZRTLGTYRL8'

Output

The agent object is listed in the output, an example looks like this:

{
  "source" : {
    "id" : "8c239bc0-55ad-11ea-9af6-b772bdeea622",
    "name" : "Sector 4",
    "description" : "AFC Area 51 sector 4 subnet 37",
    "enabled" : false,
    "address" : "100.17.17.248",
    "listening" : false,
    "lastActive" : 1582401340670,
    "lastScanStart" : 1574695052143,
    "nextScanStart" : 1573194900000,
    "reflectorId" : "RHV3X93G37EN69E5ZRTLGTYRL8",
    "version" : "2.0.6",
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "echoAddressStrategy" : "ANY",
    "echoAddress" : "192.168.125.121",
    "controlPort" : 8080,
    "useTls" : false,
    "listenConfig" : "NONE",
    "listenState" : "NO_LISTEN",
    "interfaces" : [ {
      "address" : "192.168.125.121"
    } ],
    "pollInterval" : 15,
    "state" : "ONLINE",
    "programArguments" : "-stdout -b api.firebind.com RHV3X93G37EN69E5ZRTLGTYRL8",
    "jvmArguments" : "-Djava.net.preferIPv4Stack=true -Xmx256m",
    "hostDetails" : "Linux 4.19.66-v7+ arm 'raspberrypi' 4 processors",
    "dnsServers" : "71.250.0.12,192.168.125.1",
    "sendEmailOnMia" : false,
    "locale" : "English (United States)",
    "fileEncoding" : "UTF-8",
    "created" : 1570661019349,
    "registered" : 1570661105412
  },
  "properties" : {
    "lastActivityText" : "4s ago"
  },
  "statusCode" : 200
}

Listing Scans

Obtain a list of your defined scans with the /scan endpoint like this:

curl -s -H "Authorization: Bearer $TOKEN" 'https://api.firebind.com/v1/scan'

The response looks like this:

{
  "source" : [ {
    "id" : "e350156c-55ae-11ea-b6fe-337a639c9dca",
    "name" : "US4.5 Nevada > US East - All 64k T/U Simple 4s TO 250ms S4",
    "description" : "CVE-2014-6271 (ShellShock) for unit 4 subnet 37",
    "suiteCode" : "be5564ba-55ae-11ea-af6f-3bb4fc04a887",
    "initiatorReflectorId" : "RHV3X93G37EN69E5ZRTLGTYRL8",
    "initiatorReflectorInterfaceAddress" : "ANY",
    "initiatorReflectorAddressPattern" : null,
    "targetReflectorId" : "R_FIREBIND_USAF55_T51",
    "targetClusterCode" : "US_EAST_17",
    "code" : "b7a253d0-55ae-11ea-b7f7-db4569e22be8",
    "cron" : "0 * * * * *",
    "enabled" : true,
    "policyCodes" : ["27005d6c-55af-11ea-8237-17f3c0b43e46"],
    "emailOnAlarm" : false,
    "qualificationCount" : 1,
    "resendInterval" : 7,
    "ondemand" : false,
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "message" : "qualify b7a253d0-55ae-11ea-b7f7-db4569e22be8: FAIL - (initiatorEnabledCheck) initiator RHV3X93G37EN69E5ZRTLGTYRL8/Sector 4 is disabled"
  } ],
  "statusCode" : 200
}

Here we can see a scan from an agent based in Nevada to the Firebind US East target cluster (#17 in Virginia). The scan is configured to run every minute (at second 0), will execute a Suite simulating ShellShock malicious exploits, and has an associated Policy that alarms on non-compliant results. Note however, the agent associated with the Scan is disabled.

Issuing a Scan

To start a scan (e.g. the Scan Now feature available on the Firebind Recon Web Console) use the /scan/start endpoint. For this operation the HTTP PUT method is required, the command looks like this:

curl -s -H "Authorization: Bearer $TOKEN" -XPUT 'https://api.firebind.com/v1/scan/start/b7a253d0-55ae-11ea-b7f7-db4569e22be8'

A successful response looks like this:

{
  "source" : {
    "message" : "Scan 'US4.5 Nevada > US East - All 64k T/U Simple 4s TO 250ms S4' has been issued at 02/19/2019 15:16:55 -0500",
    "resultId" : "03710122-55b3-11ea-9026-2b6cc8b7959b"
  },
  "status" : "OK",
  "statusCode" : 200
}

Viewing Results

To view the results of a scan, use the /result endpoint. Issue a HTTP GET request that supplies the resultId from the Scan issue response (see above) like this:

curl -s -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" 'https://api.firebind.com/v1/result/03710122-55b3-11ea-9026-2b6cc8b7959b'

The response contains all information about how the scan performed. This includes the particulars of the endpoints, protocols, transports, and the results of the wire activity. The example output below shows the issued scan in-progress at 19%, running a Shellshock payload. In this case the network path (and all security controls) allows complete passage of the malicious payload – unsecured endpoints receiving this payload would be affected.

{
  "source" : {
    "id" : "03710122-55b3-11ea-9026-2b6cc8b7959b",
    "start" : 1582403935138,
    "end" : 0,
    "lastActivity" : 1582403946833,
    "remoteAddress" : "R_FIREBIND_USAF55_T51.firebind.com:443",
    "serverAddress" : "R_FIREBIND_USAF55_T51.firebind.com:443",
    "initiatorReflectorId" : "R_FIREBIND_USAF55_T51",
    "initiatorReflectorName" : "Sector 4",
    "targetReflectorId" : "R_FIREBIND_USAF55_T51",
    "targetReflectorName" : "USAF55 Target 51 remote 5.3117",
    "targetReflectorClusterName" : "Firebind US EAST (Virginia)",
    "targetReflectorClusterCode" : "US_EAST_17",
    "targetReflectorEchoAddress" : "R_FIREBIND_USAF55_T51.firebind.com",
    "tag" : "Scan now request",
    "records" : [ {
      "complete" : false,
      "guid" : 178414533,
      "componentName" : "Shellshock TCP 50,000 to 50,100",
      "componentCode" : "20010836-55b4-11ea-b0d9-2b007cf84189",
      "percent" : 19,
      "componentStart" : 1582403936898,
      "componentStop" : 0,
      "error" : false,
      "tcpList" : "50000-50100",
      "tcpListCount" : 101,
      "udpList" : null,
      "udpListCount" : 0,
      "timeout" : 4000,
      "scriptCode" : "322246f6-55b4-11ea-b21c-0f1421dafb1e",
      "scriptName" : "Shellshock",
      "portDelay" : 250,
      "tcpGuid" : 1873,
      "tcpOpen" : "50000-50019",
      "tcpOpenCount" : 20,
      "tcpClosed" : "",
      "tcpClosedCount" : 0,
      "tcpResults" : {
        "12110" : "50000-50019"
      },
      "tcpComplete" : false,
      "udpGuid" : 0,
      "udpOpen" : null,
      "udpOpenCount" : 0,
      "udpClosed" : null,
      "udpClosedCount" : 0,
      "udpResults" : null,
      "udpComplete" : true
    } ],
    "originalSuiteSize" : 1,
    "suiteCode" : "4067e572-55b4-11ea-8cdb-4fe02fea115d",
    "suiteName" : "Shellshock TCP 50,000 to 50,100",
    "configName" : "US4.5 Nevada > US East - All 64k T/U Simple 4s TO 250ms S4",
    "configCode" : "b7a253d0-55ae-11ea-b7f7-db4569e22be8",
    "complete" : false,
    "percent" : 19,
    "state" : "RUN",
    "alarm" : false,
    "error" : false,
    "errorMessage" : null,
    "description" : null,
    "number" : 0,
    "suiteId" : null,
    "name" : null,
    "code" : null,
    "externalServerAddress" : null,
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "recordsInError" : [ ]
  },
  "properties" : {
    "alarms" : [ ]
  },
  "statusCode" : 200
}

Note the complete and percent fields. When the scan has completed the complete field will be true and the percent will be 100. A continued poll of this endpoint will show progress as the agent completes its conversation with the target. Results will update along the way.

Recon API – Python Client Quickstart

For this example, we will write a Python client for the Firebind Recon API. We will use the Python requests and json modules to interact and print our work.

Authentication

Lets start with a basic API object and a simple authentication method, like this:

import requests, json

class ReconAPI:
    token = None
    def authenticate(self):
        response = requests.post('https://recon-production.auth0.com/oauth/token', json={
            "client_id":"<CLIENT_ID>",
            "client_secret":"<CLIENT_SECRET>",
            "audience":"https://production-api.firebind.com",
            "grant_type":"client_credentials"
        })
        self.token = response.json()['access_token']

if __name__ == '__main__':
    api = ReconAPI()
    api.authenticate()
    

Be sure to specify your CLIENT_ID and CLIENT_SECRET. These are available from Firebind. This program will authenticate to the Firebind API (via Auth0) and save the access token for our next steps.

Listing Agents

Obtain a list of your agents with the /agent endpoint, we will add this call with a new list_agents() method:

import requests, json

class ReconAPI:
    token = None
    def authenticate(self):
        response = requests.post('https://recon-production.auth0.com/oauth/token', json={
            "client_id":"<CLIENT_ID>",
            "client_secret":"<CLIENT_SECRET>",
            "audience":"https://production-api.firebind.com",
            "grant_type":"client_credentials"
        })
        self.token = response.json()['access_token']

    def list_agents(self):
        return requests.get('https://api.firebind.com/v1/agent',
            headers={
                'Authorization': 'Bearer {}'.format(self.token)
            }).json()

if __name__ == '__main__':
    api = ReconAPI()
    api.authenticate()
    print(json.dumps(api.list_agents(), indent=2))
    

Output

The agent object is listed in the output, an example looks like this:

{
  "source" : {
    "id" : "8c239bc0-55ad-11ea-9af6-b772bdeea622",
    "name" : "Sector 4",
    "description" : "AFC Area 51 sector 4 subnet 37",
    "enabled" : false,
    "address" : "100.17.17.248",
    "listening" : false,
    "lastActive" : 1582401340670,
    "lastScanStart" : 1574695052143,
    "nextScanStart" : 1573194900000,
    "reflectorId" : "RHV3X93G37EN69E5ZRTLGTYRL8",
    "version" : "2.0.6",
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "echoAddressStrategy" : "ANY",
    "echoAddress" : "192.168.125.121",
    "controlPort" : 8080,
    "useTls" : false,
    "listenConfig" : "NONE",
    "listenState" : "NO_LISTEN",
    "interfaces" : [ {
      "address" : "192.168.125.121"
    } ],
    "pollInterval" : 15,
    "state" : "ONLINE",
    "programArguments" : "-stdout -b api.firebind.com RHV3X93G37EN69E5ZRTLGTYRL8",
    "jvmArguments" : "-Djava.net.preferIPv4Stack=true -Xmx256m",
    "hostDetails" : "Linux 4.19.66-v7+ arm 'raspberrypi' 4 processors",
    "dnsServers" : "71.250.0.12,192.168.125.1",
    "sendEmailOnMia" : false,
    "locale" : "English (United States)",
    "fileEncoding" : "UTF-8",
    "created" : 1570661019349,
    "registered" : 1570661105412
  },
  "properties" : {
    "lastActivityText" : "4s ago"
  },
  "statusCode" : 200
}

Listing Scans

Obtain a list of your scans with the /scan endpoint, we will add this call with a new list_scans() method:

import requests, json

class ReconAPI:
    token = None
    def authenticate(self):
        response = requests.post('https://recon-production.auth0.com/oauth/token', json={
            "client_id":"<CLIENT_ID>",
            "client_secret":"<CLIENT_SECRET>",
            "audience":"https://production-api.firebind.com",
            "grant_type":"client_credentials"
        })
        self.token = response.json()['access_token']

    def list_agents(self):
        return requests.get('https://api.firebind.com/v1/agent',
            headers={
                'Authorization': 'Bearer {}'.format(self.token)
            }).json()
            
    def list_scans(self):
        return requests.get('https://api.firebind.com/v1/scan', 
            headers={
                'Authorization': 'Bearer {}'.format(self.token)
            }).json()

if __name__ == '__main__':
    api = ReconAPI()
    api.authenticate()
    print(json.dumps(api.list_agents(), indent=2))
    print(json.dumps(api.list_scans(), indent=2))
    

The response looks like this:

{
  "source" : [ {
    "id" : "e350156c-55ae-11ea-b6fe-337a639c9dca",
    "name" : "US4.5 Nevada > US East - All 64k T/U Simple 4s TO 250ms S4",
    "description" : "CVE-2014-6271 (ShellShock) for unit 4 subnet 37",
    "suiteCode" : "be5564ba-55ae-11ea-af6f-3bb4fc04a887",
    "initiatorReflectorId" : "RHV3X93G37EN69E5ZRTLGTYRL8",
    "initiatorReflectorInterfaceAddress" : "ANY",
    "initiatorReflectorAddressPattern" : null,
    "targetReflectorId" : "R_FIREBIND_USAF55_T51",
    "targetClusterCode" : "US_EAST_17",
    "code" : "b7a253d0-55ae-11ea-b7f7-db4569e22be8",
    "cron" : "0 * * * * *",
    "enabled" : true,
    "policyCodes" : ["27005d6c-55af-11ea-8237-17f3c0b43e46"],
    "emailOnAlarm" : false,
    "qualificationCount" : 1,
    "resendInterval" : 7,
    "ondemand" : false,
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "message" : "qualify b7a253d0-55ae-11ea-b7f7-db4569e22be8: FAIL - (initiatorEnabledCheck) initiator RHV3X93G37EN69E5ZRTLGTYRL8/Sector 4 is disabled"
  } ],
  "statusCode" : 200
}

Here we can see a scan from an agent based in Nevada to the Firebind US East target cluster (#17 in Virginia). The scan is configured to run every minute (at second 0), will execute a Suite simulating ShellShock malicious exploits, and has an associated Policy that alarms on non-compliant results. Note however, the agent associated with the Scan is disabled.

Starting a Scan

Start a new scan with a PUT request to the /scan/start endpoint, we will add this call with a new start_scan() method:

import requests, json

class ReconAPI:
    token = None
    def authenticate(self):
        self.token = requests.post('https://recon-production.auth0.com/oauth/token', 
        json={
            "client_id":"<CLIENT_ID>",
            "client_secret":"<CLIENT_SECRET>",
            "audience":"https://production-api.firebind.com",
            "grant_type":"client_credentials"
        }).json()['access_token']

    def list_agents(self):
        return requests.get('https://api.firebind.com/v1/agent',
            headers={
                'Authorization': 'Bearer {}'.format(self.token)
            }).json()
            
    def list_scans(self):
        return requests.get('https://api.firebind.com/v1/scan', 
            headers={
                'Authorization': 'Bearer {}'.format(self.token) 
            }).json()
    
    def start_scan(self):
        self.scan_id = requests.put(
            'https://api.firebind.com/v1/scan/start/b7a253d0-55ae-11ea-b7f7-db4569e22be8', 
            headers={
                'Authorization': 'Bearer {}'.format(self.token) 
            }).json()['source']['resultId']

    
if __name__ == '__main__':
    api = ReconAPI()
    api.authenticate()
    print(json.dumps(api.list_agents(), indent=2))
    print(json.dumps(api.list_scans(), indent=2))
    api.start_scan()
    

Note that here we are saving the scan result ID so we can retrieve the results in the next step.

Viewing Results

To view the results of a scan, we will add a get_results() method that issues a HTTP GET request that supplies the resultId from the Scan issue response (see above) like this:

import requests, json

class ReconAPI:
    token = None
    def authenticate(self):
        self.token = requests.post('https://recon-production.auth0.com/oauth/token', 
        json={
            "client_id":"<CLIENT_ID>",
            "client_secret":"<CLIENT_SECRET>",
            "audience":"https://production-api.firebind.com",
            "grant_type":"client_credentials"
        }).json()['access_token']

    def list_agents(self):
        return requests.get('https://api.firebind.com/v1/agent',
            headers={
                'Authorization': 'Bearer {}'.format(self.token)
            }).json()
            
    def list_scans(self):
        return requests.get('https://api.firebind.com/v1/scan', 
            headers={
                'Authorization': 'Bearer {}'.format(self.token) 
            }).json()
    
    def start_scan(self):
        self.scan_id = requests.put(
            'https://api.firebind.com/v1/scan/start/b7a253d0-55ae-11ea-b7f7-db4569e22be8', 
            headers={
                'Authorization': 'Bearer {}'.format(self.token) 
            }).json()['source']['resultId']

    def get_results(self):
        return requests.get('https://api.firebind.com/v1/result/{}'.format(self.scan_id),           headers={
            'Authorization': 'Bearer {}'.format(self.token)
        }).json()
    
if __name__ == '__main__':
    api = ReconAPI()
    api.authenticate()
    print(json.dumps(api.list_agents(), indent=2))
    print(json.dumps(api.list_scans(), indent=2))
    api.start_scan()
    print(json.dumps(api.get_results(), indent=2))
    

The response contains all information about how the scan performed. This includes the particulars of the endpoints, protocols, transports, and the results of the wire activity. The example output below shows the issued scan in-progress at 19%, running a Shellshock payload. In this case the network path (and all security controls) allows complete passage of the malicious payload – unsecured endpoints receiving this payload would be affected.

{
  "source" : {
    "id" : "03710122-55b3-11ea-9026-2b6cc8b7959b",
    "start" : 1582403935138,
    "end" : 0,
    "lastActivity" : 1582403946833,
    "remoteAddress" : "R_FIREBIND_USAF55_T51.firebind.com:443",
    "serverAddress" : "R_FIREBIND_USAF55_T51.firebind.com:443",
    "initiatorReflectorId" : "R_FIREBIND_USAF55_T51",
    "initiatorReflectorName" : "Sector 4",
    "targetReflectorId" : "R_FIREBIND_USAF55_T51",
    "targetReflectorName" : "USAF55 Target 51 remote 5.3117",
    "targetReflectorClusterName" : "Firebind US EAST (Virginia)",
    "targetReflectorClusterCode" : "US_EAST_17",
    "targetReflectorEchoAddress" : "R_FIREBIND_USAF55_T51.firebind.com",
    "tag" : "Scan now request",
    "records" : [ {
      "complete" : false,
      "guid" : 178414533,
      "componentName" : "Shellshock TCP 50,000 to 50,100",
      "componentCode" : "20010836-55b4-11ea-b0d9-2b007cf84189",
      "percent" : 19,
      "componentStart" : 1582403936898,
      "componentStop" : 0,
      "error" : false,
      "tcpList" : "50000-50100",
      "tcpListCount" : 101,
      "udpList" : null,
      "udpListCount" : 0,
      "timeout" : 4000,
      "scriptCode" : "322246f6-55b4-11ea-b21c-0f1421dafb1e",
      "scriptName" : "Shellshock",
      "portDelay" : 250,
      "tcpGuid" : 1873,
      "tcpOpen" : "50000-50019",
      "tcpOpenCount" : 20,
      "tcpClosed" : "",
      "tcpClosedCount" : 0,
      "tcpResults" : {
        "12110" : "50000-50019"
      },
      "tcpComplete" : false,
      "udpGuid" : 0,
      "udpOpen" : null,
      "udpOpenCount" : 0,
      "udpClosed" : null,
      "udpClosedCount" : 0,
      "udpResults" : null,
      "udpComplete" : true
    } ],
    "originalSuiteSize" : 1,
    "suiteCode" : "4067e572-55b4-11ea-8cdb-4fe02fea115d",
    "suiteName" : "Shellshock TCP 50,000 to 50,100",
    "configName" : "US4.5 Nevada > US East - All 64k T/U Simple 4s TO 250ms S4",
    "configCode" : "b7a253d0-55ae-11ea-b7f7-db4569e22be8",
    "complete" : false,
    "percent" : 19,
    "state" : "RUN",
    "alarm" : false,
    "error" : false,
    "errorMessage" : null,
    "description" : null,
    "number" : 0,
    "suiteId" : null,
    "name" : null,
    "code" : null,
    "externalServerAddress" : null,
    "accountCode" : "c0af55b4-55ad-11ea-90b2-df0e766eb958",
    "recordsInError" : [ ]
  },
  "properties" : {
    "alarms" : [ ]
  },
  "statusCode" : 200
}

Note the complete and percent fields. When the scan has completed the complete field will be true and the percent will be 100. A continued poll of this endpoint will show progress as the agent completes its conversation with the target. Results will update along the way.