Import from old repository

This commit is contained in:
Stefan
2020-04-06 18:48:34 +02:00
commit 0da6783a45
762 changed files with 103065 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2013 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This file contains an import statement for each browser cookie plugin."""
from plaso.parsers.cookie_plugins import ganalytics
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2013 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This file contains a plugin for parsing Google Analytics cookies."""
import urllib
from plaso.events import time_events
from plaso.lib import errors
from plaso.lib import eventdata
from plaso.parsers.cookie_plugins import interface
class GoogleAnalyticsEvent(time_events.PosixTimeEvent):
"""A simple placeholder for a Google Analytics event."""
DATA_TYPE = u'cookie:google:analytics'
def __init__(
self, timestamp, timestamp_desc, url, data_type_append, cookie_name,
**kwargs):
"""Initialize a Google Analytics event.
Args:
timestamp: The timestamp in a POSIX format.
timestamp_desc: A string describing the timestamp.
url: The full URL where the cookie got set.
data_type_append: String to append to the data type.
cookie_name: The name of the cookie.
"""
super(GoogleAnalyticsEvent, self).__init__(
timestamp, timestamp_desc, u'{0:s}:{1:s}'.format(
self.DATA_TYPE, data_type_append))
self.url = url
self.cookie_name = cookie_name
for key, value in kwargs.iteritems():
setattr(self, key, value)
class GoogleAnalyticsUtmzPlugin(interface.CookiePlugin):
"""A browser cookie plugin for Google Analytics cookies."""
NAME = 'google_analytics_utmz'
COOKIE_NAME = u'__utmz'
# Point to few sources for URL information.
URLS = [
(u'http://www.dfinews.com/articles/2012/02/'
u'google-analytics-cookies-and-forensic-implications')]
def GetEntries(
self, parser_context, file_entry=None, parser_chain=None,
cookie_data=None, url=None, **unused_kwargs):
"""Extracts event objects from the cookie.
Args:
parser_context: A parser context object (instance of ParserContext).
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
cookie_data: The cookie data, as a byte string.
url: The full URL or path where the cookie got set.
"""
# The structure of the field:
# <domain hash>.<last time>.<sessions>.<sources>.<variables>
fields = cookie_data.split('.')
if len(fields) > 5:
variables = u'.'.join(fields[4:])
fields = fields[0:4]
fields.append(variables)
if len(fields) != 5:
raise errors.WrongPlugin(u'Wrong number of fields. [{0:d} vs. 5]'.format(
len(fields)))
domain_hash, last, sessions, sources, variables = fields
extra_variables = variables.split(u'|')
kwargs = {}
for variable in extra_variables:
key, _, value = variable.partition(u'=')
try:
value_line = unicode(urllib.unquote(str(value)), 'utf-8')
except UnicodeDecodeError:
value_line = repr(value)
kwargs[key] = value_line
event_object = GoogleAnalyticsEvent(
int(last, 10), eventdata.EventTimestamp.LAST_VISITED_TIME,
url, 'utmz', self.COOKIE_NAME, domain_hash=domain_hash,
sessions=int(sessions, 10), sources=int(sources, 10),
**kwargs)
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
class GoogleAnalyticsUtmaPlugin(interface.CookiePlugin):
"""A browser cookie plugin for Google Analytics cookies."""
NAME = 'google_analytics_utma'
COOKIE_NAME = u'__utma'
# Point to few sources for URL information.
URLS = [
(u'http://www.dfinews.com/articles/2012/02/'
u'google-analytics-cookies-and-forensic-implications')]
def GetEntries(
self, parser_context, file_entry=None, parser_chain=None,
cookie_data=None, url=None, **unused_kwargs):
"""Extracts event objects from the cookie.
Args:
parser_context: A parser context object (instance of ParserContext).
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
cookie_data: The cookie data, as a byte string.
url: The full URL or path where the cookie got set.
"""
# Values has the structure of:
# <domain hash>.<visitor ID>.<first visit>.<previous>.<last>.<# of
# sessions>
fields = cookie_data.split(u'.')
# Check for a valid record.
if len(fields) != 6:
raise errors.WrongPlugin(u'Wrong number of fields. [{0:d} vs. 6]'.format(
len(fields)))
domain_hash, visitor_id, first_visit, previous, last, sessions = fields
# TODO: Double check this time is stored in UTC and not local time.
first_epoch = int(first_visit, 10)
event_object = GoogleAnalyticsEvent(
first_epoch, 'Analytics Creation Time', url, 'utma', self.COOKIE_NAME,
domain_hash=domain_hash, visitor_id=visitor_id,
sessions=int(sessions, 10))
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
event_object = GoogleAnalyticsEvent(
int(previous, 10), 'Analytics Previous Time', url, 'utma',
self.COOKIE_NAME, domain_hash=domain_hash, visitor_id=visitor_id,
sessions=int(sessions, 10))
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
event_object = GoogleAnalyticsEvent(
int(last, 10), eventdata.EventTimestamp.LAST_VISITED_TIME,
url, 'utma', self.COOKIE_NAME, domain_hash=domain_hash,
visitor_id=visitor_id, sessions=int(sessions, 10))
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
class GoogleAnalyticsUtmbPlugin(interface.CookiePlugin):
"""A browser cookie plugin for Google Analytics cookies."""
NAME = 'google_analytics_utmb'
COOKIE_NAME = u'__utmb'
# Point to few sources for URL information.
URLS = [
(u'http://www.dfinews.com/articles/2012/02/'
u'google-analytics-cookies-and-forensic-implications')]
def GetEntries(
self, parser_context, file_entry=None, parser_chain=None,
cookie_data=None, url=None, **unused_kwargs):
"""Extracts event objects from the cookie.
Args:
parser_context: A parser context object (instance of ParserContext).
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
cookie_data: The cookie data, as a byte string.
url: The full URL or path where the cookie got set.
"""
# Values has the structure of:
# <domain hash>.<pages viewed>.10.<last time>
fields = cookie_data.split(u'.')
# Check for a valid record.
if len(fields) != 4:
raise errors.WrongPlugin(u'Wrong number of fields. [{0:d} vs. 4]'.format(
len(fields)))
domain_hash, pages_viewed, _, last = fields
event_object = GoogleAnalyticsEvent(
int(last, 10), eventdata.EventTimestamp.LAST_VISITED_TIME,
url, 'utmb', self.COOKIE_NAME, domain_hash=domain_hash,
pages_viewed=int(pages_viewed, 10))
parser_context.ProduceEvent(
event_object, parser_chain=parser_chain, file_entry=file_entry)
@@ -0,0 +1,139 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for the Google Analytics cookies."""
import unittest
# pylint: disable=unused-import
from plaso.formatters import ganalytics as ganalytics_formatter
from plaso.lib import eventdata
from plaso.lib import timelib_test
from plaso.parsers.cookie_plugins import ganalytics
from plaso.parsers.sqlite_plugins import chrome_cookies
from plaso.parsers.sqlite_plugins import firefox_cookies
from plaso.parsers.sqlite_plugins import test_lib
class GoogleAnalyticsPluginTest(test_lib.SQLitePluginTestCase):
"""Tests for the Google Analytics plugin."""
def setUp(self):
"""Sets up the needed objects used throughout the test."""
def _GetAnalyticsCookies(self, event_queue_consumer):
"""Return a list of analytics cookies."""
cookies = []
for event_object in self._GetEventObjectsFromQueue(event_queue_consumer):
if isinstance(event_object, ganalytics.GoogleAnalyticsEvent):
cookies.append(event_object)
return cookies
def testParsingFirefox29CookieDatabase(self):
"""Tests the Process function on a Firefox 29 cookie database file."""
plugin = firefox_cookies.FirefoxCookiePlugin()
test_file = self._GetTestFilePath(['firefox_cookies.sqlite'])
event_queue_consumer = self._ParseDatabaseFileWithPlugin(plugin, test_file)
event_objects = self._GetAnalyticsCookies(event_queue_consumer)
self.assertEquals(len(event_objects), 25)
event_object = event_objects[14]
self.assertEquals(
event_object.utmcct,
u'/frettir/erlent/2013/10/30/maelt_med_kerfisbundnum_hydingum/')
self.assertEquals(
event_object.timestamp, timelib_test.CopyStringToTimestamp(
'2013-10-30 21:56:06'))
self.assertEquals(event_object.url, u'http://ads.aha.is/')
self.assertEquals(event_object.utmcsr, u'mbl.is')
expected_msg = (
u'http://ads.aha.is/ (__utmz) Sessions: 1 Domain Hash: 137167072 '
u'Sources: 1 Last source used to access: mbl.is Ad campaign '
u'information: (referral) Last type of visit: referral Path to '
u'the page of referring link: /frettir/erlent/2013/10/30/'
u'maelt_med_kerfisbundnum_hydingum/')
self._TestGetMessageStrings(
event_object, expected_msg, u'http://ads.aha.is/ (__utmz)')
def testParsingChromeCookieDatabase(self):
"""Test the process function on a Chrome cookie database."""
plugin = chrome_cookies.ChromeCookiePlugin()
test_file = self._GetTestFilePath(['cookies.db'])
event_queue_consumer = self._ParseDatabaseFileWithPlugin(plugin, test_file)
event_objects = self._GetAnalyticsCookies(event_queue_consumer)
# The cookie database contains 560 entries in total. Out of them
# there are 75 events created by the Google Analytics plugin.
self.assertEquals(len(event_objects), 75)
# Check few "random" events to verify.
# Check an UTMZ Google Analytics event.
event_object = event_objects[39]
self.assertEquals(event_object.utmctr, u'enders game')
self.assertEquals(event_object.domain_hash, u'68898382')
self.assertEquals(event_object.sessions, 1)
expected_msg = (
u'http://imdb.com/ (__utmz) Sessions: 1 Domain Hash: 68898382 '
u'Sources: 1 Last source used to access: google Ad campaign '
u'information: (organic) Last type of visit: organic Keywords '
u'used to find site: enders game')
self._TestGetMessageStrings(
event_object, expected_msg, u'http://imdb.com/ (__utmz)')
# Check the UTMA Google Analytics event.
event_object = event_objects[41]
self.assertEquals(event_object.timestamp_desc, u'Analytics Previous Time')
self.assertEquals(event_object.cookie_name, u'__utma')
self.assertEquals(event_object.visitor_id, u'1827102436')
self.assertEquals(event_object.sessions, 2)
expected_timestamp = timelib_test.CopyStringToTimestamp(
'2012-03-22 01:55:29')
self.assertEquals(event_object.timestamp, expected_timestamp)
expected_msg = (
u'http://assets.tumblr.com/ (__utma) Sessions: 2 Domain Hash: '
u'151488169 Visitor ID: 151488169')
self._TestGetMessageStrings(
event_object, expected_msg, u'http://assets.tumblr.com/ (__utma)')
# Check the UTMB Google Analytics event.
event_object = event_objects[34]
self.assertEquals(
event_object.timestamp_desc, eventdata.EventTimestamp.LAST_VISITED_TIME)
self.assertEquals(event_object.cookie_name, u'__utmb')
self.assertEquals(event_object.domain_hash, u'154523900')
self.assertEquals(event_object.pages_viewed, 1)
expected_timestamp = timelib_test.CopyStringToTimestamp(
'2012-03-22 01:48:30')
self.assertEquals(event_object.timestamp, expected_timestamp)
expected_msg = (
u'http://upressonline.com/ (__utmb) Pages Viewed: 1 Domain Hash: '
u'154523900')
self._TestGetMessageStrings(
event_object, expected_msg, u'http://upressonline.com/ (__utmb)')
if __name__ == '__main__':
unittest.main()
+115
View File
@@ -0,0 +1,115 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2013 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This file contains an interface for browser cookie plugins."""
import abc
from plaso.lib import errors
from plaso.lib import registry
from plaso.parsers import plugins
# TODO: move this into the parsers and plugins manager.
def GetPlugins():
"""Returns a list of all cookie plugins."""
plugins_list = []
for plugin_cls in CookiePlugin.classes.itervalues():
parent_name = getattr(plugin_cls, 'parent_class_name', 'NOTHERE')
if parent_name != 'cookie':
continue
plugins_list.append(plugin_cls())
return plugins_list
class CookiePlugin(plugins.BasePlugin):
"""A browser cookie plugin for Plaso.
This is a generic cookie parsing interface that can handle parsing
cookies from all browsers.
"""
__metaclass__ = registry.MetaclassRegistry
__abstract = True
NAME = 'cookie'
# The name of the cookie value that this plugin is designed to parse.
# This value is used to evaluate whether the plugin is the correct one
# to parse the browser cookie.
COOKIE_NAME = u''
def __init__(self):
"""Initialize the browser cookie plugin."""
super(CookiePlugin, self).__init__()
self.cookie_data = ''
@abc.abstractmethod
def GetEntries(
self, parser_context, file_entry=None, parser_chain=None,
cookie_data=None, url=None, **kwargs):
"""Extract and return EventObjects from the data structure.
Args:
parser_context: A parser context object (instance of ParserContext).
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
cookie_data: Optional cookie data, as a byte string.
url: Optional URL or path where the cookie got set.
"""
def Process(
self, parser_context, file_entry=None, parser_chain=None,
cookie_name=None, cookie_data=None, url=None, **kwargs):
"""Determine if this is the right plugin for this cookie.
Args:
parser_context: A parser context object (instance of ParserContext).
file_entry: Optional file entry object (instance of dfvfs.FileEntry).
The default is None.
parser_chain: Optional string containing the parsing chain up to this
point. The default is None.
cookie_name: The name of the cookie value.
cookie_data: The cookie data, as a byte string.
url: The full URL or path where the cookie got set.
Raises:
errors.WrongPlugin: If the cookie name differs from the one
supplied in COOKIE_NAME.
ValueError: If cookie_name or cookie_data are not set.
"""
if cookie_name is None or cookie_data is None:
raise ValueError(u'Cookie name or data are not set.')
if cookie_name != self.COOKIE_NAME:
raise errors.WrongPlugin(
u'Not the correct cookie plugin for: {0:s} [{1:s}]'.format(
cookie_name, self.NAME))
# This will raise if unhandled keyword arguments are passed.
super(CookiePlugin, self).Process(parser_context, **kwargs)
# Add ourselves to the parser chain, which will be used in all subsequent
# event creation in this parser.
parser_chain = self._BuildParserChain(parser_chain)
self.GetEntries(
parser_context, file_entry=file_entry, parser_chain=parser_chain,
cookie_data=cookie_data, url=url)
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Browser cookie plugin related functions and classes for testing."""
from plaso.parsers import test_lib
class CookiePluginTestCase(test_lib.ParserTestCase):
"""The unit test case for a browser cookie plugin."""