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,7 +98,7 @@ if _parent_dir not in sys.path:
98 sys.path.insert(0, _parent_dir) 98 sys.path.insert(0, _parent_dir)
99 99
100 from oletools.thirdparty.tablestream import tablestream 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 from oletools.common.log_helper import log_helper 102 from oletools.common.log_helper import log_helper
103 from oletools.common.codepages import get_codepage_name 103 from oletools.common.codepages import get_codepage_name
104 104
@@ -243,6 +243,15 @@ class OleID(object): @@ -243,6 +243,15 @@ class OleID(object):
243 self.indicators = [] 243 self.indicators = []
244 self.suminfo_data = None 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 def check(self): 255 def check(self):
247 """ 256 """
248 Open file and run all checks on it. 257 Open file and run all checks on it.
@@ -288,6 +297,7 @@ class OleID(object): @@ -288,6 +297,7 @@ class OleID(object):
288 # self.check_powerpoint() 297 # self.check_powerpoint()
289 # self.check_visio() 298 # self.check_visio()
290 self.check_macros() 299 self.check_macros()
  300 + self.check_external_relationships()
291 self.check_object_pool() 301 self.check_object_pool()
292 self.check_flash() 302 self.check_flash()
293 if self.ole is not None: 303 if self.ole is not None:
@@ -321,21 +331,10 @@ class OleID(object): @@ -321,21 +331,10 @@ class OleID(object):
321 self.indicators.append(author) 331 self.indicators.append(author)
322 return appname, codepage, author 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 def check_encrypted(self): 334 def check_encrypted(self):
334 """ 335 """
335 Check whether this file is encrypted. 336 Check whether this file is encrypted.
336 337
337 - Might call check_properties.  
338 -  
339 :returns: :py:class:`Indicator` for encryption or None if file was not 338 :returns: :py:class:`Indicator` for encryption or None if file was not
340 opened 339 opened
341 """ 340 """
@@ -353,6 +352,34 @@ class OleID(object): @@ -353,6 +352,34 @@ class OleID(object):
353 encrypted.description = 'The file is encrypted. It may be decrypted with msoffcrypto-tool' 352 encrypted.description = 'The file is encrypted. It may be decrypted with msoffcrypto-tool'
354 return encrypted 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 def check_word(self): 383 def check_word(self):
357 """ 384 """
358 Check whether this file is a word document 385 Check whether this file is a word document