From 1651ac4bd58c661ab6d5fc5d08c013e7d8d8c2da Mon Sep 17 00:00:00 2001 From: Joseph Boiteau Date: Tue, 20 Dec 2016 16:08:56 +1100 Subject: [PATCH 1/2] Return 404 to UserAgents matching list Empty User-Agent should not break Add test for 404 response to /bot/ Wrap User-Agent check in `request_is_valid` method --- snappass/main.py | 12 ++++++++++++ tests.py | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/snappass/main.py b/snappass/main.py index 04e0ef6..5f0f164 100644 --- a/snappass/main.py +++ b/snappass/main.py @@ -1,6 +1,7 @@ import os import sys import uuid +import re import redis from redis.exceptions import ConnectionError @@ -78,6 +79,15 @@ def clean_input(): return time_conversion[time_period], request.form['password'] +def request_is_valid(request): + """ + Ensure the request validates the following: + - not made by some specific User-Agents (to avoid chat's preview feature issue) + """ + known_sneaky_user_agents = ['Slackbot', 'facebookexternalhit', 'Twitterbot', 'Facebot', 'WhatsApp'] + user_agents_regexp = "|".join(known_sneaky_user_agents) + return not re.search(user_agents_regexp, request.headers.get('User-Agent', '')) + @app.route('/', methods=['GET']) def index(): @@ -99,6 +109,8 @@ def handle_password(): @app.route('/', methods=['GET']) def show_password(password_key): + if not request_is_valid(request): + abort(404) password = get_password(password_key) if not password: abort(404) diff --git a/tests.py b/tests.py index 1726068..11c156a 100644 --- a/tests.py +++ b/tests.py @@ -73,6 +73,24 @@ class SnapPassRoutesTestCase(TestCase): rv = self.app.get('/{0}'.format(key)) self.assertTrue(password in rv.get_data(as_text=True)) + def test_bots_denial(self): + """ + Main known bots User-Agent should be denied access + """ + password = "Bots can't access this" + key = snappass.set_password(password, 30) + a_few_sneaky_bots = [ + "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)", + "facebookexternalhit/1.1", + "Twitterbot/1.0", + "_WhatsApp/2.12.81 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", + "WhatsApp/2.16.6/i" + ] + + for ua in a_few_sneaky_bots: + rv = self.app.get('/{0}'.format(key), headers={ 'User-Agent': ua }) + self.assertEquals(rv.status_code, 404) + if __name__ == '__main__': unittest.main() From 58f4658154a197a474740e28ba4f9506662ee88f Mon Sep 17 00:00:00 2001 From: Joseph Boiteau Date: Wed, 11 Jan 2017 13:50:42 +1100 Subject: [PATCH 2/2] Fix code according to @jparise comments - Refactor is_valid_request code - Add "Facebot/1.0" User-Agent string --- snappass/main.py | 8 ++++---- tests.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/snappass/main.py b/snappass/main.py index 5f0f164..b6e530d 100644 --- a/snappass/main.py +++ b/snappass/main.py @@ -1,7 +1,7 @@ import os +import re import sys import uuid -import re import redis from redis.exceptions import ConnectionError @@ -9,6 +9,8 @@ from redis.exceptions import ConnectionError from flask import abort, Flask, render_template, request +SNEAKY_USER_AGENTS = ('Slackbot', 'facebookexternalhit', 'Twitterbot', 'Facebot', 'WhatsApp') +SNEAKY_USER_AGENTS_RE = re.compile('|'.join(SNEAKY_USER_AGENTS)) NO_SSL = os.environ.get('NO_SSL', False) app = Flask(__name__) app.secret_key = os.environ.get('SECRET_KEY', 'Secret Key') @@ -84,9 +86,7 @@ def request_is_valid(request): Ensure the request validates the following: - not made by some specific User-Agents (to avoid chat's preview feature issue) """ - known_sneaky_user_agents = ['Slackbot', 'facebookexternalhit', 'Twitterbot', 'Facebot', 'WhatsApp'] - user_agents_regexp = "|".join(known_sneaky_user_agents) - return not re.search(user_agents_regexp, request.headers.get('User-Agent', '')) + return not SNEAKY_USER_AGENTS_RE.search(request.headers.get('User-Agent', '')) @app.route('/', methods=['GET']) diff --git a/tests.py b/tests.py index 11c156a..bc5e709 100644 --- a/tests.py +++ b/tests.py @@ -82,6 +82,7 @@ class SnapPassRoutesTestCase(TestCase): a_few_sneaky_bots = [ "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)", "facebookexternalhit/1.1", + "Facebot/1.0", "Twitterbot/1.0", "_WhatsApp/2.12.81 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", "WhatsApp/2.16.6/i"