DomainTools Deprecated
Deprecated. Use DomainTools Iris Pack instead.
Data Enrichment & Threat Intelligence · DomainTools Enterprise (Deprecated)
Details
| ID | DomainTools |
|---|---|
| Provider | DomainTools |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Supported Modules | Agentix XSIAM |
README
Domain name, DNS and Internet OSINT-based cyber threat intelligence and cybercrime forensics products and data
Configure DomainTools in Cortex
| Parameter | Required |
|---|---|
| DomainTools API URL | True |
| API Username | True |
| API Key | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | 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.
domain
Retrieve domain information.
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 | Domain name to check reputation. | Required |
| long | Should we return full response with detected URLs. | Optional |
| sampleSize | The number of samples from each type (resolutions, detections, etc.) to display for long format. | Optional |
| threshold | If number of positive detected domains is bigger than the threshold we will consider it malicious. | Optional |
| wait | Wait time between tries if we reach the API rate limit in seconds. | Optional |
| retries | Number of retries for API rate limit. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | unknown | The tested domain |
| Domain.RiskScore | unknown | The reputation returned from DomainTools |
| Domain.Malicious.Vendor | unknown | For malicious domains, the vendor that made the decision |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | unknown | The actual score. |
Command Example
#### Human Readable Output
### domainSearch
***
Search for domain based on the given parameters
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
#### Base Command
`domainSearch`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| query | (mandatory and default) Query strings. Each term in the query string must be at least three characters long. Use spaces to separate multiple terms. | Required |
| pageNumber | Sets the page of results to retrieve from the server. Each page is limited to 100 results. Default: 1. Default is 1. | Optional |
| maxLength | Limit the maximum domain character count. Default: 25. Default is 25. | Optional |
| minLength | Limit the minimum domain character count. Default: 1. Default is 1. | Optional |
| hesHyphen | (true or false) Return results with hyphens in the domain name. Default: true. | Optional |
| exclude | Terms to exclude from matching. | Optional |
| activeOnly | (true or false) Return only domains currently registered.Default: false. Possible values are: true, false. Default is false. | Optional |
| deletedOnly | (true or false) Return only domains previously registered but not currently registered. Default: false. Possible values are: true, false. Default is false. | Optional |
| anchorLeft | (true or false) Return only domains that start with the query term. Default: false. Possible values are: true, false. Default is false. | Optional |
| anchorRight | (true or false) Return only domains that end with the query term. Default: false. Possible values are: true, false. Default is false. | Optional |
| hasNumber | (true or false) Return results with numbers in the domain name. Default: true. Possible values are: false, true. Default is true. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Domain.Name | unknown | Domain found by command |
#### Command Example
Human Readable Output
reverseIP
Reverse loopkup of an IP address
Base Command
reverseIP
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | (default) specify IP address. | Optional |
| domain | If you provide a domain name, DomainTools will respond with the list of other domains that share the same IP. | Optional |
| limit | Limits the size of the domain list than can appear in a response. The limit is applied per-IP address, not for the entire request. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | unknown | Domain name |
| Domain.DNS.Address | unknown | IP address |
Command Example
#### Human Readable Output
### reverseNameServer
***
Reverse nameserver lookup
#### Base Command
`reverseNameServer`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| nameServer | (default and mandatory) specify the name of the primary or secondary name server. | Required |
| limit | Limit the size of the domain list than can appear in a response. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Domain.Name | unknown | Name of domain |
#### Command Example
Human Readable Output
reverseWhois
Reverse lookup of whois information
Base Command
reverseWhois
Input
| Argument Name | Description | Required |
|---|---|---|
| terms | (mandatory and default) List of one or more terms to search for in the Whois record, separated with the pipe character ( | ). | Required |
| exclude | Domain names with Whois records that match these terms will be excluded from the result set. Separate multiple terms with the pipe character ( | ). | Optional |
| onlyHistoricScope | Show only historic records. Possible values are: true, false. Default is false. | Optional |
| quoteMode | Only lists the size and retail price of the query if you have per-domain pricing access purchase : includes the complete list of domain names that match the query. Default is purchase. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | unknown | Name of domain |
Command Example
#### Human Readable Output
### whois
***
Provides registration details about a domain
#### Base Command
`whois`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| query | (mandatory and default) enter domain (do not use full URL). e.g. !whois [query=]demisto.com. | Required |
| parsed | Should return parsed or raw response. Default is true. Possible values are: true, false. Default is true. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Domain.Name | unknown | Requested domain name |
| Domain.Whois | unknown | Whois data |
#### Command Example
Human Readable Output
whoisHistory
Display a history of whois for a given domain
Base Command
whoisHistory
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Specify domain e.g. mycompany.com. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | unknown | Name of domain |
| Domain.WhoisHistory | unknown | Domain Whois history data |
Command Example
#### Human Readable Output
### domainProfile
***
Display profile for a given domain
#### Base Command
`domainProfile`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| domain | Specify domain e.g. mycompany.com. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
Human Readable Output
Configuration parameters
server— DomainTools API URL (required)credentials— API Usernameinsecure— Trust any certificate (not secure)proxy— Use system proxy settingskey— API Key (Deprecated)username— API UsernameintegrationReliability— Source ReliabilityfeedExpirationPolicy—feedExpirationInterval—
Commands (8)
-
domainDeprecatedRetrieve domain information.
-
domainProfileDeprecatedDisplay profile for a given domain.
-
domainSearchDeprecatedSearch for domain based on the given parameters.
-
reverseIPDeprecatedReverse loopkup of an IP address.
-
reverseNameServerDeprecatedReverse nameserver lookup.
-
reverseWhoisDeprecatedReverse lookup of whois information.
-
whoisDeprecatedProvides registration details about a domain.
-
whoisHistoryDeprecatedDisplay a history of whois for a given domain.
var toCamelCase = function(string){ var str = ' '+string.trim(); str=str.replace(/ ([a-z,A-Z])/g, function (g) { return g[1].toUpperCase(); }); return str; }; var sendRequest = function(url) { var res = http( url, { Method: 'GET', Headers: { Accept: ['application/json'] } }, params.insecure, params.proxy ); if (res.StatusCode < 200 || res.StatusCode >= 300) { throw 'Request Failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.'; } try { return JSON.parse(res.Body); } catch (err) { throw 'Failed to parse JSON'; } }; var addKeyToJson = function(cur, toAdd){ if(!cur){ return toAdd; } if(!Array.isArray(cur)){ return [cur, toAdd]; } cur.push(toAdd); return cur; }; var changeKeys = function(conv, obj){ var output = {}; for (var i in obj) { if (Object.prototype.toString.apply(obj[i]) === '[object Object]') { output[conv(i)] = changeKeys(conv, obj[i]); } else { output[conv(i)] = obj[i]; } } return output; }; var callWhoIs = function(url, query, parsed){ var whois_endpoint = `${url}/v1/${query}/whois/parsed/${encodeToURLQuery(DOMAINTOOLS_PARAMS)}` var res = sendRequest(whois_endpoint) var error = res.response.error; if(error && error.code === 206){ parsed = false; log('error code 206'); } var splitRes = res.response.whois.record.split('\n'); var md = '### DomainTools whois result for '+ query + '\n'; var resMap = {}; splitRes.forEach(function(entry){ splitEntry = entry.split(/:\s(.+)/); if(splitEntry[1]){ splitEntry[0] = toCamelCase(splitEntry[0]); md += '**'+splitEntry[0]+':** '+splitEntry[1]+'\n'; resMap[splitEntry[0]] = addKeyToJson(resMap[splitEntry[0]], splitEntry[1]); } }); var context; if(parsed === 'false'){ context = {'Domain': {'Name': res.response.record_source, 'Whois': resMap}}; }else{ context = {'Domain': {'Name': res.response.record_source, 'Whois': changeKeys(toCamelCase, res.response.parsed_whois)}}; } return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: md, EntryContext: context }; }; var scoreConv = function(score, threshold){ if(threshold){ return score>=threshold ? 3 : 1; } if(score === 0) return 1; if(score > 0 && score <=69) return 2; if(score >= 70) return 3; return -1; }; var callDomain = function(url, domain, threshold){ var api_params = Object.assign(DOMAINTOOLS_PARAMS, {"domain": domain}) var domain_reputation_endpoint = `${url}/v1/reputation/${encodeToURLQuery(api_params)}` var repRes = sendRequest(domain_reputation_endpoint) var md = 'Domain '+repRes.response.domain+' found with risk score of '+ repRes.response.risk_score +'.'; var context = { 'DBotScore' : { 'Indicator' : domain, 'Score' : scoreConv(repRes.response.risk_score, threshold), 'Type': 'domain', 'Vendor': 'domaintools', 'Reliability': params.integrationReliability } }; if(context.DBotScore.Score === 3){ addMalicious(context, outputPaths.domain, {'Name' : domain, 'RiskScore': repRes.response.risk_score ,'Malicious' : {'Vendor' : 'DomainTools'}}); } return { Type: entryTypes.note, Contents: repRes, ContentsFormat: formats.json, HumanReadable: md, ReadableContentsFormat: formats.markdown, EntryContext: context }; }; var callProfile= function(url, domain){ var domain_profile_endpoint = `${url}/v1/${domain}/${encodeToURLQuery(DOMAINTOOLS_PARAMS)}` var domRes = sendRequest(domain_profile_endpoint) return { Type: entryTypes.note, Contents: domRes, ContentsFormat: formats.json }; }; var argToUrlParam = function(string){ var map = { 'exclude':'exclude_query', 'maxLength':'max_length', 'minLength':'min_length', 'hesHyphen':'has_hyphen', 'hasNumber':'has_number', 'activeOnly':'active_only', 'deletedOnly':'deleted_only', 'anchorLeft':'anchor_left', 'anchorRight':'anchor_right', 'pageNumber':'page' }; return map[string] ? map[string] : string; }; var callDomainSearch = function(url, args){ args = changeKeys(argToUrlParam,args); args.api_username = params.username; args.api_key = params.key; var api_params = Object.assign(DOMAINTOOLS_PARAMS, args) var res = sendRequest(`${url}/v2/domain-search/${encodeToURLQuery(api_params)}`); var results = res.response.results; var md = ''; var numDomains = 0; var context = {'Domain' : []}; if(results && results.length > 0){ results.forEach(function(result){ if(result.hashad_tlds && result.hashad_tlds.length > 0){ result.hashad_tlds.forEach(function(tld){ md+='* '+result.sld+'.'+tld+'\n'; numDomains++; context.Domain.push({'Name' : result.sld+'.'+tld}); }); } }); } return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: 'Found '+numDomains +' domains:\n'+md, EntryContext: context }; }; var callReverseIP = function(url, args){ var md = ''; var context = {'Domain' : []}; var res; var addresses; var api_params = Object.assign(DOMAINTOOLS_PARAMS, {"limit": args.limit? args.limit : 50}) if(args.domain){ var reverse_ip_endpoint = `${url}/v1/${args.domain}/reverse-ip/${encodeToURLQuery(api_params)}` res = sendRequest(reverse_ip_endpoint) } else if(args.ip){ var host_domains_endpoint = `${url}/v1/${args.ip}/host-domains/${encodeToURLQuery(api_params)}` res = sendRequest(host_domains_endpoint) } addresses = res.response.ip_addresses; if(!Array.isArray(addresses)){ addresses = [addresses]; } addresses.forEach(function(address){ md+= '\nFound ' + address.domain_count + ' domains for ' +address.ip_address + '\n'; address.domain_names.forEach(function(domain){ md += '* ' + domain + '\n'; context.Domain.push({'Name': domain, 'DNS' : {'Address' : address.ip_address}}); }); }); return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: md, EntryContext: context }; } var callReverseNameServer = function(url, server, limit){ var api_params = Object.assign(DOMAINTOOLS_PARAMS, {"limit": limit? limit : 50}) var reverse_ns_endpoint = `${url}/v1/${server}/name-server-domains/${encodeToURLQuery(api_params)}` var res = sendRequest(reverse_ns_endpoint) var md = 'Found ' + res.response.primary_domains.length + ' domains\n'; var context = {'Domain' : []}; res.response.primary_domains.forEach(function(domain){ md += '* ' + domain + '\n'; context.Domain.push({'Name' : domain}); }); return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: md, EntryContext: context }; } var callReverseWhoIs = function(url, args){ args.api_username = params.username; args.api_key = params.key; args.mode = args.quoteMode; args.scope = 'current'; if(args.onlyHistoricScope === 'true'){ args.scope = 'historic'; } delete args.quoteModel delete args.onlyHistoricScope; var api_params = Object.assign(DOMAINTOOLS_PARAMS, args) var reverse_whois_endpoint = `${url}/v1/reverse-whois/${encodeToURLQuery(api_params)}` var res = sendRequest(reverse_whois_endpoint); var context = {'Domain' : []}; var md = 'Found '+res.response.domains.length+ ' domains: \n'; res.response.domains.forEach(function(domain){ md += '* ' + domain + '\n'; context.Domain.push({'Name' : domain}); }); return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: md, EntryContext: context }; } /*http://api.domaintools.com/v1/domaintools.com/whois/history/*/ var callWhoisHistory = function(url, domain){ var whois_history_endpoint = `${url}/v1/${domain}/whois/history/${encodeToURLQuery(DOMAINTOOLS_PARAMS)}` var res = sendRequest(whois_history_endpoint) var splitRecord; var context = {'Domain' : {'Name' : domain, 'WhoisHistory' : []}}; var md = ''; var entryContext, record; res.response.history.forEach(function(entry){ entryContext = {}; record = entry.whois.record; if(record){ var splitRecord = record.split('\n'); splitRecord.forEach(function(pair){ splitEntry = pair.split(/:\s(.+)/); if(splitEntry[1]){ splitEntry[0] = toCamelCase(splitEntry[0]); md += '**'+splitEntry[0]+':** '+splitEntry[1]+'\n'; entryContext[splitEntry[0]] = splitEntry[1]; } }); } context.Domain.WhoisHistory.push(entryContext); }); return { Type: entryTypes.note, Contents: res, ContentsFormat: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: md, EntryContext: context }; } var url = params.server.replace(/[\/]+$/, ''); params.key = params.key || params.credentials.password params.username = params.username || params.credentials.identifier if (!params.key || !params.username) { throw 'Username and API key must be provided.' } const DOMAINTOOLS_PARAMS = { "api_username": params.username, "api_key": params.key, "app_partner": "cortex_xsoar", "app_name": "enterprise_for_xsoar", "app_version": "1" } switch (command) { case 'test-module': var account_url = `${url}/v1/account/${encodeToURLQuery(DOMAINTOOLS_PARAMS)}` var res = sendRequest(account_url) if(res.response.error){ log('Something went wrong - error code ' + error.code); } return 'ok'; case 'domain': return callDomain(url, args.domain, args.threshold); case 'domainSearch': return callDomainSearch(url, args); case 'reverseIP': return callReverseIP(url, args); case 'reverseNameServer': return callReverseNameServer(url, args.nameServer, args.limit); case 'reverseWhois': return callReverseWhoIs(url, args); case 'whois': return callWhoIs(url, args.query, args.parsed); case 'whoisHistory': return callWhoisHistory(url, args.domain); case 'domainProfile': return callProfile(url, args.domain); }