Move authentication delay into __init__.py and add config

Use the delay for all backends (not only htpasswd).
Add configuration option to configure the delay.
This commit is contained in:
Unrud 2017-05-23 03:11:41 +02:00
parent fb970246e0
commit f2fb07fa84
5 changed files with 18 additions and 5 deletions

3
config
View File

@ -78,6 +78,9 @@
# bcrypt and md5 require the passlib library to be installed.
#htpasswd_encryption = bcrypt
# Incorrect authentication delay (seconds)
#delay = 1
[rights]

View File

@ -34,11 +34,13 @@ import itertools
import os
import posixpath
import pprint
import random
import socket
import socketserver
import ssl
import sys
import threading
import time
import traceback
import wsgiref.simple_server
import zlib
@ -383,6 +385,13 @@ class Application:
is_authenticated = False
else:
is_authenticated = self.Auth.is_authenticated(user, password)
if not is_authenticated:
# Random delay to avoid timing oracles and bruteforce attacks
delay = self.configuration.getfloat("auth", "delay")
if delay > 0:
random_delay = delay * (0.5 + random.random())
self.logger.debug("Sleeping %.3f seconds", random_delay)
time.sleep(random_delay)
# Create principal collection
if user and is_authenticated:

View File

@ -58,8 +58,6 @@ import functools
import hashlib
import hmac
import os
import random
import time
from importlib import import_module
@ -198,6 +196,4 @@ class Auth(BaseAuth):
login, hash_value = line.split(":")
if login == user and self.verify(hash_value, password):
return True
# Random timer to avoid timing oracles and simple bruteforce attacks
time.sleep(1 + random.random())
return False

View File

@ -93,7 +93,10 @@ INITIAL_CONFIG = OrderedDict([
"help": "htpasswd filename"}),
("htpasswd_encryption", {
"value": "bcrypt",
"help": "htpasswd encryption method"})])),
"help": "htpasswd encryption method"}),
("delay", {
"value": "1",
"help": "incorrect authentication delay"})])),
("rights", OrderedDict([
("type", {
"value": "owner_only",

View File

@ -47,6 +47,8 @@ class TestBaseAuthRequests(BaseTest):
self.configuration.set("storage", "filesystem_fsync", "False")
# Required on Windows, doesn't matter on Unix
self.configuration.set("storage", "close_lock_file", "True")
# Set incorrect authentication delay to a very low value
self.configuration.set("auth", "delay", "0.002")
def teardown(self):
shutil.rmtree(self.colpath)