diff --git a/Packs/IPQualityScore/.pack-ignore b/Packs/IPQualityScore/.pack-ignore
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/Packs/IPQualityScore/.secrets-ignore b/Packs/IPQualityScore/.secrets-ignore
new file mode 100644
index 000000000000..c49f45ea6fbb
--- /dev/null
+++ b/Packs/IPQualityScore/.secrets-ignore
@@ -0,0 +1,4 @@
+15.99.160.255
+172.217.11.142
+someone@gmail.com
+https://ipqualityscore.com
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.py b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.py
new file mode 100644
index 000000000000..c82958e08b33
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.py
@@ -0,0 +1,247 @@
+import urllib.parse
+import demistomock as demisto
+from CommonServerPython import *
+from CommonServerUserPython import *
+''' IMPORTS '''
+
+# Disable insecure warnings
+requests.packages.urllib3.disable_warnings()
+
+''' CONSTANTS '''
+DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
+
+
+class Client(BaseClient):
+
+ def get_ip_reputation(self, ip: str) -> Dict[str, Any]:
+ return self._http_request(
+ method='GET',
+ url_suffix=f'{ip}'
+ )
+
+ def get_email_reputation(self, email: str) -> Dict[str, Any]:
+ return self._http_request(
+ method='GET',
+ url_suffix=f'{email}'
+ )
+
+ def get_url_reputation(self, url: str) -> Dict[str, Any]:
+ return self._http_request(
+ method='GET',
+ url_suffix=f'{url}'
+ )
+
+
+def get_reputation_reliability(reliability):
+ if reliability == "A+ - 3rd party enrichment":
+ return DBotScoreReliability.A_PLUS
+ if reliability == "A - Completely reliable":
+ return DBotScoreReliability.A
+ if reliability == "B - Usually reliable":
+ return DBotScoreReliability.B
+ if reliability == "C - Fairly reliable":
+ return DBotScoreReliability.C
+ if reliability == "D - Not usually reliable":
+ return DBotScoreReliability.D
+ if reliability == "E - Unreliable":
+ return DBotScoreReliability.E
+ if reliability == "F - Reliability cannot be judged":
+ return DBotScoreReliability.F
+
+
+def test_module(client):
+ result = client.get_ip_reputation("8.8.8.8")
+ if result.get('success', False):
+ return 'ok'
+ else:
+ return result.get("message", result)
+
+
+def ip_command(client, args, ip_suspicious_score_threshold, ip_malicious_score_threshold, reliability):
+ ips = argToList(args.get("ip"), ",")
+ results = []
+ for ip in ips:
+ result = client.get_ip_reputation(ip)
+ result['address'] = ip
+
+ human_readable = tableToMarkdown(f"IPQualityScore Results for {ip}", result, result.keys())
+
+ if result.get('fraud_score', 0) >= ip_malicious_score_threshold:
+ score = 3
+ elif result.get('fraud_score', 0) >= ip_suspicious_score_threshold:
+ score = 2
+ else:
+ score = 0
+
+ reputation = Common.DBotScore(
+ indicator=ip,
+ indicator_type=DBotScoreType.IP,
+ score=score,
+ integration_name='IPQualityScore',
+ reliability=get_reputation_reliability(reliability)
+ )
+
+ ip_context = Common.IP(
+ ip=ip,
+ dbot_score=reputation,
+ asn=result.get('ASN'),
+ hostname=result.get('host'),
+ geo_country=result.get('country_code'),
+ geo_longitude=result.get('longitude'),
+ geo_latitude=result.get('latitude')
+ )
+
+ results.append(CommandResults(
+ readable_output=human_readable,
+ indicator=ip_context,
+ outputs_prefix='IPQualityScore.IP',
+ outputs_key_field='address',
+ outputs=result,
+ raw_response=result))
+ return results
+
+
+def email_command(client, args, email_suspicious_score_threshold, email_malicious_score_threshold, reliability):
+ emails = argToList(args.get("email"), ",")
+ results = []
+ for email in emails:
+ result = client.get_email_reputation(email)
+ result['address'] = email
+
+ human_readable = tableToMarkdown(f"IPQualityScore Results for {email}", result, result.keys())
+
+ if result.get('fraud_score', 0) >= email_malicious_score_threshold:
+ score = 3
+ elif result.get('fraud_score', 0) >= email_suspicious_score_threshold:
+ score = 2
+ else:
+ score = 0
+
+ reputation = Common.DBotScore(
+ indicator=email,
+ indicator_type=DBotScoreType.EMAIL,
+ score=score,
+ integration_name='IPQualityScore',
+ reliability=get_reputation_reliability(reliability)
+ )
+
+ ip_context = Common.EMAIL(
+ address=email,
+ dbot_score=reputation,
+ domain=result.get('sanitized_email', email).split("@")[-1]
+ )
+
+ results.append(CommandResults(
+ readable_output=human_readable,
+ indicator=ip_context,
+ outputs_prefix='IPQualityScore.Email',
+ outputs_key_field='address',
+ outputs=result,
+ raw_response=result))
+ return results
+
+
+def url_command(client, args, url_suspicious_score_threshold, url_malicious_score_threshold, reliability):
+ urls = argToList(args.get("url"), ",")
+ results = []
+ for url in urls:
+ url_encoded = urllib.parse.quote(url, safe="")
+ result = client.get_url_reputation(url_encoded)
+ result['url'] = url
+
+ human_readable = tableToMarkdown(f"IPQualityScore Results for {url}", result, result.keys())
+
+ if result.get('fraud_score', 0) >= url_malicious_score_threshold:
+ score = 3
+ elif result.get('fraud_score', 0) >= url_suspicious_score_threshold:
+ score = 2
+ else:
+ score = 0
+
+ reputation = Common.DBotScore(
+ indicator=url,
+ indicator_type=DBotScoreType.URL,
+ score=score,
+ integration_name='IPQualityScore',
+ reliability=get_reputation_reliability(reliability)
+ )
+
+ ip_context = Common.URL(
+ url=url,
+ dbot_score=reputation
+ )
+
+ results.append(CommandResults(
+ readable_output=human_readable,
+ indicator=ip_context,
+ outputs_prefix='IPQualityScore.Url',
+ outputs_key_field='url',
+ outputs=result,
+ raw_response=result))
+ return results
+
+
+def main():
+ """
+ PARSE AND VALIDATE INTEGRATION PARAMS
+ """
+ apikey = demisto.params().get('apikey')
+
+ # get the service API url
+ base_url_ip = urljoin('https://ipqualityscore.com/api/json/ip/', apikey)
+ base_url_email = urljoin('https://ipqualityscore.com/api/json/email/', apikey)
+ base_url_url = urljoin('https://ipqualityscore.com/api/json/url/', apikey)
+
+ verify_certificate = not demisto.params().get('insecure', False)
+
+ proxy = demisto.params().get('proxy', False)
+ LOG(f'Command being called is {demisto.command()}')
+ try:
+ if demisto.command() == 'test-module':
+ # This is the call made when pressing the integration Test button.
+ client = Client(
+ base_url=base_url_ip,
+ verify=verify_certificate,
+ proxy=proxy)
+ result = test_module(client)
+ demisto.results(result)
+
+ elif demisto.command() == 'ip':
+ ip_suspicious_score_threshold = int(demisto.params().get('ip_suspicious_score_threshold'))
+ ip_malicious_score_threshold = int(demisto.params().get('ip_malicious_score_threshold'))
+ reliability = demisto.params().get('feedReliability')
+ client = Client(
+ base_url=base_url_ip,
+ verify=verify_certificate,
+ proxy=proxy)
+ return_results(ip_command(client, demisto.args(), ip_suspicious_score_threshold,
+ ip_malicious_score_threshold, reliability))
+
+ elif demisto.command() == 'email':
+ email_suspicious_score_threshold = int(demisto.params().get('email_suspicious_score_threshold'))
+ email_malicious_score_threshold = int(demisto.params().get('email_malicious_score_threshold'))
+ reliability = demisto.params().get('feedReliability')
+ client = Client(
+ base_url=base_url_email,
+ verify=verify_certificate,
+ proxy=proxy)
+ return_results(email_command(client, demisto.args(), email_suspicious_score_threshold,
+ email_malicious_score_threshold, reliability))
+
+ elif demisto.command() == 'url':
+ url_suspicious_score_threshold = int(demisto.params().get('url_suspicious_score_threshold'))
+ url_malicious_score_threshold = int(demisto.params().get('url_malicious_score_threshold'))
+ reliability = demisto.params().get('feedReliability')
+ client = Client(
+ base_url=base_url_url,
+ verify=verify_certificate,
+ proxy=proxy)
+ return_results(url_command(client, demisto.args(), url_suspicious_score_threshold,
+ url_malicious_score_threshold, reliability))
+ # Log exceptions
+ except Exception as e:
+ return_error(f'Failed to execute {demisto.command()} command. Error: {str(e)}')
+
+
+if __name__ in ('__main__', '__builtin__', 'builtins'):
+ main()
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.yml b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.yml
new file mode 100644
index 000000000000..ab77e566f425
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore.yml
@@ -0,0 +1,433 @@
+category: Data Enrichment & Threat Intelligence
+commonfields:
+ id: IPQualityScore
+ version: -1
+fromversion: 5.0.0
+configuration:
+- display: API Key
+ name: apikey
+ required: true
+ type: 4
+- display: Trust any certificate (not secure)
+ name: insecure
+ required: false
+ type: 8
+- display: Use system proxy settings
+ name: proxy
+ required: false
+ type: 8
+- additionalinfo: Threshold for fraud score from IP lookup to be marked as suspicious
+ defaultvalue: '75'
+ display: IP Suspicious Score Threshold
+ hidden: false
+ name: ip_suspicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Threshold for fraud score from IP lookup to be marked as malicious
+ defaultvalue: '90'
+ display: IP Malicious Score Threshold
+ hidden: false
+ name: ip_malicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Threshold for fraud score from Email lookup to be marked as suspicious
+ defaultvalue: '75'
+ display: Email Suspicious Score Threshold
+ hidden: false
+ name: email_suspicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Threshold for fraud score from Email lookup to be marked as malicious
+ defaultvalue: '90'
+ display: Email Malicious Score Threshold
+ hidden: false
+ name: email_malicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Threshold for fraud score from Url lookup to be marked as suspicious
+ defaultvalue: '75'
+ display: Url Suspicious Score Threshold
+ hidden: false
+ name: url_suspicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Threshold for fraud score from Url lookup to be marked as malicious
+ defaultvalue: '90'
+ display: Url Malicious Score Threshold
+ hidden: false
+ name: url_malicious_score_threshold
+ required: false
+ type: 0
+- additionalinfo: Reliability of the source providing the intelligence data
+ defaultvalue: F - Reliability cannot be judged
+ display: Source Reliability
+ name: feedReliability
+ options:
+ - A - Completely reliable
+ - B - Usually reliable
+ - C - Fairly reliable
+ - D - Not usually reliable
+ - E - Unreliable
+ - F - Reliability cannot be judged
+ required: true
+ type: 15
+description: Proactively Prevent Fraud
+display: IPQualityScore
+name: IPQualityScore
+script:
+ commands:
+ - arguments:
+ - default: true
+ description: IP address to check
+ isArray: true
+ name: ip
+ required: true
+ secret: false
+ deprecated: false
+ description: Runs reputation on IPs.
+ execution: false
+ name: ip
+ outputs:
+ - contextPath: IPQualityScore.IP.success
+ type: Boolean
+ description: 'Was the request successful?'
+ - contextPath: IPQualityScore.IP.message
+ type: String
+ description: 'A generic status message, either success or some form of an error notice.'
+ - contextPath: IPQualityScore.IP.fraud_score
+ type: Number
+ description: 'The overall fraud score of the user based on the IP, user agent, language, and any other optionally passed variables. Fraud Scores >= 75 are suspicious, but not necessarily fraudulent. We recommend flagging or blocking traffic with Fraud Scores >= 85, but you may find it beneficial to use a higher or lower threshold.'
+ - contextPath: IPQualityScore.IP.country_code
+ type: String
+ description: 'Two character country code of IP address or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.region
+ type: String
+ description: 'Region (state) of IP address if available or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.city
+ type: String
+ description: 'City of IP address if available or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.ISP
+ type: String
+ description: 'ISP if one is known. Otherwise "N/A".'
+ - contextPath: IPQualityScore.IP.ASN
+ type: Number
+ description: 'Autonomous System Number if one is known. Null if nonexistent.'
+ - contextPath: IPQualityScore.IP.organization
+ type: String
+ description: 'Organization if one is known. Can be parent company or sub company of the listed ISP. Otherwise "N/A".'
+ - contextPath: IPQualityScore.IP.latitude
+ type: Number
+ description: 'Latitude of IP address if available or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.longitude
+ type: Number
+ description: 'Longitude of IP address if available or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.is_crawler
+ type: Boolean
+ description: 'Is this IP associated with being a confirmed crawler from a mainstream search engine such as Googlebot, Bingbot, Yandex, etc. based on hostname or IP address verification.'
+ - contextPath: IPQualityScore.IP.timezone
+ type: String
+ description: 'Timezone of IP address if available or "N/A" if unknown.'
+ - contextPath: IPQualityScore.IP.mobile
+ type: Boolean
+ description: 'Is this user agent a mobile browser? (will always be false if the user agent is not passed in the API request)'
+ - contextPath: IPQualityScore.IP.host
+ type: String
+ description: 'Hostname of the IP address if one is available.'
+ - contextPath: IPQualityScore.IP.proxy
+ type: Boolean
+ description: 'Is this IP address suspected to be a proxy? (SOCKS, Elite, Anonymous, VPN, Tor, etc.)'
+ - contextPath: IPQualityScore.IP.vpn
+ type: Boolean
+ description: 'Is this IP suspected of being a VPN connection? This can include data center ranges which can become active VPNs at any time. The "proxy" status will always be true when this value is true.'
+ - contextPath: IPQualityScore.IP.tor
+ type: Boolean
+ description: 'Is this IP suspected of being a TOR connection? This can include previously active TOR nodes and exits which can become active TOR exits at any time. The "proxy" status will always be true when this value is true.'
+ - contextPath: IPQualityScore.IP.active_vpn
+ type: Boolean
+ description: 'Premium Account Feature - Identifies active VPN connections used by popular VPN services and private VPN servers.'
+ - contextPath: IPQualityScore.IP.active_tor
+ type: Boolean
+ description: 'Premium Account Feature - Identifies active TOR exits on the TOR network.'
+ - contextPath: IPQualityScore.IP.recent_abuse
+ type: Boolean
+ description: 'This value will indicate if there has been any recently verified abuse across our network for this IP address. Abuse could be a confirmed chargeback, compromised device, fake app install, or similar malicious behavior within the past few days.'
+ - contextPath: IPQualityScore.IP.bot_status
+ type: Boolean
+ description: 'Premium Account Feature - Indicates if bots or non-human traffic has recently used this IP address to engage in automated fraudulent behavior. Provides stronger confidence that the IP address is suspicious.'
+ - contextPath: IPQualityScore.IP.connection_type
+ type: String
+ description: 'Classification of the IP address connection type as "Residential", "Corporate", "Education", "Mobile", or "Data Center".'
+ - contextPath: IPQualityScore.IP.abuse_velocity
+ type: String
+ description: 'Premium Account Feature - How frequently the IP address is engaging in abuse across the IPQS threat network. Values can be "high", "medium", "low", or "none". Can be used in combination with the Fraud Score to identify bad behavior.'
+ - contextPath: IPQualityScore.IP.request_id
+ type: String
+ description: 'A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice.'
+ - contextPath: IPQualityScore.IP.address
+ type: String
+ description: 'The IP address that was queried.'
+ - contextPath: DBotScore.Indicator
+ type: String
+ description: 'The indicator that was tested.'
+ - contextPath: DBotScore.Score
+ type: Number
+ description: 'The actual score.'
+ - contextPath: DBotScore.Type
+ type: String
+ description: 'The indicator type.'
+ - contextPath: DBotScore.Vendor
+ type: String
+ description: 'The vendor used to calculate the score.'
+ - contextPath: IP.Address
+ type: string
+ description: 'The IP address.'
+ - contextPath: IP.ASN
+ type: string
+ description: 'The autonomous system name for the IP address, for example: "AS8948".'
+ - contextPath: IP.Hostname
+ type: string
+ description: 'The hostname that is mapped to this IP address.'
+ - contextPath: IP.Geo.Country
+ type: string
+ description: 'The country in which the IP address is located.'
+ - contextPath: IP.Geo.Description
+ type: string
+ description: 'Additional information about the location.'
+ - contextPath: IP.Malicious.Vendor
+ type: string
+ description: 'The vendor reporting the IP address as malicious.'
+ - contextPath: IP.Malicious.Description
+ type: string
+ description: 'A description explaining why the IP address was reported as malicious.'
+ - arguments:
+ - default: true
+ description: Email address to check
+ isArray: true
+ name: email
+ required: true
+ secret: false
+ deprecated: false
+ description: Runs reputation on email addresses.
+ execution: false
+ name: email
+ outputs:
+ - contextPath: IPQualityScore.Email.message
+ type: String
+ description: 'A generic status message, either success or some form of an error notice.'
+ - contextPath: IPQualityScore.Email.success
+ type: Boolean
+ description: 'Was the request successful?'
+ - contextPath: IPQualityScore.Email.valid
+ type: Boolean
+ description: 'Does this email address appear valid?'
+ - contextPath: IPQualityScore.Email.disposable
+ type: Boolean
+ description: 'Is this email suspected of belonging to a temporary or disposable mail service? Usually associated with fraudsters and scammers.'
+ - contextPath: IPQualityScore.Email.smtp_score
+ type: Number
+ description: 'Validity score of email server''s SMTP setup. Range: "-1" - "3". Scores above "-1" can be associated with a valid email.
+ -1 = invalid email address;
+ 0 = mail server exists, but is rejecting all mail;
+ 1 = mail server exists, but is showing a temporary error;
+ 2 = mail server exists, but accepts all email;
+ 3 = mail server exists and has verified the email address.'
+ - contextPath: IPQualityScore.Email.overall_score
+ type: Number
+ description: 'Overall email validity score. Range: "0" - "4". Scores above "1" can be associated with a valid email.
+ 0 = invalid email address;
+ 1 = dns valid, unreachable mail server;
+ 2 = dns valid, temporary mail rejection error;
+ 3 = dns valid, accepts all mail;
+ 4 = dns valid, verified email exists.'
+ - contextPath: IPQualityScore.Email.first_name
+ type: String
+ description: 'Suspected first name based on email. Returns "CORPORATE" if the email is suspected of being a generic company email. Returns "UNKNOWN" if the first name was not determinable.'
+ - contextPath: IPQualityScore.Email.generic
+ type: Boolean
+ description: 'Is this email suspected as being a catch all or shared email for a domain? ("admin@", "webmaster@", "newsletter@", "sales@", "contact@", etc.)'
+ - contextPath: IPQualityScore.Email.common
+ type: Boolean
+ description: 'Is this email from a common email provider? ("gmail.com", "yahoo.com", "hotmail.com", etc.)'
+ - contextPath: IPQualityScore.Email.dns_valid
+ type: Boolean
+ description: 'Does the email''s hostname have valid DNS entries? Partial indication of a valid email.'
+ - contextPath: IPQualityScore.Email.honeypot
+ type: Boolean
+ description: 'Is this email believed to be a "honeypot" or "SPAM trap"? Bulk mail sent to these emails increases your risk of being blacklisted by large ISPs & ending up in the spam folder.'
+ - contextPath: IPQualityScore.Email.deliverability
+ type: String
+ description: 'How likely is this email to be delivered to the user and land in their mailbox. Values can be "high", "medium", or "low". '
+ - contextPath: IPQualityScore.Email.frequent_complainer
+ type: Boolean
+ description: 'Indicates if this email frequently unsubscribes from marketing lists or reports email as SPAM.'
+ - contextPath: IPQualityScore.Email.spam_trap_score
+ type: String
+ description: 'Confidence level of the email address being an active SPAM trap. Values can be "high", "medium", "low", or "none". We recommend scrubbing emails with "high" or "medium" statuses. Avoid "low" emails whenever possible for any promotional mailings.'
+ - contextPath: IPQualityScore.Email.catch_all
+ type: Boolean
+ description: 'Is this email likely to be a "catch all" where the mail server verifies all emails tested against it as valid? It is difficult to determine if the address is truly valid in these scenarios, since the email''s server will not confirm the account''s status.'
+ - contextPath: IPQualityScore.Email.timed_out
+ type: Boolean
+ description: 'Did the connection to the mail service provider timeout during the verification? If so, we recommend increasing the "timeout" variable above the default 7 second value. Lookups that timeout with a "valid" result as false are most likely false and should be not be trusted.'
+ - contextPath: IPQualityScore.Email.suspect
+ type: Boolean
+ description: 'This value indicates if the mail server is currently replying with a temporary error and unable to verify the email address. This status will also be true for "catch all" email addresses as defined below. If this value is true, then we suspect the "valid" result may be tainted and there is not a guarantee that the email address is truly valid.'
+ - contextPath: IPQualityScore.Email.recent_abuse
+ type: Boolean
+ description: 'This value will indicate if there has been any recently verified abuse across our network for this email address. Abuse could be a confirmed chargeback, fake signup, compromised device, fake app install, or similar malicious behavior within the past few days.'
+ - contextPath: IPQualityScore.Email.fraud_score
+ type: Number
+ description: 'The overall Fraud Score of the user based on the email''s reputation and recent behavior across the IPQS threat network. Fraud Scores >= 75 are suspicious, but not necessarily fraudulent.'
+ - contextPath: IPQualityScore.Email.suggested_domain
+ type: String
+ description: 'Default value is "N/A". Indicates if this email''s domain should in fact be corrected to a popular mail service. This field is useful for catching user typos. For example, an email address with "gmai.com", would display a suggested domain of "gmail.com". This feature supports all major mail service providers.'
+ - contextPath: IPQualityScore.Email.leaked
+ type: Boolean
+ description: 'Was this email address associated with a recent database leak from a third party? Leaked accounts pose a risk as they may have become compromised during a database breach. '
+ - contextPath: IPQualityScore.Email.domain_age.human
+ type: Date
+ description: 'A human description of when this domain was registered (E.g. 3 months ago).'
+ - contextPath: IPQualityScore.Email.domain_age.timestamp
+ type: Number
+ description: 'The unix time since epoch when this domain was first registered. (E.g. 1568061634).'
+ - contextPath: IPQualityScore.Email.domain_age.iso
+ type: Date
+ description: 'The time this domain was registered in ISO8601 format (E.g. 2019-09-09T16:40:34-04:00).'
+ - contextPath: IPQualityScore.Email.first_seen.human
+ type: Date
+ description: 'A human description of the email address age, using an estimation of the email creation date when IPQS first discovered this email address (E.g. 3 months ago).'
+ - contextPath: IPQualityScore.Email.first_seen.timestamp
+ type: Number
+ description: 'The unix time since epoch when this email was first analyzed by IPQS (E.g. 1568061634).'
+ - contextPath: IPQualityScore.Email.first_seen.iso
+ type: Date
+ description: 'The time this email was first analyzed by IPQS in ISO8601 format (E.g. 2019-09-09T16:40:34-04:00).'
+ - contextPath: IPQualityScore.Email.sanitized_email
+ type: String
+ description: 'Sanitized email address with all aliases and masking removed, such as multiple periods for Gmail.com.'
+ - contextPath: IPQualityScore.Email.request_id
+ type: String
+ description: 'A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice.'
+ - contextPath: IPQualityScore.Email.address
+ type: String
+ description: 'The email address that was queried.'
+ - contextPath: DBotScore.Indicator
+ type: String
+ description: 'The indicator that was tested.'
+ - contextPath: DBotScore.Score
+ type: Number
+ description: 'The actual score.'
+ - contextPath: DBotScore.Type
+ type: String
+ description: 'The indicator type.'
+ - contextPath: DBotScore.Vendor
+ type: String
+ description: 'The vendor used to calculate the score.'
+ - arguments:
+ - default: true
+ description: Url address to check
+ isArray: true
+ name: url
+ required: true
+ secret: false
+ deprecated: false
+ description: Runs reputation on URLs.
+ execution: false
+ name: url
+ outputs:
+ - contextPath: IPQualityScore.Url.message
+ type: String
+ description: 'A generic status message, either success or some form of an error notice.'
+ - contextPath: IPQualityScore.Url.success
+ type: Boolean
+ description: 'Was the request successful?'
+ - contextPath: IPQualityScore.Url.unsafe
+ type: Boolean
+ description: 'Is this domain suspected of being unsafe due to phishing, malware, spamming, or abusive behavior? View the confidence level by analyzing the "risk_score".'
+ - contextPath: IPQualityScore.Url.domain
+ type: String
+ description: 'Domain name of the final destination URL of the scanned link, after following all redirects.'
+ - contextPath: IPQualityScore.Url.ip_address
+ type: String
+ description: 'The IP address corresponding to the server of the domain name.'
+ - contextPath: IPQualityScore.Url.server
+ type: String
+ description: 'The server banner of the domain''s IP address. For example: "nginx/1.16.0". Value will be "N/A" if unavailable.'
+ - contextPath: IPQualityScore.Url.content_type
+ type: String
+ description: 'MIME type of URL''s content. For example "text/html; charset=UTF-8". Value will be "N/A" if unavailable.'
+ - contextPath: IPQualityScore.Url.status_code
+ type: Number
+ description: 'HTTP Status Code of the URL''s response. This value should be "200" for a valid website. Value is "0" if URL is unreachable.'
+ - contextPath: IPQualityScore.Url.page_size
+ type: Number
+ description: 'Total number of bytes to download the URL''s content. Value is "0" if URL is unreachable.'
+ - contextPath: IPQualityScore.Url.domain_rank
+ type: Number
+ description: 'Estimated popularity rank of website globally. Value is "0" if the domain is unranked or has low traffic.'
+ - contextPath: IPQualityScore.Url.dns_valid
+ type: Boolean
+ description: 'The domain of the URL has valid DNS records.'
+ - contextPath: IPQualityScore.Url.parking
+ type: Boolean
+ description: 'Is the domain of this URL currently parked with a for sale notice?'
+ - contextPath: IPQualityScore.Url.spamming
+ type: Boolean
+ description: 'Is the domain of this URL associated with email SPAM or abusive email addresses?'
+ - contextPath: IPQualityScore.Url.malware
+ type: Boolean
+ description: 'Is this URL associated with malware or viruses?'
+ - contextPath: IPQualityScore.Url.phishing
+ type: Boolean
+ description: 'Is this URL associated with malicious phishing behavior?'
+ - contextPath: IPQualityScore.Url.suspicious
+ type: Boolean
+ description: 'Is this URL suspected of being malicious or used for phishing or abuse? Use in conjunction with the "risk_score" as a confidence level.'
+ - contextPath: IPQualityScore.Url.risk_score
+ type: Number
+ description: 'The IPQS risk score which estimates the confidence level for malicious URL detection. Risk Scores 85+ are high risk, while Risk Scores = 100 are confirmed as accurate.'
+ - contextPath: IPQualityScore.Url.request_id
+ type: String
+ description: 'A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice.'
+ - contextPath: IPQualityScore.Url.url
+ type: String
+ description: 'The URL being queried.'
+ - contextPath: IPQualityScore.Url.adult
+ type: Boolean
+ description: 'Is this URL or domain hosting dating or adult content?'
+ - contextPath: IPQualityScore.Url.domain_age.human
+ type: Date
+ description: 'A human description of when this domain was registered (E.g. 3 months ago).'
+ - contextPath: IPQualityScore.Url.domain_age.timestamp
+ type: Number
+ description: 'The unix time since epoch when this domain was first registered (E.g. 1568061634).'
+ - contextPath: IPQualityScore.Url.domain_age.iso
+ type: Date
+ description: 'The time this domain was registered in ISO8601 format (E.g. 2019-09-09T16:40:34-04:00).'
+ - contextPath: DBotScore.Indicator
+ type: String
+ description: 'The indicator that was tested.'
+ - contextPath: DBotScore.Score
+ type: Number
+ description: 'The actual score.'
+ - contextPath: DBotScore.Type
+ type: String
+ description: 'The indicator type.'
+ - contextPath: DBotScore.Vendor
+ type: String
+ description: 'The vendor used to calculate the score.'
+ - contextPath: URL.Data
+ description: The URL
+ type: String
+ - contextPath: URL.Malicious.Vendor
+ description: The vendor reporting the URL as malicious.
+ type: String
+ dockerimage: demisto/python3:3.9.4.19537
+ feed: false
+ isfetch: false
+ longRunning: false
+ longRunningPort: false
+ runonce: false
+ script: '-'
+ subtype: python3
+ type: python
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_description.md b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_description.md
new file mode 100644
index 000000000000..0519ecba6ea9
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_description.md
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_image.png b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_image.png
new file mode 100644
index 000000000000..3aa5d0928468
Binary files /dev/null and b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_image.png differ
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_test.py b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_test.py
new file mode 100644
index 000000000000..0bd06b1e6acf
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/IPQualityScore_test.py
@@ -0,0 +1,61 @@
+import json
+import io
+
+
+def util_load_json(path):
+ with io.open(path, mode='r', encoding='utf-8') as f:
+ return json.loads(f.read())
+
+
+def test_ip_command(requests_mock):
+ from IPQualityScore import Client, ip_command
+ mock_response = util_load_json('test_data/ip_response.json')
+ requests_mock.get('https://ipqualityscore.com/api/json/ip/api_key_here/15.99.160.255', json=mock_response)
+ client = Client(
+ base_url='https://ipqualityscore.com/api/json/ip/api_key_here',
+ verify=False)
+ ip_suspicious_score_threshold = 75
+ ip_malicious_score_threshold = 85
+ reliability = "A - Completely reliable"
+ args = {
+ "ip": "15.99.160.255"
+ }
+ response = ip_command(client, args, ip_suspicious_score_threshold, ip_malicious_score_threshold, reliability)
+ assert response[0].outputs_prefix == 'IPQualityScore.IP'
+
+
+def test_email_command(requests_mock):
+ from IPQualityScore import Client, email_command
+ mock_response = util_load_json('test_data/email_response.json')
+ requests_mock.get('https://ipqualityscore.com/api/json/email/api_key_here/someone@gmail.com', json=mock_response)
+ client = Client(
+ base_url='https://ipqualityscore.com/api/json/email/api_key_here',
+ verify=False)
+ email_suspicious_score_threshold = 75
+ email_malicious_score_threshold = 85
+ reliability = "A - Completely reliable"
+ args = {
+ "email": "someone@gmail.com"
+ }
+ response = email_command(client, args, email_suspicious_score_threshold, email_malicious_score_threshold,
+ reliability)
+ assert response[0].outputs_prefix == 'IPQualityScore.Email'
+
+
+def test_url_command(requests_mock):
+ from IPQualityScore import Client, url_command
+ mock_response = util_load_json('test_data/url_response.json')
+ requests_mock.get('https://ipqualityscore.com/api/json/url/api_key_here/https%3A%2F%2Fgoogle.com',
+ json=mock_response)
+ client = Client(
+ base_url='https://ipqualityscore.com/api/json/url/api_key_here',
+ verify=False)
+ url_suspicious_score_threshold = 75
+ url_malicious_score_threshold = 85
+ reliability = "A - Completely reliable"
+ args = {
+ "url": "https://google.com"
+ }
+ response = url_command(client, args, url_suspicious_score_threshold, url_malicious_score_threshold,
+ reliability)
+ assert response[0].outputs_prefix == 'IPQualityScore.Url'
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/README.md b/Packs/IPQualityScore/Integrations/IPQualityScore/README.md
new file mode 100644
index 000000000000..07b907757a10
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/README.md
@@ -0,0 +1,387 @@
+Proactively Prevent Fraud
+This integration was integrated and tested with version 1.0 of IPQualityScore
+## Configure IPQualityScore on Cortex XSOAR
+
+1. Navigate to **Settings** > **Integrations** > **Servers & Services**.
+2. Search for IPQualityScore.
+3. Click **Add instance** to create and configure a new integration instance.
+
+ | **Parameter** | **Description** | **Required** |
+ | --- | --- | --- |
+ | API Key | See guide below for getting an API key. | True |
+ | Trust any certificate (not secure) | | False |
+ | Use system proxy settings | | False |
+ | IP Suspicious Score Threshold | Threshold for fraud score from IP lookup to be marked as suspicious | False |
+ | IP Malicious Score Threshold | Threshold for fraud score from IP lookup to be marked as malicious | False |
+ | Email Suspicious Score Threshold | Threshold for fraud score from Email lookup to be marked as suspicious | False |
+ | Email Malicious Score Threshold | Threshold for fraud score from Email lookup to be marked as malicious | False |
+ | Url Suspicious Score Threshold | Threshold for fraud score from Url lookup to be marked as suspicious | False |
+ | Url Malicious Score Threshold | Threshold for fraud score from Url lookup to be marked as malicious | False |
+ | Source Reliability | Reliability of the source providing the intelligence data | True |
+
+4. Click **Test** to validate the URLs, token, and connection.
+## Commands
+You can execute these commands from the Cortex XSOAR 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.
+### ip
+***
+Runs reputation on IPs.
+
+#### Aquiring an API key
+
+1. Go to https://www.ipqualityscore.com/create-account and register for an account. Accounts are free and come with 5,000 API lookups each month. Additional lookups can be purchased one time or on a monthly basis.
+2. Once you've registered, login then go to https://www.ipqualityscore.com/documentation/proxy-detection/overview and your API key will be listed under the "Private Key" subheading.
+
+
+#### Base Command
+
+`ip`
+#### Input
+
+| **Argument Name** | **Description** | **Required** |
+| --- | --- | --- |
+| ip | IP address to check. | Required |
+
+
+#### Context Output
+
+| **Path** | **Type** | **Description** |
+| --- | --- | --- |
+| IPQualityScore.IP.success | Boolean | Was the request successful? |
+| IPQualityScore.IP.message | String | A generic status message, either success or some form of an error notice. |
+| IPQualityScore.IP.fraud_score | Number | The overall fraud score of the user based on the IP, user agent, language, and any other optionally passed variables. Fraud Scores >= 75 are suspicious, but not necessarily fraudulent. We recommend flagging or blocking traffic with Fraud Scores >= 85, but you may find it beneficial to use a higher or lower threshold. |
+| IPQualityScore.IP.country_code | String | Two character country code of IP address or "N/A" if unknown. |
+| IPQualityScore.IP.region | String | Region \(state\) of IP address if available or "N/A" if unknown. |
+| IPQualityScore.IP.city | String | City of IP address if available or "N/A" if unknown. |
+| IPQualityScore.IP.ISP | String | ISP if one is known. Otherwise "N/A". |
+| IPQualityScore.IP.ASN | Number | Autonomous System Number if one is known. Null if nonexistent. |
+| IPQualityScore.IP.organization | String | Organization if one is known. Can be parent company or sub company of the listed ISP. Otherwise "N/A". |
+| IPQualityScore.IP.latitude | Number | Latitude of IP address if available or "N/A" if unknown. |
+| IPQualityScore.IP.longitude | Number | Longitude of IP address if available or "N/A" if unknown. |
+| IPQualityScore.IP.is_crawler | Boolean | Is this IP associated with being a confirmed crawler from a mainstream search engine such as Googlebot, Bingbot, Yandex, etc. based on hostname or IP address verification. |
+| IPQualityScore.IP.timezone | String | Timezone of IP address if available or "N/A" if unknown. |
+| IPQualityScore.IP.mobile | Boolean | Is this user agent a mobile browser? \(will always be false if the user agent is not passed in the API request\) |
+| IPQualityScore.IP.host | String | Hostname of the IP address if one is available. |
+| IPQualityScore.IP.proxy | Boolean | Is this IP address suspected to be a proxy? \(SOCKS, Elite, Anonymous, VPN, Tor, etc.\) |
+| IPQualityScore.IP.vpn | Boolean | Is this IP suspected of being a VPN connection? This can include data center ranges which can become active VPNs at any time. The "proxy" status will always be true when this value is true. |
+| IPQualityScore.IP.tor | Boolean | Is this IP suspected of being a TOR connection? This can include previously active TOR nodes and exits which can become active TOR exits at any time. The "proxy" status will always be true when this value is true. |
+| IPQualityScore.IP.active_vpn | Boolean | Premium Account Feature - Identifies active VPN connections used by popular VPN services and private VPN servers. |
+| IPQualityScore.IP.active_tor | Boolean | Premium Account Feature - Identifies active TOR exits on the TOR network. |
+| IPQualityScore.IP.recent_abuse | Boolean | This value will indicate if there has been any recently verified abuse across our network for this IP address. Abuse could be a confirmed chargeback, compromised device, fake app install, or similar malicious behavior within the past few days. |
+| IPQualityScore.IP.bot_status | Boolean | Premium Account Feature - Indicates if bots or non-human traffic has recently used this IP address to engage in automated fraudulent behavior. Provides stronger confidence that the IP address is suspicious. |
+| IPQualityScore.IP.connection_type | String | Classification of the IP address connection type as "Residential", "Corporate", "Education", "Mobile", or "Data Center". |
+| IPQualityScore.IP.abuse_velocity | String | Premium Account Feature - How frequently the IP address is engaging in abuse across the IPQS threat network. Values can be "high", "medium", "low", or "none". Can be used in combination with the Fraud Score to identify bad behavior. |
+| IPQualityScore.IP.request_id | String | A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice. |
+| IPQualityScore.IP.address | String | The IP address that was queried. |
+| DBotScore.Indicator | String | The indicator that was tested. |
+| DBotScore.Score | Number | The actual score. |
+| DBotScore.Type | String | The indicator type. |
+| DBotScore.Vendor | String | The vendor used to calculate the score. |
+| IP.Address | string | IP address |
+| IP.ASN | string | The autonomous system name for the IP address, for example: "AS8948". |
+| IP.Hostname | string | The hostname that is mapped to this IP address. |
+| IP.Geo.Country | string | The country in which the IP address is located. |
+| IP.Geo.Description | string | Additional information about the location. |
+| IP.Malicious.Vendor | string | The vendor reporting the IP address as malicious. |
+| IP.Malicious.Description | string | A description explaining why the IP address was reported as malicious. |
+
+
+#### Command Example
+```!ip ip="8.8.8.8"```
+
+#### Context Example
+```json
+{
+ "DBotScore": {
+ "Indicator": "8.8.8.8",
+ "Reliability": "A - Completely reliable",
+ "Score": 3,
+ "Type": "ip",
+ "Vendor": "IPQualityScore"
+ },
+ "IP": {
+ "ASN": 15169,
+ "Address": "8.8.8.8",
+ "Geo": {
+ "Country": "US",
+ "Location": "37.39:-122.07"
+ },
+ "Hostname": "dns.google",
+ "Malicious": {
+ "Description": null,
+ "Vendor": "IPQualityScore"
+ }
+ },
+ "IPQualityScore": {
+ "IP": {
+ "ASN": 15169,
+ "ISP": "Google",
+ "Malicious": {
+ "Vendor": "IPQualityScore"
+ },
+ "abuse_velocity": "high",
+ "active_tor": false,
+ "active_vpn": false,
+ "address": "8.8.8.8",
+ "bot_status": true,
+ "city": "Mountain View",
+ "connection_type": "Data Center",
+ "country_code": "US",
+ "fraud_score": 100,
+ "host": "dns.google",
+ "is_crawler": false,
+ "latitude": 37.39,
+ "longitude": -122.07,
+ "message": "Success",
+ "mobile": false,
+ "organization": "Google",
+ "proxy": true,
+ "recent_abuse": true,
+ "region": "California",
+ "request_id": "4DpK9WpOZGPFSPg",
+ "success": true,
+ "timezone": "America/Los_Angeles",
+ "tor": false,
+ "vpn": true
+ }
+ }
+}
+```
+
+#### Human Readable Output
+
+>### IPQualityScore Results for 8.8.8.8
+>|success|message|fraud_score|country_code|region|city|ISP|ASN|organization|latitude|longitude|is_crawler|timezone|mobile|host|proxy|vpn|tor|active_vpn|active_tor|recent_abuse|bot_status|connection_type|abuse_velocity|request_id|address|
+>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+>| true | Success | 100 | US | California | Mountain View | Google | 15169 | Google | 37.39 | -122.07 | false | America/Los_Angeles | false | dns.google | true | true | false | false | false | true | true | Data Center | high | 4DpK9WpOZGPFSPg | 8.8.8.8 |
+
+
+### email
+***
+Runs reputation on email addresses.
+
+
+#### Base Command
+
+`email`
+#### Input
+
+| **Argument Name** | **Description** | **Required** |
+| --- | --- | --- |
+| email | Email address to check. | Required |
+
+
+#### Context Output
+
+| **Path** | **Type** | **Description** |
+| --- | --- | --- |
+| IPQualityScore.Email.message | String | A generic status message, either success or some form of an error notice. |
+| IPQualityScore.Email.success | Boolean | Was the request successful? |
+| IPQualityScore.Email.valid | Boolean | Does this email address appear valid? |
+| IPQualityScore.Email.disposable | Boolean | Is this email suspected of belonging to a temporary or disposable mail service? Usually associated with fraudsters and scammers. |
+| IPQualityScore.Email.smtp_score | Number | Validity score of email server's SMTP setup. Range: "-1" - "3". Scores above "-1" can be associated with a valid email.
-1 = invalid email address
0 = mail server exists, but is rejecting all mail
1 = mail server exists, but is showing a temporary error
2 = mail server exists, but accepts all email
3 = mail server exists and has verified the email address |
+| IPQualityScore.Email.overall_score | Number | Overall email validity score. Range: "0" - "4". Scores above "1" can be associated with a valid email.
0 = invalid email address
1 = dns valid, unreachable mail server
2 = dns valid, temporary mail rejection error
3 = dns valid, accepts all mail
4 = dns valid, verified email exists |
+| IPQualityScore.Email.first_name | String | Suspected first name based on email. Returns "CORPORATE" if the email is suspected of being a generic company email. Returns "UNKNOWN" if the first name was not determinable. |
+| IPQualityScore.Email.generic | Boolean | Is this email suspected as being a catch all or shared email for a domain? \("admin@", "webmaster@", "newsletter@", "sales@", "contact@", etc.\) |
+| IPQualityScore.Email.common | Boolean | Is this email from a common email provider? \("gmail.com", "yahoo.com", "hotmail.com", etc.\) |
+| IPQualityScore.Email.dns_valid | Boolean | Does the email's hostname have valid DNS entries? Partial indication of a valid email. |
+| IPQualityScore.Email.honeypot | Boolean | Is this email believed to be a "honeypot" or "SPAM trap"? Bulk mail sent to these emails increases your risk of being blacklisted by large ISPs & ending up in the spam folder. |
+| IPQualityScore.Email.deliverability | String | How likely is this email to be delivered to the user and land in their mailbox. Values can be "high", "medium", or "low". |
+| IPQualityScore.Email.frequent_complainer | Boolean | Indicates if this email frequently unsubscribes from marketing lists or reports email as SPAM. |
+| IPQualityScore.Email.spam_trap_score | String | Confidence level of the email address being an active SPAM trap. Values can be "high", "medium", "low", or "none". We recommend scrubbing emails with "high" or "medium" statuses. Avoid "low" emails whenever possible for any promotional mailings. |
+| IPQualityScore.Email.catch_all | Boolean | Is this email likely to be a "catch all" where the mail server verifies all emails tested against it as valid? It is difficult to determine if the address is truly valid in these scenarios, since the email's server will not confirm the account's status. |
+| IPQualityScore.Email.timed_out | Boolean | Did the connection to the mail service provider timeout during the verification? If so, we recommend increasing the "timeout" variable above the default 7 second value. Lookups that timeout with a "valid" result as false are most likely false and should be not be trusted. |
+| IPQualityScore.Email.suspect | Boolean | This value indicates if the mail server is currently replying with a temporary error and unable to verify the email address. This status will also be true for "catch all" email addresses as defined below. If this value is true, then we suspect the "valid" result may be tainted and there is not a guarantee that the email address is truly valid. |
+| IPQualityScore.Email.recent_abuse | Boolean | This value will indicate if there has been any recently verified abuse across our network for this email address. Abuse could be a confirmed chargeback, fake signup, compromised device, fake app install, or similar malicious behavior within the past few days. |
+| IPQualityScore.Email.fraud_score | Number | The overall Fraud Score of the user based on the email's reputation and recent behavior across the IPQS threat network. Fraud Scores >= 75 are suspicious, but not necessarily fraudulent. |
+| IPQualityScore.Email.suggested_domain | String | Default value is "N/A". Indicates if this email's domain should in fact be corrected to a popular mail service. This field is useful for catching user typos. For example, an email address with "gmai.com", would display a suggested domain of "gmail.com". This feature supports all major mail service providers. |
+| IPQualityScore.Email.leaked | Boolean | Was this email address associated with a recent database leak from a third party? Leaked accounts pose a risk as they may have become compromised during a database breach. |
+| IPQualityScore.Email.domain_age.human | Date | A human description of when this domain was registered. \(Ex: 3 months ago\) |
+| IPQualityScore.Email.domain_age.timestamp | Number | The unix time since epoch when this domain was first registered. \(Ex: 1568061634\) |
+| IPQualityScore.Email.domain_age.iso | Date | The time this domain was registered in ISO8601 format \(Ex: 2019-09-09T16:40:34-04:00\) |
+| IPQualityScore.Email.first_seen.human | Date | A human description of the email address age, using an estimation of the email creation date when IPQS first discovered this email address. \(Ex: 3 months ago\) |
+| IPQualityScore.Email.first_seen.timestamp | Number | The unix time since epoch when this email was first analyzed by IPQS. \(Ex: 1568061634\) |
+| IPQualityScore.Email.first_seen.iso | Date | The time this email was first analyzed by IPQS in ISO8601 format \(Ex: 2019-09-09T16:40:34-04:00\) |
+| IPQualityScore.Email.sanitized_email | String | Sanitized email address with all aliases and masking removed, such as multiple periods for Gmail.com. |
+| IPQualityScore.Email.request_id | String | A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice. |
+| IPQualityScore.Email.address | String | The email address that was queried |
+| DBotScore.Indicator | String | The indicator that was tested. |
+| DBotScore.Score | Number | The actual score. |
+| DBotScore.Type | String | The indicator type. |
+| DBotScore.Vendor | String | The vendor used to calculate the score. |
+
+
+#### Command Example
+```!email email="noreply@ipqualityscore.com"```
+
+#### Context Example
+```json
+{
+ "DBotScore": {
+ "Indicator": "noreply@ipqualityscore.com",
+ "Reliability": "A - Completely reliable",
+ "Score": 3,
+ "Type": "email",
+ "Vendor": "IPQualityScore"
+ },
+ "EMAIL": {
+ "Address": "noreply@ipqualityscore.com",
+ "Domain": "ipqualityscore.com"
+ },
+ "IPQualityScore": {
+ "Email": {
+ "Malicious": {
+ "Vendor": "IPQualityScore"
+ },
+ "address": "noreply@ipqualityscore.com",
+ "catch_all": true,
+ "common": false,
+ "deliverability": "low",
+ "disposable": false,
+ "dns_valid": true,
+ "domain_age": {
+ "human": "10 years ago",
+ "iso": "2011-04-14T23:26:37-04:00",
+ "timestamp": 1302837997
+ },
+ "first_name": "Corporate",
+ "first_seen": {
+ "human": "2 years ago",
+ "iso": "2019-05-06T02:09:06-04:00",
+ "timestamp": 1557122946
+ },
+ "fraud_score": 95,
+ "frequent_complainer": false,
+ "generic": true,
+ "honeypot": true,
+ "leaked": false,
+ "message": "Success.",
+ "overall_score": 3,
+ "recent_abuse": true,
+ "request_id": "4DpK9WpOZGQDnr7",
+ "sanitized_email": "noreply@ipqualityscore.com",
+ "smtp_score": 2,
+ "spam_trap_score": "medium",
+ "success": true,
+ "suggested_domain": "N/A",
+ "suspect": true,
+ "timed_out": false,
+ "valid": true
+ }
+ }
+}
+```
+
+#### Human Readable Output
+
+>### IPQualityScore Results for noreply@ipqualityscore.com
+>|message|success|valid|disposable|smtp_score|overall_score|first_name|generic|common|dns_valid|honeypot|deliverability|frequent_complainer|spam_trap_score|catch_all|timed_out|suspect|recent_abuse|fraud_score|suggested_domain|leaked|domain_age|first_seen|sanitized_email|request_id|address|
+>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+>| Success. | true | true | false | 2 | 3 | Corporate | true | false | true | true | low | false | medium | true | false | true | true | 95 | N/A | false | human: 10 years ago
timestamp: 1302837997
iso: 2011-04-14T23:26:37-04:00 | human: 2 years ago
timestamp: 1557122946
iso: 2019-05-06T02:09:06-04:00 | noreply@ipqualityscore.com | 4DpK9WpOZGQDnr7 | noreply@ipqualityscore.com |
+
+
+### url
+***
+Runs reputation on URLs.
+
+
+#### Base Command
+
+`url`
+#### Input
+
+| **Argument Name** | **Description** | **Required** |
+| --- | --- | --- |
+| url | Url address to check. | Required |
+
+
+#### Context Output
+
+| **Path** | **Type** | **Description** |
+| --- | --- | --- |
+| IPQualityScore.Url.message | String | A generic status message, either success or some form of an error notice. |
+| IPQualityScore.Url.success | Boolean | Was the request successful? |
+| IPQualityScore.Url.unsafe | Boolean | Is this domain suspected of being unsafe due to phishing, malware, spamming, or abusive behavior? View the confidence level by analyzing the "risk_score". |
+| IPQualityScore.Url.domain | String | Domain name of the final destination URL of the scanned link, after following all redirects. |
+| IPQualityScore.Url.ip_address | String | The IP address corresponding to the server of the domain name. |
+| IPQualityScore.Url.server | String | The server banner of the domain's IP address. For example: "nginx/1.16.0". Value will be "N/A" if unavailable. |
+| IPQualityScore.Url.content_type | String | MIME type of URL's content. For example "text/html; charset=UTF-8". Value will be "N/A" if unavailable. |
+| IPQualityScore.Url.status_code | Number | HTTP Status Code of the URL's response. This value should be "200" for a valid website. Value is "0" if URL is unreachable. |
+| IPQualityScore.Url.page_size | Number | Total number of bytes to download the URL's content. Value is "0" if URL is unreachable. |
+| IPQualityScore.Url.domain_rank | Number | Estimated popularity rank of website globally. Value is "0" if the domain is unranked or has low traffic. |
+| IPQualityScore.Url.dns_valid | Boolean | The domain of the URL has valid DNS records. |
+| IPQualityScore.Url.parking | Boolean | Is the domain of this URL currently parked with a for sale notice? |
+| IPQualityScore.Url.spamming | Boolean | Is the domain of this URL associated with email SPAM or abusive email addresses? |
+| IPQualityScore.Url.malware | Boolean | Is this URL associated with malware or viruses? |
+| IPQualityScore.Url.phishing | Boolean | Is this URL associated with malicious phishing behavior? |
+| IPQualityScore.Url.suspicious | Boolean | Is this URL suspected of being malicious or used for phishing or abuse? Use in conjunction with the "risk_score" as a confidence level. |
+| IPQualityScore.Url.risk_score | Number | The IPQS risk score which estimates the confidence level for malicious URL detection. Risk Scores 85\+ are high risk, while Risk Scores = 100 are confirmed as accurate. |
+| IPQualityScore.Url.request_id | String | A unique identifier for this request that can be used to lookup the request details or send a postback conversion notice. |
+| IPQualityScore.Url.url | String | The URL being queried. |
+| IPQualityScore.Url.adult | Boolean | Is this URL or domain hosting dating or adult content? |
+| IPQualityScore.Url.domain_age.human | Date | A human description of when this domain was registered. \(Ex: 3 months ago\) |
+| IPQualityScore.Url.domain_age.timestamp | Number | The unix time since epoch when this domain was first registered. \(Ex: 1568061634\) |
+| IPQualityScore.Url.domain_age.iso | Date | The time this domain was registered in ISO8601 format \(Ex: 2019-09-09T16:40:34-04:00\) |
+| DBotScore.Indicator | String | The indicator that was tested. |
+| DBotScore.Score | Number | The actual score. |
+| DBotScore.Type | String | The indicator type. |
+| DBotScore.Vendor | String | The vendor used to calculate the score. |
+| URL.Data | String | The URL |
+| URL.Malicious.Vendor | String | The vendor reporting the URL as malicious. |
+
+
+#### Command Example
+```!url url="https://google.com"```
+
+#### Context Example
+```json
+{
+ "DBotScore": {
+ "Indicator": "https://google.com",
+ "Reliability": "A - Completely reliable",
+ "Score": 0,
+ "Type": "url",
+ "Vendor": "IPQualityScore"
+ },
+ "IPQualityScore": {
+ "Url": {
+ "adult": false,
+ "content_type": "text/html; charset=UTF-8",
+ "dns_valid": true,
+ "domain": "google.com",
+ "domain_age": {
+ "human": "24 years ago",
+ "iso": "1997-09-15T00:00:00-04:00",
+ "timestamp": 874296000
+ },
+ "domain_rank": 1,
+ "ip_address": "172.217.11.142",
+ "malware": false,
+ "message": "Success.",
+ "page_size": 39242,
+ "parking": false,
+ "phishing": false,
+ "request_id": "4DpK9WpOZGQFSPi",
+ "risk_score": 0,
+ "server": " gws\r\n",
+ "spamming": false,
+ "status_code": 200,
+ "success": true,
+ "suspicious": false,
+ "unsafe": false,
+ "url": "https://google.com"
+ }
+ },
+ "URL": {
+ "Data": "https://google.com"
+ }
+}
+```
+
+#### Human Readable Output
+
+>### IPQualityScore Results for https://google.com
+>|message|success|unsafe|domain|ip_address|server|content_type|status_code|page_size|domain_rank|dns_valid|parking|spamming|malware|phishing|suspicious|adult|risk_score|domain_age|request_id|url|
+>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+>| Success. | true | false | google.com | 172.217.11.142 | gws
| text/html; charset=UTF-8 | 200 | 39242 | 1 | true | false | false | false | false | false | false | 0 | human: 24 years ago
timestamp: 874296000
iso: 1997-09-15T00:00:00-04:00 | 4DpK9WpOZGQFSPi | https://google.com |
+
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/command_examples.txt b/Packs/IPQualityScore/Integrations/IPQualityScore/command_examples.txt
new file mode 100644
index 000000000000..df37ecb584a5
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/command_examples.txt
@@ -0,0 +1,3 @@
+!ip ip="8.8.8.8"
+!email email="noreply@ipqualityscore.com"
+!url url="https://google.com"
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/email_response.json b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/email_response.json
new file mode 100644
index 000000000000..1bc18323d5ce
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/email_response.json
@@ -0,0 +1 @@
+{"message":"Success.","success":true,"valid":false,"disposable":false,"smtp_score":1,"overall_score":1,"first_name":"Corporate","generic":true,"common":true,"dns_valid":true,"honeypot":true,"deliverability":"low","frequent_complainer":true,"spam_trap_score":"high","catch_all":false,"timed_out":false,"suspect":false,"recent_abuse":false,"fraud_score":70,"suggested_domain":"N\/A","leaked":true,"domain_age":{"human":"26 years ago","timestamp":808286400,"iso":"1995-08-13T00:00:00-04:00"},"first_seen":{"human":"4 years ago","timestamp":1483250461,"iso":"2017-01-01T01:01:01-05:00"},"sanitized_email":"someone@gmail.com","request_id":"4uYZ4DYC5pg3bs"}
\ No newline at end of file
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/ip_response.json b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/ip_response.json
new file mode 100644
index 000000000000..157b4552ad85
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/ip_response.json
@@ -0,0 +1 @@
+{"success":true,"message":"Success","fraud_score":75,"country_code":"US","region":"California","city":"Palo Alto","ISP":"Hewlett-Packard Company","ASN":0,"organization":"Hewlett-Packard Company","latitude":37.41,"longitude":-122.13,"is_crawler":false,"timezone":"America\/Los_Angeles","mobile":false,"host":"15.99.160.255","proxy":true,"vpn":true,"tor":false,"active_vpn":false,"active_tor":false,"recent_abuse":false,"bot_status":false,"connection_type":"Corporate","abuse_velocity":"low","request_id":"4uYZ48zT4JW3k0"}
\ No newline at end of file
diff --git a/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/url_response.json b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/url_response.json
new file mode 100644
index 000000000000..e2d6ac71df4e
--- /dev/null
+++ b/Packs/IPQualityScore/Integrations/IPQualityScore/test_data/url_response.json
@@ -0,0 +1 @@
+{"message":"Success.","success":true,"unsafe":false,"domain":"google.com","ip_address":"172.217.19.110","server":" gws\r\n","content_type":"text\/html; charset=UTF-8","status_code":200,"page_size":38017,"domain_rank":1,"dns_valid":true,"parking":false,"spamming":false,"malware":false,"phishing":false,"suspicious":false,"risk_score":0,"request_id":"4uYZ4DbcNec3o8"}
\ No newline at end of file
diff --git a/Packs/IPQualityScore/README.md b/Packs/IPQualityScore/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/Packs/IPQualityScore/TestPlayBooks/TestIPQualityScorePlaybook.yml b/Packs/IPQualityScore/TestPlayBooks/TestIPQualityScorePlaybook.yml
new file mode 100644
index 000000000000..531fe11af035
--- /dev/null
+++ b/Packs/IPQualityScore/TestPlayBooks/TestIPQualityScorePlaybook.yml
@@ -0,0 +1,325 @@
+description: This playbook tests the functionality of the IPQualityScore Integration
+id: TestIPQualityScorePlaybook
+inputs: []
+name: TestIPQualityScorePlaybook
+outputs: []
+starttaskid: "0"
+tasks:
+ "0":
+ id: "0"
+ ignoreworker: false
+ nexttasks:
+ '#none#':
+ - "1"
+ note: false
+ quietmode: 0
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ id: 759f7594-db5d-441e-8be4-7edd45aa7dfa
+ iscommand: false
+ name: ""
+ version: -1
+ description: ''
+ taskid: 759f7594-db5d-441e-8be4-7edd45aa7dfa
+ timertriggers: []
+ type: start
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 50
+ }
+ }
+ "1":
+ id: "1"
+ ignoreworker: false
+ nexttasks:
+ '#none#':
+ - "2"
+ note: false
+ quietmode: 0
+ scriptarguments:
+ all:
+ simple: "yes"
+ index: {}
+ key: {}
+ keysToKeep: {}
+ subplaybook: {}
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ description: Delete field from context
+ id: d40f7ac7-897d-4014-8a86-19e197c8b59c
+ iscommand: false
+ name: DeleteContext
+ script: DeleteContext
+ type: regular
+ version: -1
+ taskid: d40f7ac7-897d-4014-8a86-19e197c8b59c
+ timertriggers: []
+ type: regular
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 195
+ }
+ }
+ "2":
+ id: "2"
+ ignoreworker: false
+ nexttasks:
+ '#none#':
+ - "3"
+ note: false
+ quietmode: 0
+ scriptarguments:
+ fullResponse: {}
+ ip:
+ simple: 8.8.8.8
+ long: {}
+ retries: {}
+ sampleSize: {}
+ threshold: {}
+ wait: {}
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: IPQualityScore
+ description: Runs reputation on IPs.
+ id: 1a5ba2cc-ad3a-4a85-8ee6-8bf333bbff66
+ iscommand: true
+ name: ip
+ script: IPQualityScore|||ip
+ type: regular
+ version: -1
+ taskid: 1a5ba2cc-ad3a-4a85-8ee6-8bf333bbff66
+ timertriggers: []
+ type: regular
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 370
+ }
+ }
+ "3":
+ conditions:
+ - condition:
+ - - left:
+ iscontext: true
+ value:
+ simple: IP.Address
+ operator: isNotEmpty
+ label: "yes"
+ id: "3"
+ ignoreworker: false
+ nexttasks:
+ "yes":
+ - "5"
+ note: false
+ quietmode: 0
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ description: Verify context data set by the previous command.
+ id: 63d74d6c-0f73-4a9b-84ed-fb3cc8504606
+ iscommand: false
+ name: Verify Output
+ type: condition
+ version: -1
+ taskid: 63d74d6c-0f73-4a9b-84ed-fb3cc8504606
+ timertriggers: []
+ type: condition
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 545
+ }
+ }
+ "4":
+ id: "4"
+ ignoreworker: false
+ note: false
+ quietmode: 0
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ id: fe103ba3-e605-43c8-80a8-7f71ed5552d1
+ iscommand: false
+ name: End
+ type: title
+ version: -1
+ description: ''
+ taskid: fe103ba3-e605-43c8-80a8-7f71ed5552d1
+ timertriggers: []
+ type: title
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 1420
+ }
+ }
+ "5":
+ id: "5"
+ ignoreworker: false
+ nexttasks:
+ '#none#':
+ - "6"
+ note: false
+ quietmode: 0
+ scriptarguments:
+ email:
+ simple: test@example.com
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: IPQualityScore
+ description: Runs reputation on email addresses.
+ id: d7ba5023-8945-4527-8ce9-4e6644936c6d
+ iscommand: true
+ name: email
+ script: IPQualityScore|||email
+ type: regular
+ version: -1
+ taskid: d7ba5023-8945-4527-8ce9-4e6644936c6d
+ timertriggers: []
+ type: regular
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 720
+ }
+ }
+ "6":
+ conditions:
+ - condition:
+ - - left:
+ iscontext: true
+ value:
+ simple: IPQualityScore.Email.address
+ operator: isNotEmpty
+ label: "yes"
+ id: "6"
+ ignoreworker: false
+ nexttasks:
+ "yes":
+ - "7"
+ note: false
+ quietmode: 0
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ description: Verify context data set by the previous command.
+ id: 05b7442d-81ed-4a0f-8b33-58ea41a76f3f
+ iscommand: false
+ name: Verify Output
+ type: condition
+ version: -1
+ taskid: 05b7442d-81ed-4a0f-8b33-58ea41a76f3f
+ timertriggers: []
+ type: condition
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 895
+ }
+ }
+ "7":
+ id: "7"
+ ignoreworker: false
+ nexttasks:
+ '#none#':
+ - "8"
+ note: false
+ quietmode: 0
+ scriptarguments:
+ long: {}
+ retries: {}
+ sampleSize: {}
+ submitWait: {}
+ threshold: {}
+ url:
+ simple: https://google.com
+ wait: {}
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: IPQualityScore
+ description: Runs reputation on URLs.
+ id: a56e4bf0-4158-4815-8c49-e575270b6c1a
+ iscommand: true
+ name: url
+ script: IPQualityScore|||url
+ type: regular
+ version: -1
+ taskid: a56e4bf0-4158-4815-8c49-e575270b6c1a
+ timertriggers: []
+ type: regular
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 1070
+ }
+ }
+ "8":
+ conditions:
+ - condition:
+ - - left:
+ iscontext: true
+ value:
+ simple: IPQualityScore.Email.address
+ operator: isNotEmpty
+ label: "yes"
+ id: "8"
+ ignoreworker: false
+ nexttasks:
+ "yes":
+ - "4"
+ note: false
+ quietmode: 0
+ separatecontext: false
+ skipunavailable: false
+ task:
+ brand: ""
+ description: Verify context data set by the previous command.
+ id: 452b4134-5486-4fbc-86a6-8f4dfae4da9d
+ iscommand: false
+ name: Verify Output
+ type: condition
+ version: -1
+ taskid: 452b4134-5486-4fbc-86a6-8f4dfae4da9d
+ timertriggers: []
+ type: condition
+ view: |-
+ {
+ "position": {
+ "x": 50,
+ "y": 1245
+ }
+ }
+version: -1
+view: |-
+ {
+ "linkLabelsPosition": {},
+ "paper": {
+ "dimensions": {
+ "height": 1435,
+ "width": 380,
+ "x": 50,
+ "y": 50
+ }
+ }
+ }
+fromversion: 5.0.0
diff --git a/Packs/IPQualityScore/pack_metadata.json b/Packs/IPQualityScore/pack_metadata.json
new file mode 100644
index 000000000000..a9659d404b59
--- /dev/null
+++ b/Packs/IPQualityScore/pack_metadata.json
@@ -0,0 +1,18 @@
+{
+ "name": "IPQualityScore (IPQS) Threat Risk Scoring",
+ "description": "Detect threats with real-time risk scoring by IPQS. Playbook analyzes IP addresses, email addresses, and domains or URLs for high risk behavior.",
+ "support": "partner",
+ "currentVersion": "1.0.0",
+ "author": "IPQualityScore",
+ "url": "https://www.ipqualityscore.com",
+ "email": "support@ipqualityscore.com",
+ "created": "2021-03-31T00:00:00Z",
+ "categories": [
+ "Data Enrichment & Threat Intelligence",
+ "Network Security"
+ ],
+ "tags": ["Attack", "Dark Web", "Email", "Malware", "Network", "Scam", "Security", "Security Analytics", "Spam", "VPN", "Threat Intelligence"],
+ "useCases": ["Brute Force", "Hunting", "Malware", "Phishing", "SANS", "Threat Intelligence Management", "Network Security", "Compliance"],
+ "keywords": ["risk score", "threat score", "botnet", "bad actor", "ATO", "takeover", "account", "cyber", "proxy", "vpn", "tor", "ip intelligence", "ip address", "ip", "domain scoring", "parked", "parking", "domain age", "abuse", "threat", "risk", "fraud", "email validation", "url scanner", "malicious url", "malicious domain", "phishing", "malware", "ip reputation", "email reputation", "domain reputation", "url reputation", "detect", "prevent", "domain", "url"],
+ "certification": "certified"
+}
\ No newline at end of file