вторник, 25 сентября 2012 г.

Password Bruter - программа для многопоточного подбора учетных данных к страничкам с form-based авторизацией

Перед разработчиками и тестировщиками web-приложений периодически встают задачи тестирования безопасности разрабатываемого продукта. Один из наиболее известных классификаторов угроз и уязвимостей для web-приложений - The Web Application Security Consortium (The WASC) Threat Classification v2.0.
Одна из популярных уязвимостей (Weaknesses - в классификаторе), встречающихся для web-приложений - это недостатки подсистемы авторизации (WASC-02 Insufficient Authorization). На web-приложение, имеющее данную уязвимость, могут попытаться осуществить атаку (Attacks - в классификаторе) типа "Брутфорс" (WASC-11 Brute Force). При этом злоумышленник может попытаться осуществить подбор учетных данных на странице авторизации, если она недостаточно защищена.
К недостаткам защиты страницы авторизации можно отнести:
- отсутствие ограничения по числу попыток авторизации,
- отсутствие поля для ввода дополнительной информации - капчи (capture),
- отсутствие временной задержки между попытками авторизации и другие.
Наличие указанных недостатков в реализации подсистемы авторизации упрощает злоумышленнику доступ к web-приложению.
Одна из разновидностей атаки брутфорсом - подбор учетных данных (Brute Forcing Log-in Credentials) для страницы авторизации (Form-based Auth). Для имитации данного типа атаки был написан свой многопоточный брутфорсер Password Bruter на Python 3.2. В качестве цели было развернуто и использовано уязвимое web-приложение Damn Vulnerable Web Application (DVWA).

1. Краткое описание

Password Bruter - программа для многопоточного подбора учетных данных вида {логин/пароль} к страничкам с form-based авторизацией, написанная на Python 3.2.
Пример странички с form-based авторизацией расположен в DVWA на вкладке "Brute Force".

Предварительные настройки:
  1. Установленный Python 3.2.
  2. Установленный и настроенный пакет Selenium WebDriver для Python 3.2.
Особенности:
  1. Универсальность применения. Bruter подходит для большинства html-форм авторизации, так как поля логина, пароля, кнопки подтверждения входа, условия успешной и неуспешной авторизаций задаются в файле конфигурации через xPath-адресацию.
  2. Многопоточный перебор. Учетные данные перебираются в отдельных потоках.
  3. Имитация действий пользователя. Атака фактически осуществляется в браузерах, запущенных Selenium WebDriver.
  4. Предварительное разбиение множества паролей по отдельным потокам.
  5. Возможность случайного перебора вместо последовательного, для повышения вероятности нахождения валидных учетных данных.
  6. Генератор для создания файла со списком псевдослучайных строк, состоящих из выбранных символов различных алфавитов.
  7. Настройка большинства параметров запуска программы как через командную строку, так и через файл конфигурации.
  8. Предварительная оценка времени работы, ведение подробного лога, формирование отчета о фактическом времени работы, результатах перебора в отдельных потоках, и прочее.

2. Программный код.

Программный код доступен в zip-архиве по ссылке:
https://docs.google.com/open?id=0B-1rf8K04ZS5UV93bkl6bjdiS1U
Код на GitHub:
https://github.com/Tim55667757/pwd_brut


Структура проекта

pwd_brut             - корень проекта.
        /browser_drivers - каталог с Windows-драйверами для chrome и ie.
        /ff_profile      - каталог для индивидуального профиля мозиллы (пустой по умолчанию).
        /dict            - каталог по умолчанию для словарей со списками учетных данных.
                pwd.txt      - текстовый файл по умолчанию для списка паролей.
                users.txt    - текстовый файл по умолчанию для списка логинов.
        pwd_brut.py      - основной модуль для многопоточного запуска брутфорса.
        bruter_lib.py    - библиотека функций брутфорсера.
        config.py        - файл с переменными для конфигурации программы.
        readme.txt       - актуальная информация по проекту.
        result.txt       - текстовый файл по умолчанию для вывода результатов брутфорса.

Содержимое модуля pwd_brut.py

Main() # Инициализация параметров, создание и сопровождение потоков, открытие браузеров, запуск брутфорса в потоках.

Содержимое модуля bruter_lib.py

