Commit ee14bf1952e9221a0d0375bea74cef7354cf6012

Authored by decalage2
1 parent fa476b8f

oleid: added check for external relationships

Showing 1 changed file with 39 additions and 12 deletions
oletools/oleid.py
... ... @@ -98,7 +98,7 @@ if _parent_dir not in sys.path:
98 98 sys.path.insert(0, _parent_dir)
99 99  
100 100 from oletools.thirdparty.tablestream import tablestream
101   -from oletools import crypto, ftguess, olevba, mraptor
  101 +from oletools import crypto, ftguess, olevba, mraptor, oleobj, ooxml
102 102 from oletools.common.log_helper import log_helper
103 103 from oletools.common.codepages import get_codepage_name
104 104  
... ... @@ -243,6 +243,15 @@ class OleID(object):
243 243 self.indicators = []
244 244 self.suminfo_data = None
245 245  
  246 + def get_indicator(self, indicator_id):
  247 + """Helper function: returns an indicator if present (or None)"""
  248 + result = [indicator for indicator in self.indicators
  249 + if indicator.id == indicator_id]
  250 + if result:
  251 + return result[0]
  252 + else:
  253 + return None
  254 +
246 255 def check(self):
247 256 """
248 257 Open file and run all checks on it.
... ... @@ -288,6 +297,7 @@ class OleID(object):
288 297 # self.check_powerpoint()
289 298 # self.check_visio()
290 299 self.check_macros()
  300 + self.check_external_relationships()
291 301 self.check_object_pool()
292 302 self.check_flash()
293 303 if self.ole is not None:
... ... @@ -321,21 +331,10 @@ class OleID(object):
321 331 self.indicators.append(author)
322 332 return appname, codepage, author
323 333  
324   - def get_indicator(self, indicator_id):
325   - """Helper function: returns an indicator if present (or None)"""
326   - result = [indicator for indicator in self.indicators
327   - if indicator.id == indicator_id]
328   - if result:
329   - return result[0]
330   - else:
331   - return None
332   -
333 334 def check_encrypted(self):
334 335 """
335 336 Check whether this file is encrypted.
336 337  
337   - Might call check_properties.
338   -
339 338 :returns: :py:class:`Indicator` for encryption or None if file was not
340 339 opened
341 340 """
... ... @@ -353,6 +352,34 @@ class OleID(object):
353 352 encrypted.description = 'The file is encrypted. It may be decrypted with msoffcrypto-tool'
354 353 return encrypted
355 354  
  355 + def check_external_relationships(self):
  356 + """
  357 + Check whether this file has external relationships (remote template, OLE object, etc).
  358 +
  359 + :returns: :py:class:`Indicator`
  360 + """
  361 + ext_rels = Indicator('ext_rels', 0, name='External Relationships', _type=int,
  362 + risk=RISK.NONE,
  363 + description='External relationships such as remote templates, remote OLE objects, etc',
  364 + hide_if_false=False)
  365 + self.indicators.append(ext_rels)
  366 + # this check only works for OpenXML files
  367 + if not self.ftg.is_openxml():
  368 + return ext_rels
  369 + # to collect relationship types:
  370 + rel_types = set()
  371 + # open an XmlParser, using a BytesIO instead of filename (to work in memory)
  372 + xmlparser = ooxml.XmlParser(self.data_bytesio)
  373 + for rel_type, target in oleobj.find_external_relationships(xmlparser):
  374 + log.debug('External relationship: type={} target={}'.format(rel_type, target))
  375 + rel_types.add(rel_type)
  376 + ext_rels.value += 1
  377 + if ext_rels.value > 0:
  378 + ext_rels.description = 'External relationships found: {} - use oleobj for details'.format(
  379 + ', '.join(rel_types))
  380 + ext_rels.risk = RISK.HIGH
  381 + return ext_rels
  382 +
356 383 def check_word(self):
357 384 """
358 385 Check whether this file is a word document
... ...