34
RedisSentry: защищаем python web-сервер от подбора пароля на примере django Максимов Лев Викторович 9 Jul 2012

RedisSentry: защищаем python web-сервер от подбора пароля на примере django

Embed Size (px)

DESCRIPTION

Максимов Лев Викторович 9 Jul 2012. RedisSentry: защищаем python web-сервер от подбора пароля на примере django. ~7000 шт/час. 1 IP, 1 процесс. Способы борьбы с перебором пароля. Captcha , (С ompletely Automated Public Turing test to tell Computers and Humans Apart ) - PowerPoint PPT Presentation

Citation preview

Page 1: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

RedisSentry: защищаем python web-сервер от подбора пароля на примере

django

Максимов Лев Викторович

9 Jul 2012

Page 2: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

2

~7000 шт/час 1 IP, 1 процесс

Page 3: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

3

Способы борьбы с перебором пароля

• Captcha, (Сompletely Automated Public Turing test to tell Computers and Humans Apart)

+ отпугивает не особо заинтересованных атакующих − отпугивает и обычних пользователей тоже+ скрипт из пары строчек уже не сработает − есть специализированные программы-распознаватели и люди-

распознаватели

• Throttling, задержка ответа сервера

+ несколько снижает эффективность атаки − может раздражать пользователя − сложности реализации на синхронном сервере

• Блокировки, не допускает к аутентификации в течение некоторого времени

+ практически неощутимо для пользователя + более эффективно сдерживает атаки

Page 4: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

4

Модули защиты от перебора пароля:

redis …me9 Apr 2012

–3 May 2012

django-redissentry

main db IP & username(company)30 Nov 2009 –

6 Mar 2011

django-brutebuster

main db usernameAlex Kuhl12 Jan 2011

–3 Mar 2011

django-failedloginblocker

memcached IPBrian Jay Stanley

24 Jul 2011 –

18 Oct 2011

django-lockout

main db IPJosh

VanderLinden

1 Oct 2010 -

18 May 2012

django-axes

IP либо IP+username

memcachedSimon Wilson

7 Jan 2009 -24 Sep 2009

ratelimitcache

global либо IPmain dbjensbreit24 Sep 2008 –

24 Sep 2008

django snippet #1083

storage счетчикиauthorfirst commit-

last commit

взломтвиттера

Социальнаясеть

Page 5: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

5

Модули защиты от перебора пароля:способы интеграции

storage счетчикиспособ

интеграции

django snippet #1083 main database global либо IP decorator

ratelimitcache memcachedIP либо

IP+username decorator

django-brutebuster main db IP & username auth

django-axes main db IP login

django-failedloginblocker

main db username auth

django-lockout memcached IP auth

django-redissentry redis … auth

Page 6: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

6

Особенности реализации

• /django-axes/ успешный вход сбрасывает счетчик: - 4*admin, 1*hacker, 4*admin, …

Page 7: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

7

Уязвимости реализации (устранимые)

storage счетчики

django snippet #1083 main database global либо IP

ratelimitcache memcached IP либо IP+username

django-brutebuster main db IP & username

django-axes main db IP

django-failedloginblocker

main db username

django-lockout memcached IP

django-redissentry redis …

сброс счетчика

Page 8: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

8

Особенности реализации

• /main db/ скорость обработки отказа в аутентификации => DDOS

• /django-axes/ успешный вход сбрасывает счетчик: - 4*admin, 1*hacker, 4*admin, …

Page 9: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

9

main db

main db

main db

main db

main db

main db

Уязвимости реализации (устранимые)

IP

username

IP

IP & username

IP либо IP+username

global либо IP

счетчики

memcachedratelimitcache

main dbdjango snippet #1083

redis

memcached

storage

django-axes

django-redissentry

django-lockout

django-failedloginblocker

django-brutebusterDDOS

DDOS

DDOS

сброс счетчика

main db DDOS

Page 10: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

10

Особенности реализации

• /main db/ скорость обработки отказа в аутентификации => DDOS

• /django-axes/ успешный вход сбрасывает счетчик: - 4*admin, 1*hacker, 4*admin, …

• /username/ возможность неограниченного переполнения БД

