Skip to content

Commit

Permalink
Company name and cert event fixes
Browse files Browse the repository at this point in the history
1. Moved common SSL event functions to common_ssl_cert.py
2. Change sfp_crt and sfp_sslcert accordingly.
3. Allowed sfp_company to grab the O= portion of cert subject as full name (not limited to 3 words)

fixes smicallef#1749
  • Loading branch information
secretrobotron authored and niavasha committed Oct 28, 2024
1 parent f4494a8 commit 4373057
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 94 deletions.
47 changes: 47 additions & 0 deletions modules/common_ssl_cert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from spiderfoot import SpiderFootEvent

def process_ssl_cert_events(spiderfoot_plugin, cert, root_event):
eventName = root_event.eventType

if cert.get('issued'):
new_event = SpiderFootEvent('SSL_CERTIFICATE_ISSUED', cert['issued'], spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)

if cert.get('issuer'):
new_event = SpiderFootEvent('SSL_CERTIFICATE_ISSUER', cert['issuer'], spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)

if eventName != "IP_ADDRESS" and cert.get('mismatch'):
new_event = SpiderFootEvent('SSL_CERTIFICATE_MISMATCH', ', '.join(cert.get('hosts')), spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)

for san in set(cert.get('altnames', list())):
domain = san.replace("*.", "")

if spiderfoot_plugin.getTarget().matches(domain, includeChildren=True):
new_event_type = 'INTERNET_NAME'
if spiderfoot_plugin.opts['verify'] and not spiderfoot_plugin.sf.resolveHost(domain) and not spiderfoot_plugin.sf.resolveHost6(domain):
spiderfoot_plugin.debug(f"Host {domain} could not be resolved")
new_event_type += '_UNRESOLVED'
else:
new_event_type = 'CO_HOSTED_SITE'

new_event = SpiderFootEvent(new_event_type, domain, spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)

if spiderfoot_plugin.sf.isDomain(domain, spiderfoot_plugin.opts['_internettlds']):
if new_event_type == 'CO_HOSTED_SITE':
new_event = SpiderFootEvent('CO_HOSTED_SITE_DOMAIN', domain, spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)
else:
new_event = SpiderFootEvent('DOMAIN_NAME', domain, spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)

if cert.get('expired'):
new_event = SpiderFootEvent("SSL_CERTIFICATE_EXPIRED", cert.get('expirystr', 'Unknown'), spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)
return

if cert.get('expiring'):
new_event = SpiderFootEvent("SSL_CERTIFICATE_EXPIRING", cert.get('expirystr', 'Unknown'), spiderfoot_plugin.__name__, root_event)
spiderfoot_plugin.notifyListeners(new_event)
40 changes: 25 additions & 15 deletions modules/sfp_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

from spiderfoot import SpiderFootEvent, SpiderFootPlugin


class sfp_company(SpiderFootPlugin):

