From 1651ac4bd58c661ab6d5fc5d08c013e7d8d8c2da Mon Sep 17 00:00:00 2001 From: Joseph Boiteau Date: Tue, 20 Dec 2016 16:08:56 +1100 Subject: [PATCH] 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()