SecurityTrails
This integration provides API access to the SecurityTrails platform.
Utilities · SecurityTrails
Details
| ID | SecurityTrails |
|---|---|
| Provider | Recorded Future |
| Category | Utilities |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix XSIAM |
README
This integration provides API access to the SecurityTrails platform.
This integration was integrated and tested with V1 of SecurityTrails
Configure SecurityTrails in Cortex
| Parameter | Required |
|---|---|
| API Key | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Fetch indicators | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
securitytrails-get-subdomains
Returns child and sibling subdomains for a given hostname.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
securitytrails-get-subdomains
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | The hostname. | Required |
| children_only | Only return children subdomains. Possible values are: true, false. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.Domain.name | string | Hostname |
| SecurityTrails.Domain.subdomains | unknown | Subdomains |
| Domain.Name | string | Domain name |
| Domain.Subdomains | string | Subdomains |
| SecurityTrails.Domain.subdomain_count | number | Subdomain Count |
Command Example
#### Human Readable Output
### securitytrails-get-domain-details
***
Returns the current data about the given hostname. In addition to the current data, you also get the current statistics associated with a particular record. For example, for a records you'll get how many other hostnames have the same IP.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
#### Base Command
`securitytrails-get-domain-details`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| hostname | The hostname. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.name | string | Domain name |
| SecurityTrails.Domain.alexa_rank | number | Alexa rank |
| SecurityTrails.Domain.apex_domain | string | Apex domain |
| SecurityTrails.Domain.current_dns | unknown | Current DNS records |
| SecurityTrails.Domain.subdomain_count | number | Subdomain count |
| Domain.Name | string | Domain name |
| Domain.NameServers | string | Name servers |
#### Command Example
Human Readable Output
securitytrails-get-tags
Returns tags for a given hostname
Base Command
securitytrails-get-tags
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | Hostname. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.Domain.name | string | Domain name |
| SecurityTrails.Domain.tags | unknown | Domain tags |
| Domain.Name | string | Domain name |
| Domain.Tags | string | Domain tags |
Command Example
#### Human Readable Output
### securitytrails-get-company-details
***
Returns details for a company domain.
#### Base Command
`securitytrails-get-company-details`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| domain | Domain. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.name | string | Domain name |
| SecurityTrails.Domain.company | string | Company name |
| Domain.Name | string | Domain name |
| Domain.Organization | string | Organization |
| Domain.Registrant.Name | string | Domain registrant name |
| WHOIS.Registrant.Name | string | Domain registrant name |
#### Command Example
Human Readable Output
securitytrails-get-company-associated-ips
Returns associated IPs for a company domain. The data is based on whois data with the names matched to the domains.
Base Command
securitytrails-get-company-associated-ips
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.Domain.name | string | Domain name |
| SecurityTrails.Domain.assocaitedips | unknown | Associated IPs |
| SecurityTrails.Domain.assocaitedip_count | number | Associated IP Count |
Command Example
#### Human Readable Output
### securitytrails-get-domain-whois
***
Returns the current WHOIS data about a given hostname with the stats merged together
#### Base Command
`securitytrails-get-domain-whois`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| hostname | Hostname. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.expiresDate | date | Expires date |
| SecurityTrails.Domain.nameServers | unknown | Name servers |
| SecurityTrails.Domain.updatedDate | date | Updated date |
| SecurityTrails.Domain.name | string | Domain name |
| SecurityTrails.Domain.status | string | Status |
| SecurityTrails.Domain.contacts.countryCode | string | Country code |
| SecurityTrails.Domain.contacts.organization_count | number | Organization count |
| SecurityTrails.Domain.contacts.telephone | string | Telephone |
| SecurityTrails.Domain.contacts.postalCode_count | number | Postal code count |
| SecurityTrails.Domain.contacts.fax_count | number | Fax count |
| SecurityTrails.Domain.contacts.street1 | string | Street 1 |
| SecurityTrails.Domain.contacts.state | string | State |
| SecurityTrails.Domain.contacts.organization | string | Organization |
| SecurityTrails.Domain.contacts.telephone_count | number | Telephone count |
| SecurityTrails.Domain.contacts.country | string | Country |
| SecurityTrails.Domain.contacts.postalCode | string | Postcode |
| SecurityTrails.Domain.contacts.type | string | Type |
| SecurityTrails.Domain.contacts.city_count | number | City count |
| SecurityTrails.Domain.contacts.name_count | number | Name count |
| SecurityTrails.Domain.contacts.email | string | Email |
| SecurityTrails.Domain.contacts.fax | string | Fax |
| SecurityTrails.Domain.contacts.street1_count | number | Street 1 count |
| SecurityTrails.Domain.private_registration | boolean | Private registration |
| SecurityTrails.Domain.createdDate | date | Created date |
| SecurityTrails.Domain.registrarName | string | Registrar name |
| SecurityTrails.Domain.contactEmail | string | Contact email |
| Domain.Admin.Country | string | Country |
| Domain.Admin.Email | string | Email |
| Domain.Admin.Name | string | Name |
| Domain.Admin.Phone | string | Phone |
| Domain.DomainStatus | string | Status |
| Domain.Name | string | Name |
| Domain.NameServers | string | Name server |
| Domain.UpdatedDate | date | Updated date |
| Domain.WHOIS.CreationDate | date | Creation date |
| Domain.WHOIS.DomainStatus | string | Status |
| Domain.WHOIS.ExpirationDate | date | Expiration date |
| Domain.WHOIS.NameServers | string | Name servers |
| Domain.WHOIS.Registrar.Name | string | Name |
| Domain.WHOIS.UpdatedDate | date | Updated date |
#### Command Example
Human Readable Output
securitytrails-get-dns-history
Lists out specific historical information about the given hostname parameter. In addition of fetching the historical data for a particular type, the count statistic is returned as well, which represents the number of that particular resource against current data.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
securitytrails-get-dns-history
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | Hostname. | Required |
| type | Type. Possible values are: a, aaaa, mx, ns, soa, txt. Default is a. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.Domain.a_history_records.first_seen | string | First seen |
| SecurityTrails.Domain.a_history_records.last_seen | string | Last seen |
| SecurityTrails.Domain.a_history_records.organizations | unknown | Organizations |
| SecurityTrails.Domain.a_history_records.type | string | Type |
| SecurityTrails.Domain.a_history_records.values.ip | string | IP |
| SecurityTrails.Domain.a_history_records.values.ipv6 | string | IPv6 |
| SecurityTrails.Domain.mx_history_records.values.host | string | Host |
| SecurityTrails.Domain.mx_history_records.values.mx_count | number | MX count |
| SecurityTrails.Domain.mx_history_records.values.priority | number | Priority |
| SecurityTrails.Domain.name | string | Name |
| SecurityTrails.Domain.ns_history_records.values.nameserver | string | Name server |
| SecurityTrails.Domain.ns_history_records.values.nameserver_count | number | Name server count |
| SecurityTrails.Domain.soa_history_records.values.email | string | |
| SecurityTrails.Domain.soa_history_records.values.email_count | number | Email count |
| SecurityTrails.Domain.soa_history_records.values.ttl | number | TTL |
| SecurityTrails.Domain.txt_history_records.values.value | string | Value |
| SecurityTrails.Domain.a_history_record_pages | number | A record pages count |
| SecurityTrails.Domain.aaaa_history_record_pages | number | AAAA record pages count |
| SecurityTrails.Domain.mx_history_record_pages | number | MX record pages count |
| SecurityTrails.Domain.ns_history_record_pages | number | NS record pages count |
| SecurityTrails.Domain.soa_history_record_pages | number | SOA record pages count |
| SecurityTrails.Domain.txt_history_record_pages | number | TXT record pages count |
Command Example
#### Human Readable Output
### securitytrails-get-whois-history
***
Returns historical WHOIS information about the given domain.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
#### Base Command
`securitytrails-get-whois-history`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| hostname | Hostname. | Required |
| page | The page of the returned results, starting at 1. A page returns 100 results. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.name | string | Name |
| SecurityTrails.Domain.whois_history.contact.telephone | string | Telephone |
| SecurityTrails.Domain.whois_history.contact.city | string | City |
| SecurityTrails.Domain.whois_history.contact.name | string | Name |
| SecurityTrails.Domain.whois_history.contact.street1 | string | Street 1 |
| SecurityTrails.Domain.whois_history.contact.state | string | State |
| SecurityTrails.Domain.whois_history.contact.organization | string | Organization |
| SecurityTrails.Domain.whois_history.contact.country | string | Country |
| SecurityTrails.Domain.whois_history.contact.postalCode | string | Postal code |
| SecurityTrails.Domain.whois_history.contact.type | string | Type |
| SecurityTrails.Domain.whois_history.contact.email | string | Email |
| SecurityTrails.Domain.whois_history.contact.fax | string | Fax |
| SecurityTrails.Domain.whois_history.started | number | Started |
| SecurityTrails.Domain.whois_history.expiresDate | number | Expires date |
| SecurityTrails.Domain.whois_history.domain | string | Domain |
| SecurityTrails.Domain.whois_history.nameServers | string | Name servers |
| SecurityTrails.Domain.whois_history.gtld | boolean | GTLD |
| SecurityTrails.Domain.whois_history.updatedDate | number | Updated date |
| SecurityTrails.Domain.whois_history.status | string | Status |
| SecurityTrails.Domain.whois_history.full_domain | string | Full domain |
| SecurityTrails.Domain.whois_history.createdDate | number | Created date |
| SecurityTrails.Domain.whois_history.registrarName | string | Registrar name |
| SecurityTrails.Domain.whois_history.ended | number | Ended date |
| SecurityTrails.Domain.whois_history_count | number | WHOIS history count |
| Domain.Name | string | Name |
| Domain.WHOIS/History.Admin.Email | string | Email |
| Domain.WHOIS/History.Admin.Name | string | Name |
| Domain.WHOIS/History.Admin.Phone | string | Phone |
| Domain.WHOIS/History.CreationDate | date | Creation date |
| Domain.WHOIS/History.DomainStatus | string | Status |
| Domain.WHOIS/History.ExpirationDate | date | Expiration date |
| Domain.WHOIS/History.NameServers | string | Name servers |
| Domain.WHOIS/History.Registrant.Email | string | Email |
| Domain.WHOIS/History.Registrant.Name | string | Name |
| Domain.WHOIS/History.Registrant.Phone | string | Phone |
| Domain.WHOIS/History.Registrar.Email | string | Email |
| Domain.WHOIS/History.Registrar.Name | string | Name |
| Domain.WHOIS/History.Registrar.Phone | string | Phone |
| Domain.WHOIS/History.UpdatedDate | date | Updated date |
#### Command Example
Human Readable Output
securitytrails-get-ip-neighbors
Returns the neighbors in any given IP level range and essentially allows you to explore closeby IP addresses. It will divide the range into 16 groups. Example: a /28 would be divided into 16 /32 blocks or a /24 would be divided into 16 /28 blocks
Base Command
securitytrails-get-ip-neighbors
Input
| Argument Name | Description | Required |
|---|---|---|
| ipaddress | Starting IP address (optionally with CIDR subnet mask). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.IP.ip | string | IP address |
| SecurityTrails.IP.block.active_egress | boolean | Active Egress |
| SecurityTrails.IP.block.hostnames | string | Hostnames |
| SecurityTrails.IP.block.ports | number | Port |
| SecurityTrails.IP.block.sites | number | Sites |
| IP.Address | string | Address |
Command Example
#### Human Readable Output
### securitytrails-search-domain
***
Filter and search specific records using DSL - a powerful SQL like query interface to the data via certain API end points.
#### Base Command
`securitytrails-search-domain`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| include_ips | Resolves any A records and additionally returns IP addresses. Possible values are: false, true. Default is false. | Optional |
| page | The page of the returned results, starting at 1. A page returns 100 results. | Optional |
| scroll | Request scrolling. Only supported when query is used and not filter. See the Scrolling API endpoint. Possible values are: false, true. Default is false. | Optional |
| query | The DSL query you want to run (https://docs.securitytrails.com/docs/how-to-use-the-dsl). | Optional |
| filter | JSON dicitonary of filter terms (https://docs.securitytrails.com/reference#domain-search). Can not be used together with query. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.Search.alexa_rank | number | Alexa rank |
| SecurityTrails.Domain.Search.computed.company_name | string | Company name |
| SecurityTrails.Domain.Search.host_provider | string | Host provider |
| SecurityTrails.Domain.Search.hostname | string | Hostname |
| SecurityTrails.Domain.Search.mail_provider.[0] | string | Mail provider |
| SecurityTrails.Domain.Search.whois.createdDate | number | Created date |
| SecurityTrails.Domain.Search.whois.expiresDate | number | Expires date |
| SecurityTrails.Domain.Search.whois.registrar | string | Registrar |
#### Command Example
Human Readable Output
securitytrails-statistics-domain
Domain statistics
Base Command
securitytrails-statistics-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The DSL query you want to run (https://docs.securitytrails.com/docs/how-to-use-the-dsl). | Optional |
| filter | JSON dicitonary of filter terms (https://docs.securitytrails.com/reference#domain-search). Can not be used together with query. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.Domain.Search.DomainStats.domain_count | number | Domain count |
| SecurityTrails.Domain.Search.DomainStats.hostname_count.relation | string | Relation |
| SecurityTrails.Domain.Search.DomainStats.hostname_count.value | number | Value |
| SecurityTrails.Domain.Search.DomainStats.tld_count | number | TLD count |
| SecurityTrails.Domain.Search.DomainStats.top_organizations.count | number | Count |
| SecurityTrails.Domain.Search.DomainStats.top_organizations.key | string | Key |
| SecurityTrails.Domain.Search.DomainStats.whois_organization_count | number | WHOIS count |
Command Example
#### Human Readable Output
### securitytrails-get-associated-domains
***
Find all domains that are related to a hostname you input. Limited to 10000 results.
#### Base Command
`securitytrails-get-associated-domains`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| hostname | Hostname. | Required |
| page | The page of the returned results, starting at 1. A page returns 100 results. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.Domain.associated_domains.alexa_rank | number | Alexa Rank |
| SecurityTrails.Domain.associated_domains.computed.company_name | string | Company Name |
| SecurityTrails.Domain.associated_domains.host_provider | string | Host Provider |
| SecurityTrails.Domain.associated_domains.hostname | string | Hostname |
| SecurityTrails.Domain.associated_domains.mail_provider | string | Mail Provider |
| SecurityTrails.Domain.associated_domains.whois.createdDate | number | Created Date |
| SecurityTrails.Domain.associated_domains.whois.expiresDate | number | Expires Date |
| SecurityTrails.Domain.associated_domains.whois.registrar | string | Registrar |
| SecurityTrails.Domain.associated_domain_count | number | Associated Domain Count |
#### Command Example
Human Readable Output
securitytrails-search-ip
Search for IP addresses. A maximum of 10000 results can be retrieved.
Base Command
securitytrails-search-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| page | The page of the returned results, starting at 1. A page returns 100 results. Default is 1. | Optional |
| query | The DSL query you want to run (https://docs.securitytrails.com/docs/how-to-use-the-dsl). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.IP.Search.ip | string | IP Address |
| SecurityTrails.IP.Search.ports.port | number | Port |
| SecurityTrails.IP.Search.ports.date_checked | number | Date checked |
| SecurityTrails.IP.Search.ptr | string | PTR Record |
| IP.Address | string | Address |
| IP.Hostname | string | Hostname |
| IP.Ports | string | Ports |
Command Example
#### Human Readable Output
### securitytrails-statistics-ip
***
Statistics like Reverse DNS pattern identification (RDNS entries are grouped and displayed as x), ports (number of open ports found) or total results are returned
#### Base Command
`securitytrails-statistics-ip`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| query | The DSL query you want to run (https://docs.securitytrails.com/docs/how-to-use-the-dsl). | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.IP.Search.IPStats.ports.count | number | Count |
| SecurityTrails.IP.Search.IPStats.ports.key | number | Key |
| SecurityTrails.IP.Search.IPStats.top_ptr_patterns.count | number | Count |
| SecurityTrails.IP.Search.IPStats.top_ptr_patterns.key | string | Key |
| SecurityTrails.IP.Search.IPStats.total.relation | string | Relation |
| SecurityTrails.IP.Search.IPStats.total.value | number | Value |
#### Command Example
Human Readable Output
securitytrails-get-ip-whois
Returns IPs information based on whois information.
Base Command
securitytrails-get-ip-whois
Input
| Argument Name | Description | Required |
|---|---|---|
| ipaddress | IP Address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| SecurityTrails.IP.contact_email | string | |
| SecurityTrails.IP.contacts.email | string | |
| SecurityTrails.IP.contacts.organization | string | Organization |
| SecurityTrails.IP.contacts.telephone | string | Telephone |
| SecurityTrails.IP.contacts.type | string | Type |
| SecurityTrails.IP.ip | string | IP |
| SecurityTrails.IP.source | string | Source |
Command Example
#### Human Readable Output
### securitytrails-get-useragents
***
Fetch user agents seen during the last 30 days for a specific IPv4 address. It shows devices with egressing traffic based on large scale web server logs. The number of results is not limited.
#### Base Command
`securitytrails-get-useragents`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| ipaddress | IP Address. | Required |
| page | The page of the returned results, starting at 1. A page returns 100 results. Default is 1. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| SecurityTrails.IP.ip | string | IP Address |
| SecurityTrails.IP.useragent_records_count | number | Count |
| SecurityTrails.IP.useragents.browser_family | string | Browser Family |
| SecurityTrails.IP.useragents.client.engine | string | Client Engine |
| SecurityTrails.IP.useragents.client.engine_version | string | Client Engine Version |
| SecurityTrails.IP.useragents.client.name | string | Client Engine Name |
| SecurityTrails.IP.useragents.client.type | string | Client Engine Type |
| SecurityTrails.IP.useragents.client.version | string | Client Version |
| SecurityTrails.IP.useragents.device.brand | string | Device Brand |
| SecurityTrails.IP.useragents.device.model | string | Device Model |
| SecurityTrails.IP.useragents.device.type | string | Device Type |
| SecurityTrails.IP.useragents.lastseen | string | Last Seen |
| SecurityTrails.IP.useragents.os.name | string | OS Name |
| SecurityTrails.IP.useragents.os.platform | string | OS Platform |
| SecurityTrails.IP.useragents.os.version | string | OS Version |
| SecurityTrails.IP.useragents.os_family | string | OS Family |
| SecurityTrails.IP.useragents.user_agent | string | User Agent |
#### Command Example
Human Readable Output
domain
Provides data enrichment for domains.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain name to enrich. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | String | The domain name, for example: “google.com”. |
| Domain.DNS | String | A list of IP objects resolved by DNS. |
| Domain.DomainStatus | Datte | The status of the domain. |
| Domain.NameServers | Unknown | (List<String>) Name servers of the domain. |
| Domain.Organization | String | The organization of the domain. |
| Domain.Subdomains | Unknown | (List<String>) Subdomains of the domain. |
| Domain.Admin.Country | String | The country of the domain administrator. |
| Domain.Admin.Email | String | The email address of the domain administrator. |
| Domain.Admin.Name | String | The name of the domain administrator. |
| Domain.Admin.Phone | String | The phone number of the domain administrator. |
| Domain.Registrant.Country | String | The country of the registrant. |
| Domain.Registrant.Email | String | The email address of the registrant. |
| Domain.Registrant.Name | String | The name of the registrant. |
| Domain.Registrant.Phone | String | The phone number for receiving abuse reports. |
| Domain.Tags | Unknown | (List) Tags of the domain. |
| Domain.WHOIS.DomainStatus | String | The status of the domain. |
| Domain.WHOIS.NameServers | String | (List<String>) Name servers of the domain. |
| Domain.WHOIS.CreationDate | Date | The date that the domain was created. |
| Domain.WHOIS.UpdatedDate | Date | The date that the domain was last updated. |
| Domain.WHOIS.ExpirationDate | Date | The expiration date of the domain. |
| Domain.WHOIS.Registrant.Name | String | The name of the registrant. |
| Domain.WHOIS.Registrant.Email | String | The email address of the registrant. |
| Domain.WHOIS.Registrant.Phone | String | The phone number of the registrant. |
| Domain.WHOIS.Registrar.Name | String | The name of the registrar, for example: `GoDaddy` |
| Domain.WHOIS.Registrar.Email | String | The email address of the contact. |
| Domain.WHOIS.Registrar.Phone | String | The phone number of contact. |
| Domain.WHOIS.Admin.Name | String | The name of the domain administrator. |
| Domain.WHOIS.Admin.Email | String | The email address of the domain administrator. |
| Domain.WHOIS.Admin.Phone | String | The phone number of the domain administrator. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
#### Human Readable Output
### securitytrails-sql-query
***
Queries the SecurityTrails SQL endpoint. The SecurityTrails SQL API provides a powerful SQL-like query interface to data via certain API endpoints. For a full reference of properties and operators please check the following link: https://securitytrails.com/reference/sql
#### Base Command
`securitytrails-sql-query`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| sql | The SQL query to execute (example: SELECT attribute FROM table WHERE condition = "value"). Possible values are: . | Required |
| timeout | Read timeout for calls (default is 20 seconds). Possible values are: . Default is 20. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Securitytrails.SQL.total | Number | The total number of hits discovered |
| Securitytrails.SQL.records | Unknown | The records returned |
| Securitytrails.SQL.id | String | The ID to use for further GET calls to retrieve more results |
| Securitytrails.SQL.query | String | The original query used |
| Securitytrails.SQL.pages | Number | The total number of pages that would need to be called to retrieve the rest of the results |
#### Command Example
Human Readable Output
securitytrails-sql-get-next
Retrieves the next page of results returned from a SQL query where the results exceeded the last page.
Base Command
securitytrails-sql-get-next
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID to use to retrieve the next page of results. Possible values are: . | Required |
| timeout | Read timeout for calls (default is 20 seconds). Possible values are: . Default is 20. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Securitytrails.SQL.total | number | The total number of hits discovered |
| Securitytrails.SQL.records | unknown | The records returned |
| Securitytrails.SQL.id | string | The ID to use for further GET calls to retrieve more results |
| Securitytrails.SQL.query | string | The original query used |
Command Example
``````
Human Readable Output
Configuration parameters
apikey— API Key (required)timeout— Timeoutinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsintegrationReliability— Source ReliabilityfeedExpirationPolicy—feedExpirationInterval—
Commands (19)
-
domainProvides data enrichment for domains.
-
securitytrails-get-associated-domainsFind all domains that are related to a hostname you input. Limited to 10000 results.
-
securitytrails-get-company-associated-ipsReturns associated IPs for a company domain. The data is based on whois data with the names matched to the domains.
-
securitytrails-get-company-detailsReturns details for a company domain.
-
securitytrails-get-dns-historyLists out specific historical information about the given hostname parameter. In addition of fetching the historical data for a particular type, the count statistic is returned as well, which represents the number of that particular resource against current data.
-
securitytrails-get-domain-detailsReturns the current data about the given hostname. In addition to the current data, you also get the current statistics associated with a particular record. For example, for a records you'll get how many other hostnames have the same IP.
-
securitytrails-get-domain-whoisReturns the current WHOIS data about a given hostname with the stats merged together.
-
securitytrails-get-ip-neighborsReturns the neighbors in any given IP level range and essentially allows you to explore closeby IP addresses. It will divide the range into 16 groups. Example: a /28 would be divided into 16 /32 blocks or a /24 would be divided into 16 /28 blocks.
-
securitytrails-get-ip-whoisReturns IPs information based on whois information.
-
securitytrails-get-subdomainsReturns child and sibling subdomains for a given hostname.
-
securitytrails-get-tagsReturns tags for a given hostname.
-
securitytrails-get-useragentsFetch user agents seen during the last 30 days for a specific IPv4 address. It shows devices with egressing traffic based on large scale web server logs. The number of results is not limited.
-
securitytrails-get-whois-historyReturns historical WHOIS information about the given domain.
-
securitytrails-search-domainFilter and search specific records using DSL - a powerful SQL like query interface to the data via certain API end points.
-
securitytrails-search-ipSearch for IP addresses. A maximum of 10000 results can be retrieved.
-
securitytrails-sql-get-nextRetrieves the next page of results returned from a SQL query where the results exceeded the last page.
-
securitytrails-sql-queryQueries the SecurityTrails SQL endpoint. The SecurityTrails SQL API provides a powerful SQL-like query interface to data via certain API endpoints. For a full reference of properties and operators please check the following link: https://securitytrails.com/reference/sql
-
securitytrails-statistics-domainDomain statistics.
-
securitytrails-statistics-ipStatistics like Reverse DNS pattern identification (RDNS entries are grouped and displayed as x), ports (number of open ports found) or total results are returned.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ CONSTANTS """ removed_keys = ["endpoint", "domain", "hostname"] """ CLIENT CLASS """ class Client(BaseClient): def __init__(self, base_url, verify=True, proxy=False, ok_codes=(), headers=None, auth=None, timeout=10): super().__init__(base_url, verify=verify, proxy=proxy, ok_codes=ok_codes, headers=headers, auth=auth) self.timeout = timeout def domain_tags(self, hostname: str = None): res = self._http_request("GET", f"domain/{hostname}/tags", ok_codes=(200, 403), timeout=self.timeout) return res.get("tags", []) def domain_details(self, hostname: str = None): return self._http_request("GET", f"domain/{hostname}", ok_codes=(200, 403), timeout=self.timeout) def domain_subdomains(self, hostname: str = None, children_only: str = "true"): query_string = {"children_only": children_only} res = self._http_request( "GET", f"domain/{hostname}/subdomains", params=query_string, ok_codes=(200, 403), timeout=self.timeout ) return res def associated_domains(self, hostname: str = None, page: int = 1): params = {"page": page} res = self._http_request("GET", f"domain/{hostname}/associated", params=params, ok_codes=(200, 403), timeout=self.timeout) return res def get_ssl_certificates(self, query_type: str = "stream", hostname: str = None, params: dict = None): # There's a bug in the API where the result is malformed. if query_type == "paged": res = self._http_request( "GET", f"domain/{hostname}/ssl", params=params or {}, ok_codes=(200, 403), resp_type="response", timeout=self.timeout, ) elif query_type == "stream": res = self._http_request( "GET", f"domain/{hostname}/ssl_stream", params=params, ok_codes=(200, 403), resp_type="response", timeout=self.timeout, ) else: res = {} demisto.debug(f"The {query_type=} didn't match any value. {res=}") return res def get_company(self, domain: str = None): res = self._http_request("GET", f"company/{domain}", ok_codes=(200, 403), timeout=self.timeout) return res.get("record", {}) def get_useragents(self, ip_address: str = None, params: dict = None): return self._http_request( "GET", f"ips/{ip_address}/useragents", params=params or {}, ok_codes=(200, 403), timeout=self.timeout ) def get_company_associated_ips(self, domain: str = None): res = self._http_request("GET", f"company/{domain}/associated-ips", ok_codes=(200, 403), timeout=self.timeout) return res.get("record", {}) def get_whois(self, query_type: str = "domain", hostname: str = None): if query_type == "domain": # noqa: RET503 return self._http_request("GET", f"domain/{hostname}/whois", ok_codes=(200, 403), timeout=self.timeout) elif query_type == "ip": return self._http_request("GET", f"ips/{hostname}/whois", ok_codes=(200, 403), timeout=self.timeout) def get_dns_history(self, hostname: str = None, record_type: str = None, page: int = 1): params = {"page": page} return self._http_request( "GET", f"history/{hostname}/dns/{record_type}", params=params, ok_codes=(200, 403), timeout=self.timeout ) def get_whois_history(self, hostname: str = None, page: int = 1): params = {"page": page} res = self._http_request("GET", f"history/{hostname}/whois", params=params, ok_codes=(200, 403), timeout=self.timeout) return res.get("result") def get_ip_neighbors(self, ipaddress: str = None): res = self._http_request("GET", f"ips/nearby/{ipaddress}", ok_codes=(200, 403), timeout=self.timeout) return res.get("blocks") def query(self, query_type: str = "domain_search", body: dict = None, params: dict = None): if query_type == "domain_search": # noqa: RET503 return self._http_request( "POST", "domains/list", params=params, json_data=body, ok_codes=(200, 403), timeout=self.timeout ) elif query_type == "domain_stats": return self._http_request("POST", "domains/stats", json_data=body, ok_codes=(200, 403), timeout=self.timeout) elif query_type == "ip_search": return self._http_request( "POST", "ips/list", params=params, json_data=body, ok_codes=(200, 403), timeout=self.timeout ) elif query_type == "ip_stats": return self._http_request( "POST", "ips/stats", params=params, json_data=body, ok_codes=(200, 403), timeout=self.timeout ) def sql(self, sql: dict = None, timeout: int = 20): return self._http_request("POST", "query/scroll", json_data=sql, timeout=self.timeout) def sql_next(self, next_id: str = None, timeout: int = 20): return self._http_request("GET", f"query/scroll/{next_id}", timeout=self.timeout) """ HELPER FUNCTIONS """ ################################# # Standard Context Outputs ################################# def create_standard_domain_context(domain_data): command_results = CommandResults( outputs_prefix="Domain", outputs_key_field="Name", outputs=domain_data, readable_output=tableToMarkdown("Domain(s):", domain_data), ) return_results(command_results) def create_standard_ip_context(ip_data): command_results = CommandResults( outputs_prefix="IP", outputs_key_field="Address", outputs=ip_data, readable_output=tableToMarkdown("IP Address(es):", ip_data), ) return_results(command_results) def domain_command(client, args): domains = argToList(args.get("domain")) command_results: List[CommandResults] = [] for domain in domains: try: domain_details = client.domain_details(hostname=domain) except Exception: demisto.info(f"No information found for domain: {domain}") return_results(f"No information found for domain: {domain}") continue domain_subdomains = client.domain_subdomains(hostname=domain) domain_whois = client.get_whois(query_type="domain", hostname=domain) domain_tags = client.domain_tags(hostname=domain) admin_contact = [ {"Name": x.get("name"), "Email": x.get("email"), "Phone": x.get("telephone"), "Country": x.get("country")} for x in domain_whois.get("contacts", []) if "admin" in x.get("type", "").lower() ] registrant_contact = [ { "Name": x.get("name", None), "Email": x.get("email", None), "Phone": x.get("telephone", None), "Country": x.get("country", None), } for x in domain_whois.get("contacts", []) if "registrant" in x.get("type", "").lower() ] registrar_contact = [ { "Name": x.get("name", None), "Email": x.get("email", None), "Phone": x.get("telephone", None), "Country": x.get("country", None), } for x in domain_whois.get("contacts", []) if "registrar" in x.get("type", "").lower() ] domain_data = { "Name": domain, "DNS": ",".join([x.get("ip", "") for x in domain_details.get("current_dns", {}).get("a", {}).get("values", [])]), "NameServers": ",".join( [x.get("nameserver", "") for x in domain_details.get("current_dns", {}).get("ns", {}).get("values", [])] ), "Organization": domain_details.get("name", None), "Subdomains": ",".join(domain_subdomains.get("subdomains", [])), "WHOIS": { "DomainStatus": domain_whois.get("status"), "NameServers": ",".join(domain_whois.get("nameServers")) if domain_whois.get("nameServers") else None, "CreationDate": domain_whois.get("createdDate"), "UpdatedDate": domain_whois.get("updatedDate"), "ExpirationDate": domain_whois.get("expiresData"), "Registrant": { "Name": registrant_contact[0].get("Name", None) if registrant_contact else None, "Email": registrant_contact[0].get("Email", None) if registrant_contact else None, "Phone": registrant_contact[0].get("Phone", None) if registrant_contact else None, }, "Registrar": { "Name": registrar_contact[0].get("Name", None) if registrar_contact else None, "Email": registrar_contact[0].get("Email", None) if registrar_contact else None, "Phone": registrar_contact[0].get("Phone", None) if registrar_contact else None, }, "Admin": { "Name": admin_contact[0].get("Name", None) if admin_contact else None, "Email": admin_contact[0].get("Email", None) if admin_contact else None, "Phone": admin_contact[0].get("Phone", None) if admin_contact else None, }, }, "Tags": ",".join(domain_tags), "Admin": { "Country": admin_contact[0].get("Country", None) if admin_contact else None, "Name": admin_contact[0].get("Name", None) if admin_contact else None, "Email": admin_contact[0].get("Email", None) if admin_contact else None, "Phone": admin_contact[0].get("Phone", None) if admin_contact else None, }, "Registrant": { "Country": registrant_contact[0].get("Country", None) if registrant_contact else None, "Name": registrant_contact[0].get("Name", None) if registrant_contact else None, "Email": registrant_contact[0].get("Email", None) if registrant_contact else None, "Phone": registrant_contact[0].get("Phone", None) if registrant_contact else None, }, } dbot_score = Common.DBotScore( indicator=domain, indicator_type=DBotScoreType.DOMAIN, integration_name="SecurityTrails", score=Common.DBotScore.NONE, reliability=demisto.params().get("integrationReliability"), ) domain_indicator = Common.Domain(domain=domain, dbot_score=dbot_score) md = tableToMarkdown(f"Domain {domain}:", domain_data) result = CommandResults( outputs_prefix="Domain", outputs_key_field="Name", outputs=domain_data, indicator=domain_indicator, readable_output=md ) command_results.append(result) return_results(command_results) ################################# # Company endpoints ################################# def get_company_details_command(client, args): domain = args.get("domain") res = client.get_company(domain=domain) readable_output = f"### Company for {domain}: {res.get('name', None)}" command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs={"name": domain, "company": res.get("name", None)}, readable_output=readable_output, ) return_results(command_results) create_standard_domain_context( domain_data={ "Name": domain, "Organization": res.get("name", None), "Registrant": {"Name": res.get("name", None)}, "WHOIS": {"Registrant": {"Name": res.get("name", None)}}, } ) def get_company_associated_ips_command(client, args): domain = args.get("domain") res = client.get_company_associated_ips(domain=domain) readable_output = tableToMarkdown(f"Associated IPs for {domain}", res) output_data = {"name": domain, "associatedips": res, "associatedips_count": len(res)} command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=output_data, readable_output=readable_output ) return_results(command_results) ################################# # Domain endpoints ################################# def domain_details_command(client, args): hostname = args.get("hostname") res = client.domain_details(hostname=hostname) res = {k: v for k, v in res.items() if k not in removed_keys} res["name"] = hostname output_data = sorted( [{"Type": k, "Record Count": len(v.get("values", []))} for k, v in res.get("current_dns", {}).items()], key=lambda x: x["Type"], ) readable_output = tableToMarkdown(f"Domain details for {hostname}:", output_data, ["Type", "Record Count"]) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=res, readable_output=readable_output ) return_results(command_results) create_standard_domain_context( domain_data={ "Name": hostname, "NameServers": ", ".join( [x.get("nameserver", None) for x in res.get("current_dns", {}).get("ns", {}).get("values", [])] ), } ) def domains_subdomains_command(client, args): hostname = args.get("hostname") children_only = args.get("children_only", "true") res = client.domain_subdomains(hostname=hostname, children_only=children_only) subdomains = res.get("subdomains", []) md = tableToMarkdown(f"Subdomains for {hostname}:", [{"Subdomain": x} for x in subdomains]) output_data = {"name": hostname, "subdomains": subdomains, "subdomains_count": len(subdomains)} command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=output_data, readable_output=md ) return_results(command_results) def get_domain_tags_command(client, args): hostname = args.get("hostname") res = client.domain_tags(hostname=hostname) tags = ", ".join(res) readable_output = f"### Tags for {hostname}:\n\n{tags}" command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs={"name": hostname, "tags": res}, readable_output=readable_output, ) return_results(command_results) create_standard_domain_context(domain_data={"Name": hostname, "Tags": tags}) def get_whois_command(client, args): command = demisto.command() if command == "securitytrails-get-domain-whois": hostname = args.get("hostname") res = client.get_whois(query_type="domain", hostname=hostname) res = {k: v for k, v in res.items() if k not in removed_keys} res["name"] = hostname readable_output = tableToMarkdown(f"WHOIS data for {hostname}", res) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=res, readable_output=readable_output ) return_results(command_results) contacts = res.get("contacts", []) domain_data = { "Name": hostname, "UpdatedDate": res.get("updatedDate"), "DomainStatus": res.get("status"), "WHOIS": { "DomainStatus": res.get("status"), "CreationDate": res.get("createdDate"), "UpdatedDate": res.get("updatedDate"), "ExpirationDate": res.get("expiresDate"), "Registrar": {"Name": res.get("registrarName")}, }, } if res.get("nameServers", None): name_servers = ", ".join(x for x in res.get("nameServers", [])) domain_data["NameServers"] = name_servers domain_data["WHOIS"]["NameServers"] = name_servers # Find the admin contact admin = None for contact in contacts: if (contact.get("type").lower()).startswith("admin"): admin = contact break if admin: domain_data["Admin"] = { "Country": admin.get("country", None), "Email": admin.get("email", None), "Name": admin.get("name", None), "Phone": admin.get("telephone", None), } create_standard_domain_context(domain_data=domain_data) elif command == "securitytrails-get-ip-whois": ip_address = args.get("ipaddress") res = client.get_whois(query_type="ip", hostname=ip_address) res = res.get("record", {}) res = {k: v for k, v in res.items() if k not in removed_keys} res["ip"] = ip_address readable_output = tableToMarkdown(f"WHOIS data for {ip_address}", res) command_results = CommandResults( outputs_prefix="SecurityTrails.IP", outputs_key_field="ip", outputs=res, readable_output=readable_output ) return_results(command_results) ip_data = {"Address": ip_address} create_standard_ip_context(ip_data=ip_data) def domain_search_command(client, args): include_ips = argToBoolean(args.get("include_ips", "false")) page = int(args.get("page", 1)) scroll = args.get("include_ips", "false") == "true" query = args.get("query", None) filter = args.get("filter", None) if not query and not filter: return_error("You must provide at least a query or a filter") params = {"include_ips": include_ips, "page": page, "scroll": scroll} body = {} if query: body["query"] = query elif filter: body["filter"] = filter res = client.query(query_type="domain_search", params=params, body=body) records = res.get("records") record_count = res.get("record_count") md = tableToMarkdown(f"Domain DSL Search Results ({record_count} record(s)):", records) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain.Search", outputs_key_field="hostname", outputs=records, readable_output=md ) return_results(command_results) def domain_statistics_command(client, args): query = args.get("query", None) filter = args.get("filter", None) if not query and not filter: return_error("You must provide at least a query or a filter") body = {} if query: body["query"] = query elif filter: body["filter"] = filter res = client.query(query_type="domain_stats", body=body) res = {k: v for k, v in res.items() if k not in removed_keys} top_orgs = res.get("top_organizations", []) tld_count = res.get("tld_count", 0) hostname_count = res.get("hostname_count", {}) domain_count = res.get("domain_count", 0) table_data = { "Top Organizations Count": len(top_orgs), "TLD Count": tld_count, "Hostname Count": hostname_count, "Domain Count": domain_count, } md = tableToMarkdown("Domain Statistics:", table_data) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain.Search.DomainStats", outputs_key_field="hostname", outputs=res, readable_output=md ) return_results(command_results) def associated_domains_command(client, args): hostname = args.get("hostname") page = args.get("page", 1) res = client.associated_domains(hostname=hostname, page=page) records = res.get("records", []) record_count = res.get("record_count", 0) table_data = { "Count": record_count, "Domains": ", ".join([x.get("hostname") for x in records]), "Current Page": page, "Total Pages": res.get("meta", {}).get("total_pages", 1), } md = tableToMarkdown(f"{hostname} Associated Domains:", table_data, ["Count", "Current Page", "Total Pages", "Domains"]) output_data = {"name": hostname, "associated_domains": records, "associated_domain_count": record_count} command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=output_data, readable_output=md ) return_results(command_results) def get_ssl_certificates(client, args): hostname = args.get("hostname") include_subdomains = args.get("include_subdomains", "false") == "true" status = args.get("status", "valid") page = None params = {"include_subdomains": include_subdomains, "status": status} if "page" in args: page = int(args.get("page", 1)) params["page"] = page query_type = "paged" if page else "stream" res = client.get_ssl_certificates(query_type=query_type, hostname=hostname, params=params) records = res.get("records", []) # record_count = res.get('record_count', 0) table_data = [ { "Subject Key ID": x.get("subject_key_id"), "Subject Common Name": x.get("subject", {}).get("common_name"), "Subject Alternative Names": ", ".join(list(x.get("subject", {}).get("alt_names", []))), "Serial Number": x.get("serial_number"), "Public Key Type": x.get("public_key", {}).get("key_type"), "Public Key": x.get("public_key", {}).get("key"), "Public Key Bit Length": x.get("public_key", {}).get("bit_length"), "Precert": x.get("precert"), "Not Before": x.get("not_before"), "Not After": x.get("not_after"), "Issuer Organization": ",".join(x.get("issuer", {}).get("organization")), "Issuer Country": ",".join(x.get("issuer", {}).get("country")), "Issuer Common Name": x.get("issuer", {}).get("common_name"), "ID": x.get("id"), "Fingerprints": x.get("fingerprints"), "DNS Names": ",".join(x.get("dns_names")), } for x in records ] md = tableToMarkdown( f"SSL Certificates for {hostname}", table_data, [ "ID", "Subject Key ID", "Subject Common Name", "Subject Alternative Names", "Serial Number", "Public Key Type", "Public Key", "Public Key Bit Length", "Precert", "Not Before", "Not After", "Issuer Organization", "Issuer Country", "Issuer Common Name", "Fingerprints", "DNS Names", ], ) output_data = {"name": hostname, "ssl_certiticates": records} command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs=output_data, readable_output=md ) return_results(command_results) ################################# # History endpoints ################################# def get_dns_history_command(client, args): hostname = args.get("hostname") record_type = args.get("type") page = int(args.get("page", 1)) res = client.get_dns_history(hostname=hostname, record_type=record_type, page=page) res = {k: v for k, v in res.items() if k not in removed_keys} records_list = [] if record_type == "a": pull_field = "ip" elif record_type == "aaaa": pull_field = "ipv6" elif record_type == "mx": pull_field = "host" elif record_type == "ns": pull_field = "nameserver" elif record_type == "soa": pull_field = "email" elif record_type == "txt": pull_field = "value" else: pull_field = "" demisto.debug(f"There is no matching value for {record_type=}. {pull_field=}") records = res.get("records", {}) for record in records: for value in record.get("values"): if pull_field in value: records_list.append({"Record Type": record_type, "Value(s)": value.get(pull_field)}) readable_output = tableToMarkdown(f"DNS history for {hostname}:", records_list) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs={ "name": hostname, f"{record_type}_history_records": res.get("records"), f"{record_type}_history_record_pages": res.get("pages", 1), }, readable_output=readable_output, ) return_results(command_results) latest_record = res.get("records", [])[0] values = latest_record.get("values", []) values = [values] if type(values) is dict else values # hosts = [x['host'] for x in values if "host" in x] ipv4 = [x["ip"] for x in values if "ip" in x] ipv6 = [x["ip"] for x in values if "ipv6" in x] nameservers = [x["nameserver"] for x in values if "nameserver" in x] domain_data = {"Name": hostname} if nameservers: domain_data["NameServers"] = ", ".join(nameservers) create_standard_domain_context(domain_data=domain_data) if ipv4: [create_standard_ip_context({"Address": x}) for x in ipv4] if ipv6: [create_standard_ip_context({"Address": x}) for x in ipv6] def get_whois_history_command(client, args): hostname = args.get("hostname") page = int(args.get("page", 1)) res = client.get_whois_history(hostname=hostname, page=page) readable_output = tableToMarkdown(f"WHOIS history for {hostname}:", res.get("items")) command_results = CommandResults( outputs_prefix="SecurityTrails.Domain", outputs_key_field="name", outputs={"name": hostname, "WHOIS_history": res.get("items", []), "WHOIS_history_count": res.get("count", 0)}, readable_output=readable_output, ) return_results(command_results) domain_data = {"Name": hostname} contacts = res.get("items", [])[0].get("contact") if res.get("items", None) else [] admin_contact = [x for x in contacts if x.get("type", None) == "administrativeContact"] admin_contact = admin_contact[0] if admin_contact else None registrant_contact = [x for x in contacts if x.get("type", None) == "registrant"] registrant_contact = registrant_contact[0] if registrant_contact else None registrar_contact = admin_contact if admin_contact else None whois_objects = [] for x in res.get("items", []): whois_object = { "DomainStatus": ", ".join(x.get("status", [])), "NameServers": ", ".join(x.get("nameServers", [])), "CreationDate": datetime.fromtimestamp(x.get("createdDate") / 1000).strftime("%Y-%m-%dT%H:%M:%SZ") if x.get("createdDate", None) else None, "UpdatedDate": datetime.fromtimestamp(x.get("updatedDate") / 1000).strftime("%Y-%m-%dT%H:%M:%SZ") if x.get("updatedDate", None) else None, "ExpirationDate": datetime.fromtimestamp(x.get("expiresDate") / 1000).strftime("%Y-%m-%dT%H:%M:%SZ") if x.get("expiresDate", None) else None, } if admin_contact: whois_object["Admin"] = { # type: ignore "Name": admin_contact.get("name"), "Email": admin_contact.get("email"), "Phone": admin_contact.get("telephone"), } if registrant_contact: whois_object["Registrant"] = { # type: ignore "Name": registrant_contact.get("name"), "Email": registrant_contact.get("email"), "Phone": registrant_contact.get("telephone"), } if registrar_contact: whois_object["Registrar"] = { # type: ignore "Name": registrar_contact.get("name"), "Email": registrar_contact.get("email"), "Phone": registrar_contact.get("telephone"), } whois_objects.append(whois_object) if len(whois_objects) > 0: domain_data["WHOIS/History"] = whois_objects create_standard_domain_context(domain_data=domain_data) ################################# # IPs endpoints ################################# def get_ip_neighbors_command(client, args): ipaddress = args.get("ipaddress") res = client.get_ip_neighbors(ipaddress=ipaddress) readable_output = tableToMarkdown( f"IP neighbors for {ipaddress}:", [ { "IP": x.get("ip", ""), "Hostnames": x.get("hostnames", None), "Sites": x.get("sites", 0), "Ports": x.get("ports", None), "Active Egress": x.get("active_egress"), } for x in res ], ["IP", "Hostnames", "Sites", "Ports", "Active Egress"], ) command_results = CommandResults( outputs_prefix="SecurityTrails.IP", outputs_key_field="ip", outputs={"ip": ipaddress, "blocks": res}, readable_output=readable_output, ) return_results(command_results) create_standard_ip_context(ip_data=[{"Address": x.get("ip").split("/")[0]} for x in res]) def ip_search_command(client, args): page = arg_to_number(args.get("page", 1)) query = args.get("query", None) params = {"page": page} body = {"query": query} res = client.query(query_type="ip_search", params=params, body=body) records = res.get("records") record_count = res.get("record_count") md = tableToMarkdown(f"IP DSL Search Results ({record_count} record(s)):", records) command_results = CommandResults( outputs_prefix="SecurityTrails.IP.Search", outputs_key_field="ip", outputs=records, readable_output=md ) return_results(command_results) create_standard_ip_context( ip_data=[ {"Address": x.get("ip"), "Hostname": x.get("ptr"), "Ports": ", ".join([str(y["port"]) for y in x.get("ports")])} for x in records ] ) def ip_statistics_command(client, args): query = args.get("query") body = {"query": query} res = client.query(query_type="ip_stats", body=body) res = {k: v for k, v in res.items() if k not in removed_keys} top_ptrs = res.get("top_ptr_patterns", []) ports = res.get("ports", []) total = res.get("total", {}).get("value") table_data = {"Top PTRs Count": len(top_ptrs), "Ports": len(ports), "Total": total} md = tableToMarkdown("IP Statistics:", table_data) command_results = CommandResults(outputs_prefix="SecurityTrails.IP.Search.IPStats", outputs=res, readable_output=md) return_results(command_results) def get_useragents_command(client, args): ip_address = args.get("ipaddress") page = arg_to_number(args.get("page", 1)) params = {"page": page} res = client.get_useragents(ip_address=ip_address, params=params) records = res.get("records", []) record_count = res.get("record_count", 0) table_data = [ { "User Agent": x.get("user_agent"), "OS Name": x.get("os", {}).get("name"), "OS Platform": x.get("os", {}).get("platform"), "OS Version": x.get("os", {}).get("version"), "Browser Family": x.get("browser_family"), "Last Seen": x.get("lastseen"), "Device Type": x.get("device", {}).get("type"), "Device Brand": x.get("device", {}).get("brand"), "Device Model": x.get("device", {}).get("model"), "Client Type": x.get("client", {}).get("type"), "Client Name": x.get("client", {}).get("name"), "Client Version": x.get("client", {}).get("version"), "Client Engine": x.get("client", {}).get("engine"), "Client Engine Verison": x.get("client", {}).get("engine_version"), } for x in records ] md = tableToMarkdown( f"User Agents for {ip_address}:", table_data, [ "User Agent", "OS Name", "OS Platform", "OS Version", "Browser Family", "Last Seen", "Device Type", "Device Brand", "Device Model", "Client Type", "Client Name", "Client Version", "Client Engine", "Client Engine Verison", ], ) output_data = {"ip": ip_address, "useragents": records, "useragent_records_count": record_count} command_results = CommandResults( outputs_prefix="SecurityTrails.IP", outputs_key_field="ip", outputs=output_data, readable_output=md ) return_results(command_results) ################################# # Query endpoints ################################# def query_sql_command(client, args): sql = args.get("sql") timeout = int(args.get("timeout", "20")) query = {"query": sql} res = client.sql(sql=query, timeout=timeout) total = res.get("total", {}).get("value") pages = 0 if total: pages = total // 100 output = { "total": res.get("total", {}).get("value"), "pages": pages, "records": res.get("records"), "id": res.get("id"), "query": res.get("query"), } readable_output = tableToMarkdown("SQL Query Results:", output) command_results = CommandResults( outputs_prefix="SecurityTrails.SQL", outputs_key_field=["query", "id"], outputs=output, readable_output=readable_output ) return_results(command_results) def query_sql_get_next_command(client, args): next_id = str(args.get("id")) timeout = int(args.get("timeout", "20")) res = client.sql_next(next_id=next_id, timeout=timeout) output = { "total": res.get("total", {}).get("value"), "records": res.get("records"), "id": res.get("id"), "query": res.get("query"), } readable_output = tableToMarkdown("SQL Query Results:", output) command_results = CommandResults( outputs_prefix="SecurityTrails.SQL", outputs_key_field=["query", "id"], outputs=output, readable_output=readable_output ) return_results(command_results) def test_module(client): results = client._http_request("GET", "ping", ok_codes=(200, 403)) if "success" in results: return "ok" else: return results.get("message") """ MAIN FUNCTION """ def main() -> None: params = demisto.params() args = demisto.args() api_key = params.get("apikey") timeout = int(params.get("timeout", "10")) verify_certificate = not params.get("insecure", False) proxy = params.get("proxy", False) base_url = "https://api.securitytrails.com/v1/" commands = { "securitytrails-sql-query": query_sql_command, "securitytrails-sql-get-next": query_sql_get_next_command, "securitytrails-get-subdomains": domains_subdomains_command, "securitytrails-get-domain-details": domain_details_command, "securitytrails-get-tags": get_domain_tags_command, "securitytrails-get-company-details": get_company_details_command, "securitytrails-get-company-associated-ips": get_company_associated_ips_command, "securitytrails-get-domain-whois": get_whois_command, "securitytrails-get-dns-history": get_dns_history_command, "securitytrails-get-whois-history": get_whois_history_command, "securitytrails-get-ip-neighbors": get_ip_neighbors_command, "securitytrails-search-domain": domain_search_command, "securitytrails-statistics-domain": domain_statistics_command, "securitytrails-get-associated-domains": associated_domains_command, # These 2 commands have issues with the response object - error when trying to parse to JSON # 'securitytrails-get-ssl-certitficates': get_ssl_certificates, # 'securitytrails-get-ssl-certitficates-stream': get_ssl_certificates, "securitytrails-search-ip": ip_search_command, "securitytrails-statistics-ip": ip_statistics_command, "securitytrails-get-ip-whois": get_whois_command, "securitytrails-get-useragents": get_useragents_command, "domain": domain_command, } command = demisto.command() demisto.debug(f"Command being called is {command}") try: headers = {"Content-Type": "application/json", "Accept": "application/json", "APIKEY": api_key} client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy, timeout=timeout) if demisto.command() == "test-module": # This is the call made when pressing the integration Test button. result = test_module(client) return_results(result) elif command in commands: commands[command](client, args) # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()