Page 11: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

11

username

IP & username

IP либо IP+username

username

IP & username

IP либо IP+username

Уязвимости реализации (устранимые)

IP

IP

global либо IP

счетчики

memcachedratelimitcache

main dbdjango snippet #1083

redis

memcached

main db

main db

main db

storage

django-axes

django-redissentry

django-lockout

django-failedloginblocker

django-brutebusterDDOS

DDOS

DDOS

overflow

overflow

overflow

подменазаголовков

сброс счетчика

DDOS

Page 12: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

12

1-to-1 1-to-m m-to-1

IP-адрес + USER_AGENT блок. только 1 браузер

IP-адрес + X_FORWARDED_FOR ровно 1 сет.интерф.

Архитектура модуля

username заодно блок. владелец эккаунта

(IP-address, username) 1M x 1M = 1T

IP-address; username 1M + 1M = 2M; подсеть, владелец

IP-address; username; whitelist много счетчиков

proxy, NAT =>блок. целая подсеть IP-address

Page 13: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

13

Архитектура модуля

• IP-address:

1.2.3.4

[email protected]

• username

1.2.3.4

• (IP,username)

1.2.3.4

• IP-address; username

1.2.3.4

[email protected]

• IP-address; username; whitelist

1.2.3.4

[email protected]

6*1077

~106

Page 14: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

14

Уязвимости архитектуры (неустранимые)

1-to-1 1-to-m m-to-1

django snippet #1083 global либо IP + +

ratelimitcacheIP либо

IP+username+ +

django-brutebuster IP & username + ± ±

django-axes IP + + –

django-failedloginblocker

username+ - +

django-lockout IP + + ±

django-redissentry … + + +

Page 15: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

15

Цель работы

Создание надежного модуля защиты от брутфорса, который можно было бы использовать в production.

Подобрать набор фильтров, который бы одновременно:

− позволял защищать сервер от всех перечисленных видов атак

− не блокировал лишний раз пользователя только по той причине, что из-под его IP была атака и/или на его эккаунт была атака

− не допускал возможности переполнения базы данных счетчиков.

Page 16: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

16

Блок-схема

auth error

Page 17: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

17

Блок-схема

auth error

ip ∈ blacklist ?

ok

no

yes

c++

Page 18: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

18

Блок-схема

auth

username ∈ blacklistB ?

ok

no

yes

ip ∈ blacklistA ?

no

yes

error

cA++cB++

Page 19: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

19

Блок-схема

auth error

ok

no

yes

cA++

ip ∈ blacklistA ?

no

yes

cB++

ip, username ∈ whitelist ?

no

yes

add to whitelist

username ∈ blacklistB ?

Page 20: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

20

Блок-схема

auth error

username ∈ blacklistB ?

ok

no

yes

cA++

ip ∈ blacklistA ?

no

yes

cB++

ip ∈ whitelist ?

noyes

ip,username ∈ blacklistW ?yes

auth

ok

error

cW++

add to whitelist

no

Page 21: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

21

Диаграмма состояний - 1

5 failed attempts

10 min block

5 failed attempts

30 min block5 failed attempts

1 hour block

5 failed attempts

5 min block

5 failed attempts

23 hours block5 failed attempts

23 hours block. . .

Try again in 5 minutes

Page 22: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

22

Диаграмма состояний - 2

5 failed attempts10 min block

5 failed attempts30 min block

5 failed attempts1 hour block

5 failed attempts5 min block

5 failed attempts

23 hours block5 failed attempts

23 hours block. . .

9 blocked attempts1 hour block

9 blocked attempts1 hour block

. . .

из исходного состояния из заблокированного состояния

Page 23: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

23

Диаграмма состояний - 3 (RedisSentryPlus)

5 failed attempts10 min block

5 failed attempts30 min block

5 failed attempts1 hour block

5 failed attempts5 min block

5 failed attempts3..23 hours block

5 failed attempts3..23 hours block

. . .

9 blocked attempts3..23 hours block

9 blocked attempts1 hour block

из исходного состояния из «явно» заблокированного состояния

из «неявно» заблокированного состояния