Основные глобальные переменные:
workDir = os.path.abspath(os.curdir) # Рабочая директория проекта, относительно которой строятся другие пути.
threads = [] # Список потоков.
browsers = [] # Список запущенных браузеров. Каждый браузер в отдельном потоке.

Основные функции:
ParseArgs() # Парсер аргументов командной строки.
EstimateTime(numLogins, numPasswords, waitInSec, rumpUp, treadsNum) # Функция расчета ожидаемого времени работы.
DurationOperation(func) # Декоратор для оценки времени работы функций.
StringOfNumToNumsList(string) # Конвертер строки чисел с разделителями в список чисел.
GetListFromfile(file) # Получение списка строк из файла.
SeparateListByPieces(fullList, piecesNum) # Возвращает список списков, полученных разбиением входного списка на указанное число "кусков".
Reporting(instance, file, creds, users, passwords, actualTime) # Репортер для брутфорсера.
OpenBrowser(instance, opTimeout, browserString, ffProfile) # Открытие и подготовка браузера к работе.
GoingToTarget(instance, opTimeout, targetURL, loginField, passwordField, acceptButton) # Переход к целевой страничке.
CloseBrowser(instance=0) # Завершение работы браузера.
Cleaner() # Функция для корректного завершения всех операций и потоков программы.
GenerateRandomString(length, useNum, useEngUp, useEngLo, useRuUp, useRuLo, useSpecial) # Генерация псевдослучайной строки указанной длины, состоящей из символов указанных алфавитов.
GenerateListOfRandomStrings(numbers, length, useNum, useEngUp, useEngLo, useRuUp, useRuLo, useSpecial) # Генерация листа с указанным числом псевдослучайных строк.
GenerateFileWithRandomStrings(par) # Генерация файла со списком псевдослучайных строк.
Bruter(instance, opTimeout, loginField, passwordField, acceptButton, successAuth, failAuth, users=None, passwords, randomization, result) # Основная функция для перебора учётных данных.

В ходе работы, программа выводит в консоль подробные логи о выполняемых действиях и расчетное время операций подбора. Результаты программы выводятся по умолчанию в файл result.txt.

3. Запуск программы.

Password Bruter можно запустить без параметров, в этом случае он начнет подбирать учетные данные согласно настройкам по умолчанию, заданным в файле конфигурации config.py. Все параметры содержат комментарии. Рекомендуется не изменять имена переменных-параметров.

Параметры для консольного запуска представлены ключами:
КлючСлово        Описание
-h
--helpПоказать подсказку по опциям.
-t
--targetЦелевой URL для программы, указывающий на страничку с form-based авторизацией. Примеры: 
--target=http://mysite.com/admin/    t http://site.ru/
-b
--browserСтрока браузера (*firefox, *chrome, *ie), показывающая, в каком браузере запустить перебор. По умолчанию, запускается firefox. Примеры: 
--browser=*chrome    -b *ie
-r
--randomЕсли ключ равен True, тогда программа использует случайные учетные данные при переборе. Примеры: 
--random=True    -r False
-T
--threadsЧисло потоков, в которых будет запущен перебор. Примеры: 
--threads=5    -T 10
-w
--waitОжидание успешного завершения операций в браузере, сек. Примеры: 
--wait=2    -w 1
-p
--periodПериод, в течении которого следует запустить все потоки. Ориентировочно +5 сек. на поток. Примеры: 
--period=10    -p 5
-L--loginsПуть к текстовому файлу со списком логинов. По умолчанию, dict/users.txt. Примеры: 
--logins=my_logins.txt    -L dict/123/my_logins.txt
-P--passwordsПуть к текстовому файлу со списком паролей. По умолчанию, dict/pwd.txt. Примеры: 
--passwords=my_pass.txt    -P dict/123/my_passwords.txt
-R
--results
Путь к текстовому файлу для вывода результатов. По умолчанию, result.txt. Примеры: 
--results=res.log    -R results/res.log
-g
--generatorГенератор псевдослучайных строк, выходной файл: dict/rnd_<date_time>.txt.
На вход подаётся список чисел [1,2,3,4,5,6,7,8], в котором: 
1 число - количество случайных строк,
2 число - длина генерируемых строк, 
3 цифра - {0, 1} - использовать или нет цифры при генерации, 
4 цифра - {0, 1} - использовать (0) или нет (1) большие символы латинского алфавита, 
5 цифра - {0, 1} - использовать (0) или нет (1) маленькие символы латинского алфавита, 
6 цифра - {0, 1} - использовать (0) или нет (1) большие символы русского алфавита, 
7 цифра - {0, 1} - использовать (0) или нет (1) маленькие символы русского алфавита, 
8 цифра - {0, 1} - использовать (0) или нет (1) специальные символы: !@#$%^&*()-_+=.,<>[]{}\|/`~"\':;
Пример: 
--generator=[100,8,1,1,1,0,0,0] 
- сгенерировать 100 случайных строк, длины 8, состоящих только из цифр, больших и маленьких символов латинского алфавита.
Находясь в корне проекта для запуска программы можно использовать команду: python pwd_brut.py [options] [options] - необязательные параметры командной строки, так как все настройки могут быть заданы в config.py.
Примеры использования ключей:

