|
|
|
@ -6,93 +6,88 @@ A honeypot for wiki scrapers
@@ -6,93 +6,88 @@ A honeypot for wiki scrapers
|
|
|
|
|
__version__ = "0.0.1" |
|
|
|
|
|
|
|
|
|
import os |
|
|
|
|
import pickle |
|
|
|
|
import re |
|
|
|
|
import pickle # noqa: S403 |
|
|
|
|
|
|
|
|
|
from collections import OrderedDict |
|
|
|
|
from pyramid.httpexceptions import HTTPFound |
|
|
|
|
from pyramid.config import Configurator |
|
|
|
|
from pyramid.response import Response |
|
|
|
|
from pyramid.view import view_config |
|
|
|
|
from pyramid.config import Configurator |
|
|
|
|
from pyramid.httpexceptions import HTTPFound |
|
|
|
|
from pyramid_mailer.message import Message |
|
|
|
|
|
|
|
|
|
from . import utils |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RootResource: |
|
|
|
|
''' A simple 'catch all' resource ''' |
|
|
|
|
"""A simple 'catch all' resource""" |
|
|
|
|
|
|
|
|
|
moin_config_dir = None |
|
|
|
|
moin_wiki_defs = [] |
|
|
|
|
admin_emails = [] |
|
|
|
|
|
|
|
|
|
def __init__(self, request): |
|
|
|
|
''' initialization ''' |
|
|
|
|
"""initialization""" |
|
|
|
|
self.request = request |
|
|
|
|
|
|
|
|
|
def __getitem__(self, key): |
|
|
|
|
''' no child resource lookup, only one view used''' |
|
|
|
|
"""no child resource lookup, only one view used""" |
|
|
|
|
return self |
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
def configure(cls, settings): |
|
|
|
|
''' parses the moinmoin farmconfig file ''' |
|
|
|
|
cls.moin_config_dir = settings['moin.config_path'] |
|
|
|
|
moin_farmconfig = os.path.join(cls.moin_config_dir, 'farmconfig.py') |
|
|
|
|
"""parses the moinmoin farmconfig file""" |
|
|
|
|
cls.moin_config_dir = settings["moin.config_path"] |
|
|
|
|
moin_farmconfig = os.path.join(cls.moin_config_dir, "farmconfig.py") |
|
|
|
|
encoding = utils.guess_encoding(moin_farmconfig) |
|
|
|
|
with open(moin_farmconfig, 'r', encoding=encoding) as fh: |
|
|
|
|
with open(moin_farmconfig, "r", encoding=encoding) as fh: |
|
|
|
|
cls.moin_wiki_defs = list(utils.extract_wiki_definitions(fh)) |
|
|
|
|
cls.admin_emails = settings['mail.admin_email'].split() |
|
|
|
|
|
|
|
|
|
cls.admin_emails = settings["mail.admin_email"].split() |
|
|
|
|
|
|
|
|
|
def get_moin_user(self): |
|
|
|
|
''' returns a name and email address of the current wiki user''' |
|
|
|
|
name, email = '<unknown user>', '<unknown email>' |
|
|
|
|
"""returns a name and email address of the current wiki user""" |
|
|
|
|
name, email = "<unknown user>", "<unknown email>" |
|
|
|
|
try: |
|
|
|
|
moin_data_dir = self._get_wiki_data_dir() |
|
|
|
|
moin_session_dir = os.path.join( |
|
|
|
|
moin_data_dir, |
|
|
|
|
'cache', |
|
|
|
|
'__session__' |
|
|
|
|
) |
|
|
|
|
moin_data_dir, "cache", "__session__" |
|
|
|
|
) |
|
|
|
|
moin_user_id = self._get_user_id(moin_session_dir) |
|
|
|
|
moin_user_file = os.path.join(moin_data_dir, 'user', moin_user_id) |
|
|
|
|
with open(moin_user_file, 'r') as fh: |
|
|
|
|
for line in fh: |
|
|
|
|
if line.startswith('email='): |
|
|
|
|
email = line.split('=', 1)[1].strip() |
|
|
|
|
if line.startswith('name='): |
|
|
|
|
name = line.split('=', 1)[1].strip() |
|
|
|
|
except: |
|
|
|
|
moin_user_file = os.path.join(moin_data_dir, "user", moin_user_id) |
|
|
|
|
with open(moin_user_file, "r") as fh: |
|
|
|
|
for line in fh: |
|
|
|
|
if line.startswith("email="): |
|
|
|
|
email = line.split("=", 1)[1].strip() |
|
|
|
|
if line.startswith("name="): |
|
|
|
|
name = line.split("=", 1)[1].strip() |
|
|
|
|
except: # noqa: S110, E722 |
|
|
|
|
pass |
|
|
|
|
return name, email |
|
|
|
|
|
|
|
|
|
def _get_wiki_data_dir(self): |
|
|
|
|
''' get the data directory by parsing a wiki config ''' |
|
|
|
|
"""get the data directory by parsing a wiki config""" |
|
|
|
|
wiki_name = self._get_wiki_name() |
|
|
|
|
wiki_config = os.path.join(self.moin_config_dir, wiki_name + '.py') |
|
|
|
|
wiki_config = os.path.join(self.moin_config_dir, wiki_name + ".py") |
|
|
|
|
encoding = utils.guess_encoding(wiki_config) |
|
|
|
|
with open(wiki_config, 'r', encoding=encoding) as fh: |
|
|
|
|
with open(wiki_config, "r", encoding=encoding) as fh: |
|
|
|
|
data_dir = utils.extract_data_dir(fh) |
|
|
|
|
return data_dir |
|
|
|
|
|
|
|
|
|
def _get_wiki_name(self): |
|
|
|
|
''' return the internal wiki name for a url ''' |
|
|
|
|
"""return the internal wiki name for a url""" |
|
|
|
|
for name, re_url in self.moin_wiki_defs: |
|
|
|
|
if re.match(re_url, self.request.url): |
|
|
|
|
return name |
|
|
|
|
|
|
|
|
|
def _get_user_id(self, session_dir): |
|
|
|
|
''' extract the user id from the session store ''' |
|
|
|
|
"""extract the user id from the session store""" |
|
|
|
|
session_path = self._get_session_path(session_dir) |
|
|
|
|
with open(session_path, 'rb') as fh: |
|
|
|
|
session_data = pickle.load(fh) |
|
|
|
|
return session_data.get('user.id') |
|
|
|
|
with open(session_path, "rb") as fh: |
|
|
|
|
session_data = pickle.load(fh) # noqa: S301 |
|
|
|
|
return session_data.get("user.id") |
|
|
|
|
|
|
|
|
|
def _get_session_path(self, session_dir): |
|
|
|
|
''' get the path to the session store for a given cookie ''' |
|
|
|
|
"""get the path to the session store for a given cookie""" |
|
|
|
|
for key, value in self.request.cookies.items(): |
|
|
|
|
if key.lower().startswith('moin'): |
|
|
|
|
if key.lower().startswith("moin"): |
|
|
|
|
session_path = os.path.join(session_dir, value) |
|
|
|
|
if os.path.isfile(session_path): |
|
|
|
|
return session_path |
|
|
|
@ -101,45 +96,44 @@ class RootResource:
@@ -101,45 +96,44 @@ class RootResource:
|
|
|
|
|
|
|
|
|
|
@view_config(context=RootResource) |
|
|
|
|
def the_view(context, request): |
|
|
|
|
''' the one and only view for the app ''' |
|
|
|
|
"""the one and only view for the app""" |
|
|
|
|
|
|
|
|
|
name, email = context.get_moin_user() |
|
|
|
|
|
|
|
|
|
body = [ |
|
|
|
|
'The Honey Pot Was Accessed', |
|
|
|
|
'--------------------------', |
|
|
|
|
'', |
|
|
|
|
'This might be an attempt to scrape the whole wiki', |
|
|
|
|
'', |
|
|
|
|
'wiki user: %s (%s)' % (name, email), |
|
|
|
|
'', |
|
|
|
|
'requested url: %s' % request.url, |
|
|
|
|
'request method: %s' % request.method, |
|
|
|
|
'client ip address: %s' % request.client_addr, |
|
|
|
|
'remote ip address: %s' % request.remote_addr, |
|
|
|
|
'', |
|
|
|
|
'headers:' |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
headers = [' %s: %s' % (k, v) for k, v in request.headers.items()] |
|
|
|
|
"The Honey Pot Was Accessed", |
|
|
|
|
"--------------------------", |
|
|
|
|
"", |
|
|
|
|
"This might be an attempt to scrape the whole wiki", |
|
|
|
|
"", |
|
|
|
|
"wiki user: %s (%s)" % (name, email), |
|
|
|
|
"", |
|
|
|
|
"requested url: %s" % request.url, |
|
|
|
|
"request method: %s" % request.method, |
|
|
|
|
"client ip address: %s" % request.client_addr, |
|
|
|
|
"remote ip address: %s" % request.remote_addr, |
|
|
|
|
"", |
|
|
|
|
"headers:", |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
headers = [" %s: %s" % (k, v) for k, v in request.headers.items()] |
|
|
|
|
body.extend(headers) |
|
|
|
|
|
|
|
|
|
body = '\n'.join(body) |
|
|
|
|
body = "\n".join(body) |
|
|
|
|
|
|
|
|
|
message = Message( |
|
|
|
|
subject='[cpi wikis]: HoneyPot Link Was Accessed', |
|
|
|
|
sender=request.registry.settings['mail.default_sender'], |
|
|
|
|
subject="[cpi wikis]: HoneyPot Link Was Accessed", |
|
|
|
|
sender=request.registry.settings["mail.default_sender"], |
|
|
|
|
recipients=context.admin_emails, |
|
|
|
|
body=body |
|
|
|
|
) |
|
|
|
|
body=body, |
|
|
|
|
) |
|
|
|
|
request.mailer.send_immediately(message) |
|
|
|
|
|
|
|
|
|
return HTTPFound('https://www.cpi.uni-freiburg.de/') |
|
|
|
|
return HTTPFound("https://www.cpi.uni-freiburg.de/") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main(global_config, **settings): |
|
|
|
|
""" This function returns a Pyramid WSGI application. |
|
|
|
|
""" |
|
|
|
|
"""This function returns a Pyramid WSGI application.""" |
|
|
|
|
RootResource.configure(settings) |
|
|
|
|
|
|
|
|
|
config = Configurator(settings=settings) |
|
|
|
|