Skip to content

Commit

Permalink
Removed reference to non-existant field in VulnArticle. Handle vuln a…
Browse files Browse the repository at this point in the history
…rticles with no impacted assets. Add new impacted_attack_surfaces property to vuln articles and update dataframe impacts column to count only those attack surfaces.
  • Loading branch information
aeetos committed Mar 11, 2022
1 parent cc3f889 commit 0dc72e4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 11 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ when methods returned RecordList-type objects.
to historical Whois (ownership) records. Includes more consistent implementation of
RecordList functionality and better pandas dataframe support for both historical Whois and
field-level Whois searches.
- New `impacted_attack_surfaces` property of vulnerability articles (`VulnArticle`) filters
the list of third-party vendors to only those with at least one observation. The Illuminate
API returns all attack surfaces associated with an API key regardless of whether they are
impacted; the complete list is still available in the `attack_surfaces` property. Also updated
the `info` view of the Pandas dataframe on a vulnerability article so the `impacts` column
shows the count of impacted attack surfaces.


#### Bug Fixes
Expand All @@ -24,6 +30,9 @@ field-level Whois searches.
record list were only counting high-priority insights.
- Fixed issue that caused an exception when trying to generate a dictionary view of an
AttackSurfaceComponent (detection).
- Removed reference to non-existant field in `VulnArticle` that was causing an exception when
rendering a vulnerability article as a dictionary with the `as_dict` property.
- Handle vuln articles with no impacted assets without raising an exception.



Expand Down
53 changes: 42 additions & 11 deletions passivetotal/analyzer/illuminate/vuln.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,11 @@ def _pagination_parse_page(self, api_response):
self._totalrecords = api_response.get('totalCount')
if self._pagination_current_page == 0:
self._records = []
for result in api_response.get('assets',[]):
self._records.append(AttackSurfaceCVEObservation(self._cve, result))
try:
for result in api_response.get('assets',[]):
self._records.append(AttackSurfaceCVEObservation(self._cve, result))
except TypeError:
pass # assets may be blank instead of an empty list

@property
def cve(self):
Expand Down Expand Up @@ -481,7 +484,7 @@ def _api_get_article(self, id):

def _get_dict_fields(self):
return ['id','description','cwes','score','cvss2score','cvss3score','str:date_published',
'str:date_updated','str:date_publisher_updated','references','components',
'str:date_publisher_updated','references','components',
'observation_count']

def to_dataframe(self, view='info'):
Expand Down Expand Up @@ -515,7 +518,7 @@ def to_dataframe(self, view='info'):
'observations': self.observation_count,
'references': len(self.references),
'components': len(self.components),
'impacts': len(self._impacted3p)
'impacts': len(self.impacted_attack_surfaces)
}],
'references': [{
'cve_id': self.id,
Expand Down Expand Up @@ -639,6 +642,16 @@ def attack_surfaces(self):
"""
return VulnArticleImpacts(self, self._impacted3p)

@property
@lru_cache(maxsize=None)
def impacted_attack_surfaces(self):
"""List of all attack surfaces associated with your API account that are impacted
by this vulnerability (they have at least one observation of an impacted asset).
:rtype: :class:`passivetotal.analyzer.illuminate.vuln.VulnArticleImpacts`
"""
return self.attack_surfaces.only_impacted

@property
def observation_count(self):
"""Number of observations (assets) within the primary attack surface that are impacted by this vulnerability."""
Expand Down Expand Up @@ -666,8 +679,8 @@ def observations(self):

class VulnArticleImpacts(RecordList, ForPandas):

"""Collection of Illuminate Attack Surfaces impacted by a vulnerability as a list-like
object containing :class:`VulnArticleImpact` objects."""
"""Collection of Illuminate Attack Surfaces potentially impacted by a vulnerability
as a list-like object containing :class:`VulnArticleImpact` objects."""

def __init__(self, article=None, impacts=[]):
self._records = []
Expand All @@ -680,7 +693,7 @@ def __repr__(self):
return '<VulnArticleImpacts {0.article.id}>'.format(self)

def __str__(self):
return '{0.article.id} impacts {0.impact_count:,} attack surfaces(s)'.format(self)
return '{0.article.id} impacts {0.impact_count:,} of {0.length:,} attack surfaces(s)'.format(self)

def _get_dict_fields(self):
return ['cve_id', 'impact_count']
Expand All @@ -701,9 +714,16 @@ def article(self):

@property
def attack_surfaces(self):
"""List of impacted attack surfaces.
"""Unfiltered list of all attack surfaces associated with your API account.
This is the same list you would get if you iterated through an instance of this
object. Each record will include a count of assets impacted by a vulnerability, in the
"observation_count" property. The count may be zero.
If you need a list of only impacted attack surfaces, use the `only_impacted`
property instead.
:rtypte: :class:`passivetotal.analyzer.illuminate.vuln.VulnArticleImpact`
:rtype: :class:`passivetotal.analyzer.illuminate.vuln.VulnArticleImpacts`
"""
return self._records

Expand All @@ -712,10 +732,21 @@ def cve_id(self):
"""CVE identifier for the vulnerability this article applies to."""
return self.article.id

@property
def only_impacted(self):
"""Filter the list to include only articles with at least one observation (asset).
:rtype: :class:`VulnArticleImpacts`
"""
return self.filter_fn(lambda asi: asi.observation_count > 0)

@property
def impact_count(self):
"""Number of attack surfaces impacted by this vulnerability."""
return len(self._records)
"""Number of attack surfaces with assets impacted by this vulnerability.
Counts the number of records that have more than zero observations.
"""
return len(self.only_impacted)



Expand Down

0 comments on commit 0dc72e4

Please sign in to comment.