Настройка программы через файл конфигурации config.py

Параметры для цели:
target = 'http://mysite.com/admin/' # Целевая страничка с form-based авторизацией.
xPathLogin = "//input[@name='login']" # xPath для поля логина.
xPathPassword = "//input[@name='password']" # xPath для поля пароля.
xPathAcceptButton = "//input[@type='submit']" # xPath для кнопки подтверждения входа.
xPathSuccessAuth = "//a[@id='loginLink']" # xPath для условия успешной авторизации.
xPathFailAuth = "//div[@id='error']" # xPath для условия провала авторизации.
selBrowserString = '*firefox' # Строка браузера показывает Selenium WebDriver какой браузер нужно запустить: *firefox, *chrome, *ie.
selFFProfile = 'ff_profile' # Профиль Mozilla. Этот параметр используется только ff. Это относительный путь до директории с профилем.

Параметры для брутфорсера:
usersFile = 'dict/users.txt' # Путь к файлу со списком логинов.
passwordsFile = 'dict/pwd.txt' # Путь к файлу со списком паролей.
resultFile = 'result.txt' # Путь к файлу для вывода результатов.
brutThreads = 1 # Число потоков для запуска брутфорса.
rumpUpPeriod = brutThreads * 5 # Период в секундах, показывающий когда все потоки будут запущены.
timeout = 1 # Таймаут операций в сек. Требует особого подбора. Если поставить слишком маленький, есть шанс пропустить успешную авторизацию.
randomCredentials = False # Если ключ равен True, тогда Bruter использует случайные учетные данные, а не по порядку, как указано в файлах с логинами и паролями.

Параметры генератора псевдослучайных строк:
randomGeneratorParameter = [100, 8, 1, 1, 1, 0, 0, 0] # В конфигурации можно указывать список с пробелами. В командной строке - числа могут разделяться только знаками препинания.

4. Пример реализации атаки на страничку авторизации в DVWA.

Было установлено и развернуто приложение DVWA. Для брутера были указаны параметры:
target = 'http://10.111.113.83/dvwa/vulnerabilities/brute/'
xPathLogin = "//input[@name='username']"
xPathPassword = "//input[@name='password']"
xPathAcceptButton = "//input[@name='Login']"
xPathSuccessAuth = "//img[@src='http://10.111.113.83/dvwa/hackable/users/admin.jpg']"
xPathFailAuth = "//pre[contains(text(), 'Username and/or password incorrect.']"
selBrowserString = '*chrome'
usersFile = 'dict/users.txt'
passwordsFile = 'dict/pwd.txt'
resultFile = 'result.txt'
brutThreads = 2
rumpUpPeriod = brutThreads * 5
timeout = 1
randomCredentials = True

На выходе получили результаты в файл result.txt:

12:52:52 25.09.2012 - Thread #0, Bruter finished check for
users = ['admin', ..., ''], 5 items,
passwords = ['', ..., 'user'], 4 items.
Actual time worked: 0:00:05.838000
Suitable credentials: {'admin': ''}

12:53:59 25.09.2012 - Thread #1, Bruter finished check for
users = ['admin', ..., ''], 5 items,
passwords = ['guest', ..., 'qwerty'], 5 items.
Actual time worked: 0:00:09.354000
Bruter can't find suitable credentials.