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.