Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgresql logging capabilities #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Wordpot is a Wordpress honeypot which detects probes for plugins, themes, timthu
--plugins=PLUGINS Fake installed plugins
--themes=THEMES Fake installed plugins
--ver=VERSION Wordpress version
--server=SERVER Custom server header

To configure the honeypot you can edit the config file `wordpot.conf` or provide arguments trough the command line interface as shown above.

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Flask==0.10.1
-e git+https://github.com/threatstream/hpfeeds/#egg=hpfeeds-dev
psycopg2
8 changes: 8 additions & 0 deletions wordpot.conf
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ HPFEEDS_PORT = 10000
HPFEEDS_IDENT = 'wordpot'
HPFEEDS_SECRET = 'wordpot-pass'
HPFEEDS_TOPIC = 'wordpot.events'

POSTGRESQL_ENABLED = True
POSTGRESQL_DATABASE = 'database'
POSTGRESQL_USER = 'username'
POSTGRESQL_PASSWORD = 'password'
POSTGRESQL_HOST = '127.0.0.1'
POSTGRESQL_PORT = 5432

103 changes: 103 additions & 0 deletions wordpot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,109 @@ def check_options():
else:
LOGGER.warn('hpfeeds is disabled')

if app.config['POSTGRESQL_ENABLED']:
import psycopg2
print 'Connecting to postgresql {}:{}'.format(app.config['POSTGRESQL_HOST'], app.config['POSTGRESQL_PORT'])
app.config['postgresql_dbh'] = psycopg2.connect(database=app.config['POSTGRESQL_DATABASE'], user=app.config['POSTGRESQL_USER'], password=app.config['POSTGRESQL_PASSWORD'], host=app.config['POSTGRESQL_HOST'], port=app.config['POSTGRESQL_PORT'])
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS
login_attempts (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
username TEXT,
password TEXT,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
login_page_probes (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
file_probes (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
probed_filename TEXT,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
plugins_probes (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
probed_plugin TEXT,
path TEXT,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
themes_probes (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
probed_theme TEXT,
path TEXT,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
author_probes (
id SERIAL PRIMARY KEY,
plugin TEXT,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
probed_author TEXT,
user_agent TEXT,
url TEXT,
timestamp TIMESTAMP
);""")
cursor.execute("""CREATE TABLE IF NOT EXISTS
connections (
id SERIAL PRIMARY KEY,
source_ip TEXT,
source_port INTEGER,
dest_host TEXT,
dest_port INTEGER,
user_agent TEXT,
url TEXT,
method TEXT,
path TEXT,
headers TEXT,
timestamp TIMESTAMP
);""")
app.config['postgresql_dbh'].commit()
else:
LOGGER.warn('postgresql is disabled')


# ------------------------
# Add Custom Server Header
Expand Down
5 changes: 5 additions & 0 deletions wordpot/plugins/badlogin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from wordpot.plugins_manager import BasePlugin

import datetime

class Plugin(BasePlugin):
def run(self):
# Initialize template vars dict
Expand All @@ -17,10 +19,13 @@ def run(self):
password = self.inputs['request'].form['pwd']
self.outputs['log'] = '%s tried to login with username %s and password %s' % (origin, username, password)
self.outputs['log_json'] = self.to_json_log(username=username, password=password, plugin='badlogin')
self.outputs['log_postgresql_login_attempt'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"username": self.inputs['request'].form['log'],"password": self.inputs['request'].form['pwd'],"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}

self.outputs['template_vars']['BADLOGIN'] = True
self.outputs['template'] = 'wp-login.html'
else:
self.outputs['log'] = '%s probed for the login page' % origin
self.outputs['log_postgresql_login_page_probes'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}
self.outputs['template_vars']['BADLOGIN'] = False
self.outputs['template'] = 'wp-login.html'

Expand Down
3 changes: 3 additions & 0 deletions wordpot/plugins/commonfiles.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from wordpot.plugins_manager import BasePlugin

import datetime

class Plugin(BasePlugin):
def run(self):
# Initialize template vars dict
Expand All @@ -20,6 +22,7 @@ def run(self):
if filename in common:
self.outputs['log'] = '%s probed for: %s' % (origin, filename)
self.outputs['log_json'] = self.to_json_log(filename=filename, plugin='commonfiles')
self.outputs['log_postgresql_file_probes'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"probed_filename": filename,"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}
self.outputs['template'] = common[filename]

return
8 changes: 8 additions & 0 deletions wordpot/plugins/timthumb.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from wordpot.plugins_manager import BasePlugin
import re

import datetime

TIMTHUMB_RE = re.compile('[tim]*thumb|uploadify', re.I)

class Plugin(BasePlugin):
Expand All @@ -11,6 +13,12 @@ def run(self):
log = '%s probed for timthumb: %s' % (self.inputs['request'].remote_addr, self.inputs['subpath'])
self.outputs['log'] = log
self.outputs['log_json'] = self.to_json_log(filename=self.inputs['subpath'], plugin='timthumb')
if 'theme' in self.inputs:
self.outputs['log_postgresql_themes_probes'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"probed_theme": self.inputs['theme'],"path": self.inputs['subpath'],"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}

if 'plugin' in self.inputs:
self.outputs['log_postgresql_plugins_probes'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"probed_plugin": self.inputs['plugin'],"path": self.inputs['subpath'],"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}

# Template to render
self.outputs['template'] = 'timthumb.html'

Expand Down
3 changes: 3 additions & 0 deletions wordpot/plugins/userenumeration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from wordpot.plugins_manager import BasePlugin
from wordpot import app

import datetime

class Plugin(BasePlugin):
def run(self):
# Initialize template vars dict
Expand All @@ -15,6 +17,7 @@ def run(self):
if (k + 1) == int(req_args['author']):
self.outputs['log'] = '%s probed author page for user: %s' % (origin, a)
self.outputs['log_json'] = self.to_json_log(author=a, plugin='userenumeration')
self.outputs['log_postgresql_author_probes'] = {"source_ip": self.inputs['request'].remote_addr,"source_port": self.inputs['request'].environ['REMOTE_PORT'],"dest_host": self.inputs['request'].environ['SERVER_NAME'],"dest_port": self.inputs['request'].environ['SERVER_PORT'],"probed_author": a,"user_agent": self.inputs['request'].user_agent.string,"url": self.inputs['request'].url,"timestamp": str(datetime.datetime.now())}
self.outputs['template_vars']['AUTHORPAGE'] = True
self.outputs['template_vars']['CURRENTAUTHOR'] = (k+1, a)
self.outputs['template'] = app.config['THEME'] + '.html'
Expand Down
76 changes: 76 additions & 0 deletions wordpot/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,56 @@
from wordpot.helpers import *
from wordpot.logger import LOGGER

import psycopg2
import datetime

TEMPLATE = app.config['THEME'] + '.html'

@app.route('/', methods=['GET', 'POST'])
@app.route('/<filename>.<ext>', methods=['GET', 'POST'])
def commons(filename=None, ext=None):

if app.config['POSTGRESQL_ENABLED']:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO connections (source_ip, source_port, dest_host, dest_port, user_agent, url, method, path, headers, timestamp) VALUES (%(remote_addr)s,%(remote_port)s,%(server_name)s,%(server_port)s,%(user_agent)s,%(url)s,%(method)s,%(path)s,%(headers)s,%(timestamp)s)", {"remote_addr": request.remote_addr, "remote_port": request.environ['REMOTE_PORT'], "server_name": request.environ['SERVER_NAME'], "server_port": request.environ['SERVER_PORT'], "user_agent": request.user_agent.string, "url": request.url, "method": request.method, "path": request.path, "headers": str(request.headers), "timestamp": str(datetime.datetime.now())})
app.config['postgresql_dbh'].commit()


# Plugins hook
for p in pm.hook('commons'):
p.start(filename=filename, ext=ext, request=request)
if 'log' in p.outputs:
LOGGER.info(p.outputs['log'])
if 'log_json' in p.outputs and app.config['HPFEEDS_ENABLED']:
app.config['hpfeeds_client'].publish(app.config['HPFEEDS_TOPIC'], p.outputs['log_json'])
if 'log_postgresql_login_attempt' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO login_attempts (plugin, source_ip, source_port, dest_host, dest_port, username, password, user_agent, url, timestamp) VALUES ('badlogin',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(username)s,%(password)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_login_attempt'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'log_postgresql_login_page_probes' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO login_page_probes (plugin, source_ip, source_port, dest_host, dest_port, user_agent, url, timestamp) VALUES ('badlogin',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_login_page_probes'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'log_postgresql_author_probes' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO author_probes (plugin, source_ip, source_port, dest_host, dest_port, probed_author, user_agent, url, timestamp) VALUES ('userenumeration',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(probed_author)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_author_probes'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'log_postgresql_file_probes' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO file_probes (plugin, source_ip, source_port, dest_host, dest_port, probed_filename, user_agent, url, timestamp) VALUES ('commonfiles',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(probed_filename)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_file_probes'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'template' in p.outputs:
if 'template_vars' in p.outputs:
return render_template(p.outputs['template'], vars=p.outputs['template_vars'])
Expand All @@ -37,6 +74,11 @@ def admin(subpath='/'):
origin = request.remote_addr
LOGGER.info('%s probed for the admin panel with path: %s', origin, subpath)

if app.config['POSTGRESQL_ENABLED']:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO connections (source_ip, source_port, dest_host, dest_port, user_agent, url, method, path, headers, timestamp) VALUES (%(remote_addr)s,%(remote_port)s,%(server_name)s,%(server_port)s,%(user_agent)s,%(url)s,%(method)s,%(path)s,%(headers)s,%(timestamp)s)", {"remote_addr": request.remote_addr, "remote_port": request.environ['REMOTE_PORT'], "server_name": request.environ['SERVER_NAME'], "server_port": request.environ['SERVER_PORT'], "user_agent": request.user_agent.string, "url": request.url, "method": request.method, "path": request.path, "headers": str(request.headers), "timestamp": str(datetime.datetime.now())})
app.config['postgresql_dbh'].commit()

# Plugins hook
for p in pm.hook('plugins'):
p.start(subpath=subpath, request=request)
Expand All @@ -58,6 +100,11 @@ def plugin(plugin, subpath='/'):
origin = request.remote_addr
LOGGER.info('%s probed for plugin "%s" with path: %s', origin, plugin, subpath)

if app.config['POSTGRESQL_ENABLED']:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO connections (source_ip, source_port, dest_host, dest_port, user_agent, url, method, path, headers, timestamp) VALUES (%(remote_addr)s,%(remote_port)s,%(server_name)s,%(server_port)s,%(user_agent)s,%(url)s,%(method)s,%(path)s,%(headers)s,%(timestamp)s)", {"remote_addr": request.remote_addr, "remote_port": request.environ['REMOTE_PORT'], "server_name": request.environ['SERVER_NAME'], "server_port": request.environ['SERVER_PORT'], "user_agent": request.user_agent.string, "url": request.url, "method": request.method, "path": request.path, "headers": str(request.headers), "timestamp": str(datetime.datetime.now())})
app.config['postgresql_dbh'].commit()

# Is the plugin in the whitelist?
if not is_plugin_whitelisted(plugin):
abort(404)
Expand All @@ -69,6 +116,13 @@ def plugin(plugin, subpath='/'):
LOGGER.info(p.outputs['log'])
if 'log_json' in p.outputs and app.config['HPFEEDS_ENABLED']:
app.config['hpfeeds_client'].publish(app.config['HPFEEDS_TOPIC'], p.outputs['log_json'])
if 'log_postgresql_plugins_probes' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO plugins_probes (plugin, source_ip, source_port, dest_host, dest_port, probed_plugin, path, user_agent, url, timestamp) VALUES ('timthumb',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(probed_plugin)s,%(path)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_plugins_probes'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'template' in p.outputs:
if 'template_vars' in p.outputs:
return render_template(p.outputs['template'], vars=p.outputs['template_vars'])
Expand All @@ -83,6 +137,11 @@ def theme(theme, subpath='/'):
origin = request.remote_addr
LOGGER.info('%s probed for theme "%s" with path: %s', origin, theme, subpath)

if app.config['POSTGRESQL_ENABLED']:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO connections (source_ip, source_port, dest_host, dest_port, user_agent, url, method, path, headers, timestamp) VALUES (%(remote_addr)s,%(remote_port)s,%(server_name)s,%(server_port)s,%(user_agent)s,%(url)s,%(method)s,%(path)s,%(headers)s,%(timestamp)s)", {"remote_addr": request.remote_addr, "remote_port": request.environ['REMOTE_PORT'], "server_name": request.environ['SERVER_NAME'], "server_port": request.environ['SERVER_PORT'], "user_agent": request.user_agent.string, "url": request.url, "method": request.method, "path": request.path, "headers": str(request.headers), "timestamp": str(datetime.datetime.now())})
app.config['postgresql_dbh'].commit()

# Is the theme whitelisted?
if not is_theme_whitelisted(theme):
abort(404)
Expand All @@ -94,10 +153,27 @@ def theme(theme, subpath='/'):
LOGGER.info(p.outputs['log'])
if 'log_json' in p.outputs and app.config['HPFEEDS_ENABLED']:
app.config['hpfeeds_client'].publish(app.config['HPFEEDS_TOPIC'], p.outputs['log_json'])
if 'log_postgresql_themes_probes' in p.outputs and app.config['POSTGRESQL_ENABLED']:
try:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO themes_probes (plugin, source_ip, source_port, dest_host, dest_port, probed_theme, path, user_agent, url, timestamp) VALUES ('timthumb',%(source_ip)s,%(source_port)s,%(dest_host)s,%(dest_port)s,%(probed_theme)s,%(path)s,%(user_agent)s,%(url)s,%(timestamp)s)", p.outputs['log_postgresql_themes_probes'])
app.config['postgresql_dbh'].commit()
except Exception as e:
print(e)
if 'template' in p.outputs:
if 'template_vars' in p.outputs:
return render_template(p.outputs['template'], vars=p.outputs['template_vars'])
return render_template(p.outputs['template'], vars={})

return render_template(TEMPLATE, vars={})

@app.route('/<path:path>', methods=['GET', 'POST'])
def connection(path='/'):

if app.config['POSTGRESQL_ENABLED']:
cursor = app.config['postgresql_dbh'].cursor()
cursor.execute("INSERT INTO connections (source_ip, source_port, dest_host, dest_port, user_agent, url, method, path, headers, timestamp) VALUES (%(remote_addr)s,%(remote_port)s,%(server_name)s,%(server_port)s,%(user_agent)s,%(url)s,%(method)s,%(path)s,%(headers)s,%(timestamp)s)", {"remote_addr": request.remote_addr, "remote_port": request.environ['REMOTE_PORT'], "server_name": request.environ['SERVER_NAME'], "server_port": request.environ['SERVER_PORT'], "user_agent": request.user_agent.string, "url": request.url, "method": request.method, "path": request.path, "headers": str(request.headers), "timestamp": str(datetime.datetime.now())})
app.config['postgresql_dbh'].commit()

abort(404)