3 blocked attempts3..23 hours block

3 blocked attempts 3..23 hours block

“Try again later”

Page 24: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

24

Счетчик whitelist’а

• IP: 193.124.10.53 Username: [email protected]

15 bytes ~50 bytes

4*uchar 4 bytes

/24 3 bytes

user_id ~8 bytes

hash(username):

md5(username) 16 bytes

232 = 4*109

7*109 (1 Nov 2011)

? 4 bytes

log26 232=6.8

Page 25: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

25

Hash-функции

• 4 bytes hash-functions:

- additive/xor/rot - elf/snx/djb - fnv/one-at-a-time - superfasthash/lookup3 - murmur3 - md5[:4]

300k

313k/316k/1732166/57/1315/918/1059

100k

98k/100k/35364/5/01/918/1001

• 5 bytes hash-function: md5[:5]1m

0

2m

4

pip install pyhash

• 6 bytes hash-function: md5[:6]

14m

00 0

Page 26: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

26

Счетчики

development production

Ac:ip

Ab:ip

Bc:username

Bb:username

Wc:ip:username

Wb:ip:username

a....

A....

b....

B....

c.......

C.......

ip

hash(username)

ip hash(username)

18

18

53

53

68

68

5

5

5

5

8

8

bytesbytes

Page 27: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

27

Админка

Page 28: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

28

Выбор инструментария

• почему redis, а не couchdb? − expire

• почему redis, а не mongodb? − expire − лучшая устойчивость к перезагрузкам

• почему redis, а не memcached? − удобные структуры данных − лучший контроль используемой памяти − масштабирование (шардинг)

• почему nosql а не sql? − в основном доступ key-value − скорость

Page 29: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

29

Техническая информация

• Лицензия: MIT

• Исходный код: - https://github.com/axil/redissentry-core - https://github.com/axil/django-redissentry

• Тестовая инсталляция: - http://redissentry.alwaysdata.net

Page 30: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

30

Установка и интеграция

• flask:

• django:

MIDDLEWARE_CLASSES += 'redissentry.middleware.RequestMiddleware', INSTALLED_APPS += 'redissentry',

def protected_authprotected_auth(username, password): sentry = RedisSentry(ip, username) msg = sentry.askask() if msg != ‘’: raise Exception(msg) result = authauth(username, password) msg = sentry.informinform(bool(result)) if msg != ‘’: raise Exception(msg) return result

pip install django-redissentry

Page 31: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

31

Заключение

• защита от атак: 1 IP-1 account; 1 IP-many accounts; many IP-1 account

• «гуманность» блокировки за счёт whitelist’а

• невозможность произвольного переполнения базы данных счетчиков

• крайне высокая скорость отказа в допуске к авторизации • кумулятивное нарастание времени блокировки

• мелкие know-how:

- простейший скрипт с фикс. временем задержки блокируется на всё время его работы;

- эффективное время блокировки для атакующего больше, чем для обычного пользователя;

- обработка попыток авторизоваться из заблокированного состояния;

Page 32: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

32

Спасибо за внимание!

Максимов Лев Викторович

RedisSentry: защищаем python web-сервер от подбора пароля на примере django

Page 33: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

33

1-to-1 1-to-m m-to-1

IP-адрес + USER_AGENT блок. только 1 браузер

IP-адрес + X_FORWARDED_FOR ровно 1 сет.интерф.

Архитектура модуля

username заодно блок. владелец эккаунта

(IP-address, username) 1M x 1M = 1T

IP-address; username 1M + 1M = 2M; подсеть, владелец

IP-address; username; whitelist много счетчиков

proxy, NAT =>блок. целая подсеть IP-address

Page 34: RedisSentry:  защищаем python web-сервер  от подбора пароля на примере django

34

Уязвимости реализации (устранимые)

storage счетчики

django snippet #1083 main db global либо IP

ratelimitcache memcached IP либо IP+username

django-brutebuster main db IP & username

django-axes main db IP

django-failedloginblocker

main db username

django-lockout memcached IP

django-redissentry redis …

DDOS

DDOS

DDOS

overflow

overflow

overflow

подменазаголовков

сброс счетчика

DDOS