meta = {
Expand Down Expand Up @@ -56,6 +55,8 @@ def handleEvent(self, event):
srcModuleName = event.module
eventData = event.data

found_company_names = list()

# Various ways to identify companies in text
# Support up to three word company names with each starting with
# a capital letter, allowing for hyphens brackets and numbers within.
Expand Down Expand Up @@ -95,8 +96,17 @@ def handleEvent(self, event):
try:
if eventName == "SSL_CERTIFICATE_ISSUED":
eventData = eventData.split("O=")[1]
except Exception:

# Try to get O= as easy company name
o_match = re.search(r"(.+)[,]", eventData)

if o_match:
company_name = o_match.groups()[0]
found_company_names.append(company_name)
eventData = eventData[len(company_name):]
except Exception as e:
self.debug("Couldn't strip out 'O=' from certificate issuer, proceeding anyway...")
self.debug(e)

# Find chunks of text containing what might be a company name first.
# This is to avoid running very expensive regexps on large chunks of
Expand All @@ -116,7 +126,6 @@ def handleEvent(self, event):
offset = m + len(pat)
m = eventData.find(pat, offset)

myres = list()
for chunk in chunks:
for pat in pattern_match_re:
matches = re.findall(pattern_prefix + "(" + pat + ")" + pattern_suffix, chunk, re.MULTILINE | re.DOTALL)
Expand All @@ -141,22 +150,23 @@ def handleEvent(self, event):

self.info("Found company name: " + fullcompany)

if fullcompany in myres:
if fullcompany in found_company_names:
self.debug("Already found from this source.")
continue

myres.append(fullcompany)
found_company_names.append(fullcompany)

if "AFFILIATE_" in eventName:
etype = "AFFILIATE_COMPANY_NAME"
else:
etype = "COMPANY_NAME"
if "AFFILIATE_" in eventName:
etype = "AFFILIATE_COMPANY_NAME"
else:
etype = "COMPANY_NAME"

evt = SpiderFootEvent(etype, fullcompany, self.__name__, event)
if event.moduleDataSource:
evt.moduleDataSource = event.moduleDataSource
else:
evt.moduleDataSource = "Unknown"
self.notifyListeners(evt)
for company_name in found_company_names:
evt = SpiderFootEvent(etype, company_name, self.__name__, event)
if event.moduleDataSource:
evt.moduleDataSource = event.moduleDataSource
else:
evt.moduleDataSource = "Unknown"
self.notifyListeners(evt)

# End of sfp_company class
40 changes: 2 additions & 38 deletions modules/sfp_crt.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from spiderfoot import SpiderFootEvent, SpiderFootPlugin

from modules.common_ssl_cert import process_ssl_cert_events

class sfp_crt(SpiderFootPlugin):

Expand Down Expand Up @@ -216,43 +217,6 @@ def handleEvent(self, event):
evt = SpiderFootEvent("SSL_CERTIFICATE_RAW", str(cert_text), self.__name__, event)
self.notifyListeners(evt)

sans = cert.get('altnames', list())

if not sans:
continue

for san in sans:
if san.lower() == event.data.lower():
continue
domains.append(san.lower().replace("*.", ""))

if self.opts['verify'] and len(domains) > 0:
self.info(f"Resolving {len(set(domains))} domains ...")

for domain in set(domains):
if domain in self.results:
continue

if not self.sf.validHost(domain, self.opts['_internettlds']):
continue

if self.getTarget().matches(domain, includeChildren=True, includeParents=True):
evt_type = 'INTERNET_NAME'
if self.opts['verify'] and not self.sf.resolveHost(domain) and not self.sf.resolveHost6(domain):
self.debug(f"Host {domain} could not be resolved")
evt_type += '_UNRESOLVED'
else:
evt_type = 'CO_HOSTED_SITE'

evt = SpiderFootEvent(evt_type, domain, self.__name__, event)
self.notifyListeners(evt)

if self.sf.isDomain(domain, self.opts['_internettlds']):
if evt_type == 'CO_HOSTED_SITE':
evt = SpiderFootEvent('CO_HOSTED_SITE_DOMAIN', domain, self.__name__, event)
self.notifyListeners(evt)
else:
evt = SpiderFootEvent('DOMAIN_NAME', domain, self.__name__, event)
self.notifyListeners(evt)
process_ssl_cert_events(self, cert, event)

# End of sfp_crt class
44 changes: 3 additions & 41 deletions modules/sfp_sslcert.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from spiderfoot import SpiderFootEvent, SpiderFootPlugin, SpiderFootHelpers

from modules.common_ssl_cert import process_ssl_cert_events

class sfp_sslcert(SpiderFootPlugin):

Expand Down Expand Up @@ -128,47 +129,8 @@ def handleEvent(self, event):
rawevt = SpiderFootEvent("SSL_CERTIFICATE_RAW", cert['text'], self.__name__, event)
self.notifyListeners(rawevt)

if cert.get('issued'):
evt = SpiderFootEvent('SSL_CERTIFICATE_ISSUED', cert['issued'], self.__name__, event)
self.notifyListeners(evt)

if cert.get('issuer'):
evt = SpiderFootEvent('SSL_CERTIFICATE_ISSUER', cert['issuer'], self.__name__, event)
self.notifyListeners(evt)

if eventName != "IP_ADDRESS" and cert.get('mismatch'):
evt = SpiderFootEvent('SSL_CERTIFICATE_MISMATCH', ', '.join(cert.get('hosts')), self.__name__, event)
self.notifyListeners(evt)

for san in set(cert.get('altnames', list())):
domain = san.replace("*.", "")

if self.getTarget().matches(domain, includeChildren=True):
evt_type = 'INTERNET_NAME'
if self.opts['verify'] and not self.sf.resolveHost(domain) and not self.sf.resolveHost6(domain):
self.debug(f"Host {domain} could not be resolved")
evt_type += '_UNRESOLVED'
else:
evt_type = 'CO_HOSTED_SITE'
process_ssl_cert_events(self, cert, event)

evt = SpiderFootEvent(evt_type, domain, self.__name__, event)
self.notifyListeners(evt)

if self.sf.isDomain(domain, self.opts['_internettlds']):
if evt_type == 'CO_HOSTED_SITE':
evt = SpiderFootEvent('CO_HOSTED_SITE_DOMAIN', domain, self.__name__, event)
self.notifyListeners(evt)
else:
evt = SpiderFootEvent('DOMAIN_NAME', domain, self.__name__, event)
self.notifyListeners(evt)

if cert.get('expired'):
evt = SpiderFootEvent("SSL_CERTIFICATE_EXPIRED", cert.get('expirystr', 'Unknown'), self.__name__, event)
self.notifyListeners(evt)
return

if cert.get('expiring'):
evt = SpiderFootEvent("SSL_CERTIFICATE_EXPIRING", cert.get('expirystr', 'Unknown'), self.__name__, event)
self.notifyListeners(evt)


# End of sfp_sslcert class

0 comments on commit 4373057

Please sign in to comment.