Конкурс [Истории за кодом] Притча о тривиальности. Брутфорс атака.

Статья для участия в конкурсе Тестирование Веб-Приложений на проникновение.​

Статья является приквелом к циклу, который я хочу запустить: Истории за кодом. В нём я расскажу о вещах, которых как мне кажется не хватает местным «кодерам». Будут разговоры об архитектуре, базах данных, напишем с вами свой sqlmap, разберём пару эксплойтов, напишем сканер по диапазону, автоатакер по диапазонам и прочее. Будет очень весело. От меня код, проект на gitlab, постоянные ревью ваших пул реквестов, обсуждения и открытые таски. В целом – это то, что я хотел сделать для школы codeby, но делаю бесплатно и на добровольных началах. Своего рода интерактивная обучалка-стажировка для всех. Быстрая публикация статьи и не очень близкая по духу мне тема, связана, разумеется, с конкурсом. Итак погнали.

Современная enterprise разработка, нашими усилиями, свелась к использованию и знанию библиотек, однако даже сейчас многие задают просто поражающие вопросы, я много раз пытался поставить себя на место таких «спрашивающих» и пришёл к выводу, что они просто лентяи.

Ну посудите сами, тот самый минимум необходимый для работы с библиотеками, для создания приложений, это формирование, внимание, строк! Не верим? Хорошо, по крайней мере в тематики этичного хакинга это так. А чтоб мозг не скучал рассмотрим дырку с rootme, только дырка для sql-инъекции, а я буду её брутить (про sql-инъекцию напишу в дальнейших статьях цикла.

Теория

Для успешной атаки важно представлять такое понятие, как, сравнение с ожидаемым результатом.

Оно бывает позитивным и негативным. Позитивное тестирование – это тестирование, при котором мы ожидаем увидеть позитивный эффект. В случае с атакой перебором – позитивным эффектом являлось бы надпись “Welcome back, admin” ну или нечто подобное.

Негативное же тестирование – это такое тестирование, при котором мы ожидаем увидеть негативный результат. Например: «no such user/password» ну или нечто подобное.

Так вот, сейчас мы займёмся негативным тестированием – но для начала – задумаемся о вещах, которые мы сейчас знаем:
  • Мы знаем, что запрос на аутентификацию отправляется http-методом POST.
  • Мы 100% знаем, что в случае неверного сочетания user/password мы получим html страничку в теле которой будет содержаться заголовок, который написан криво: открывается тегом h3 а закрывается тегом h2, с текстом: «Error: no such user/password»
  • Мы знаем, что такое негативное и позитивное тестирование.
Последовательность действий, которая почему-то не может сформироваться в голове у многих форумчан:

Читаем строку из словаря -> парсим её разделитель -> приводим к объекту -> отправляем пост запрос на атакуемый сервер -> получаем ответ -> ищем в ответе имеющиеся сообщением о ошибке -> если нашли переходим к следующей строке в словаре и так пока либо не получим отличную ошибку, либо не получим доступ, либо бан ip. Что делать в подобных ситуациях я думаю рассказывать не надо, хотя может как-нибудь потом опишу.

Есть много способов оптимизировать описанный процесс (поделитесь с другими в комментариях) тут же мы рассматриваем базу.

Практика:

Начнём с того, что, любой код, который делает что-то с web’oм содержит в себе как минимум post и\или get запросы. Говоря почти человеческим языком: это дерьмо как-то работает с rest api того дерьма. Ну или что-то в этом духе. Опять же, направляю вас учить мат часть: как работает интернет, что это вообще за rest такой, и почему 80% людей понятия не имеют о чистом rest, и вообще рассуждения о нём выходит за рамки стати.

Давайте прикинем базовый классик на C# который будет шаблоном наших дальнейших api клиентов. Начнём с необходимых методов, для решения конкретной таски с . А именно с метода создания пост запроса.

1540916245517.png


Wow и всё. На вашем любимом питоне это короче выглядит, но суть, как всегда, не в это. Что делается в этом методе… Создаётся HttpClient (ВНЕЗАПНО!) что это такое? Давайте-ка подумаем… кхмм… даже не знаю! Вероятно, это такая штука, которая как-то (ВНЕЗАПНО!) взаимодействует с http? Так, рассуждаем дальше, я только валидол под язык положу… Неужели это такая штука, которая каким-то образом работает с http протоколом? Кхм.. ВЕРОЯТНО!

Ладно, я больше не буду разговаривать с тобой как с дауном, дорогой читатель, прости! Действительно как мы видим дальше наш клиент отправляет асинхронно пост запрос. Почему асинхроно? Пока тебе хватит следующей информации: в случае асинхронной отправки, мы не обязаны ждать пока нам вернётся ответ, мы просто продолжаем работать с приложением дальше, грубо говоря: чтоб интерфейс не подвисал, кхах.. (на самом деле, я просто не хочу рассказывать скучную теорию потоков и процессов, и почему вот это вот всё происходит, но очевидно, что это не значит, что я её не знаю и тем более не значит, что вам её не нужно знать, наоборот, смысл статьи как раз в том, что бы все поняли как важны тривиальные вещи.)

Итак у нас есть метод, отправляющий пост запрос на адрес HostName, по конечной точке endpoint ( это всё что идёт после доменной зоны) Справедливости ради стоит сказать, что content-type тут задан из-за заголовка, так же создан cookie контейнер, который я почему то не привёл в статье, но все эти настройки объекта, можно узнать (внезапно из документации msdn).

Вернёмся к rootme, посмотрим в devtools(F12) вкладку сеть, а именно за тем, что происходит при отправке запроса с введёнными данными. Т.е. нормально выражаясь, проведём анализ запроса. Вводим admin/admin и получаем следующую картину:

1540916267997.png

Могу вас заверить нас интересует POST запрос, посмотрим на него внимательнее:

1540916323363.png


Поверите ли вы мне, что это все необходимые нам heder’ы? Осталось узнать о содержании!

1540916336893.png


Пожалуй ещё вкладка ответ вызывает интерес

1540916350198.png


Внезапно, правда? Значит, что мы имеем уже сейчас? Какой вектор атаки у нас есть? Правильно – любимый брутфорс. (делать это я разумеется не буду… а хотя ладно буду, но покажу как написать маленький, малюсенький такой брутфорсер ( без приколюх типа прокси, параллелизма и прочего)

Я немного изменил первоначальный метод: добавил headerы. И теперь он выглядит так

1540916382042.png


Как видите в этом тоже нет ничего сложного, просто получаем данные из анализа запроса и добавляем их в defaultsheader. Разумеется, тут можно подменять useragenta, чтоб не палить браузер, и прочее. По-хорошему бы это всё нужно вынести в настройки, но мне лень объяснять за рефакторинг и чистоту кода и т.д. поэтому делать я этого не буду. Хотя ладно приоткрою немного завесу тайн: по уму бы сделать в базовом классе настроечное свойство, а в методе, в цикле пробежаться и добавить header’ов примерно так:

1540916428160.png


соответственно в наследнике в конструкторе зададим свойство Headers (а в дальнейшем можем из бд или файла читать, в зависимости от потребностей)

1540916446246.png


Дальше как говорится дело техники. Ночь. Улица. Словарь. Брутфорс.

Положим x на y, а так же что у нас имелся словарь вида login;pass в txt файле. Спарсим, txt файл (разумеется, надо понимать, что если у нас словарь размером с петабайт, грузить его целиком в оперативную память идея не то, что плохая… феерически идиотская, используйте фрагментированное чтение). В итоге у меня получился вот такой вот классик для сервиса словаря.

1540916463387.png


Разумеется, как сделать «фрагментированное чтение через take-offset» я опустил, вы и сами разберётесь). Таким образом мы имеем(почти) полностью функциональный инструмент для брутфорс-атаки. Почему почти? Потому что, понятное дело нужно организовать взаимодействие классов.

Ну дело за малым:

1540916478707.png


Метод брута

1540916499804.png


Демонстрация:

1540916514853.png


Что мы имеем? Рабочее приложение, которое решает определённую задачу. С первого взгляда всё классно-шоколадно, но увы спешу вас расстроить – это не так. И тут начинается основная часть статьи. А я пока за кофе схожу.

Давайте я вам со сто процентной вероятностью скажу: что такое решение никуда не годится. Его архитектура не обеспечивает приложению ни масштабируемости, ни тестируемости, кроме того, усложняет дальнейшее сопровождение. Вот так выглядит uml-диаграмма сейчас.

1540916533209.png


И теперь мы подошли к основной дилемме архитектуры и основной её эвристике: будьте готовы выбросить своё первое решение. Макконнелл описывает архитектуру системы, как грязную проблема. То есть это такая проблема, для которой оптимальное решение, появляется лишь после нескольких релизов. Так, например, при постройке моста, одни архитекторы не учли, силу ветра. В итоге при урагане мост рухнул, но эту проблему невозможно было решить на тот момент. Новый мост удерживает порывы урагана и всё классно. Так и с программным обеспечением, большинство проблем невозможно решить (а о большинстве проблем вы даже не догадаетесь, независимо от опыта разработки) в первом решении.

Давайте начнём анализ нашей диаграммы. На первый взгляд очевидна проблема с наименованиями. Я завязал классы на название сайта. Так делать не стоит, давайте исправим это переименовав их.

Класс RootMeModel содержит два свойства (атрибута класса) Login и Password. Очевидно, что у такой структуры данных есть более подходящие названия, например AuthenticationsData (данные аутентификации). Логично? Максимально. Согласитесь, человеку, который наш код вдруг будет читать словосочетания данные аутентификации скажет куда больше, чем «модель получи root досутп от меня» (перевёл как со сленга).

Так же в данном классе есть неочевидная проблемка – переопределённый метод ToString. Вот его сигнатура и тело.

1540916546738.png


Данный метод хорошо сработает, в случае, если сервер принимает данные в виде
Код:
"application/x-www-form-urlencoded"

И не сработает, если нужно передавать эти данные в json формате или yaml… Думаю проблема ясна, но вот так в лоб её не решить. Поэтому пока что напишем TODOшку

1540916562227.png


Лирическое отступление для TODOшек. Во многих редакторах кода, то что вы помечаете комментарием TODO отображается на различных таск листах, тем самым давая вам удобную навигацию по коду. Так, например, для Visual Studio Enterprise 2017, которую я использую, Таск лист выглядит так:

1540916580926.png


Следующее, что стоит сделать – это разделить приложение на уровни для изоляции проблем, в частности. Так если ошибка будет в уровне доступа к базе данных\файловой системы, она будет в одном месте, если же ошибка будет в алгоритме атаке, она будет лежать на другом уровне и так далее. Традиционно предлагается следующее разделение:
  • Data access layer – слой доступа к данным.
  • Business layer – слой бизнес логики, в нашем контексте тут будут хранится алгоритмы атаки: на данный момент это способы брутфорса, определение полей для sql инъекций, определение количества столбцов в таблице для sql инъекций и так далее. Классы данного слоя часто называют сервисами.
  • Presentation/UI layer – слой пользовательского интерфейса. Будь то веб приложение, консольной, телеграмм бот, или апи сервис.
  • Frontend layer – для spa веб-приложений часто стоит выделить этот слой, так как порой решения там совсем не тривиальные.
В рамках статьи, в качестве слоя представлений мы будем использовать консольное приложение, возможно потом всё это разрастётся до масштабов web spa и я покажу как делать вещи на react & redux.

Начнём с Data access layer. Первым делом создадим Class Dynamic library (в дальнейшем dll’ку). Дадим ей название проекта и постфикс DataAccessLayer для удобства. Я называю так: ForAticle.DataAccessLayer. Далее определим структуру папок, следующим образом:

1540916592292.png


В папке Models у нас будут лежать модели данных для функциональных возможностей нашего приложения. Чаще всего они повторяют структуру базы данных.

В папке Interfaces будут находятся абстракции и интерфейсы. Основная причина существования этой папки, да и вообще подобного тема для целой книги, поэтому поиск основной информации по темам Dependency Injections, Inversion Of Control я оставлю на плечи любознательного пользователя, современный софт без этих понятий не пишется. От себя, конечно же, порекомендую литературу в конце статьи.

В папке DataHandlers будут находится классы доступа к данным. Так же их можно называть репозиториями (и даже в каком то смысле это правильно, хотя момент спорный).

Данные, которые в нашем приложении, можно где-то хранить:
  • Словари для перебора
  • Словари для подбора названий таблиц для sql
  • Header’ы для апи клиентов
И ещё много чего… Кроме того, эти классы являются реализацией абстракций из папки Interfaces. Ограничимся пока этими классами.

1540916608265.png


Класс ApiClientsSettingsHandler занимается настройкой Апи клиентов, конкретно редактированием, добавлением, удалением Header’ов, HostName’ов и прочего.

Класс BruteForceDictionaryFileHandler занимается хранением словаря в файле. Занимается добавлением новых пар в словарь, их фрагментированном чтением и прочим необходимым.

На момент написания этих слов полная структура выглядит вот так

1540916620590.png


Диаграмма UML будет иметь следующий вид

1540916633266.png


Теперь перейдём к слою с бизнесс логикой. Опять же создаём dll’ку называем её похожим образом, т.е. ForAticle.BusinessLayer и задаём общую структуру.

1540916648934.png


Принцип похож на DataAccessLayer только вместо папки DataHandlers, а так же добавились такие вещи как: BusinessModels, DataTransferObjects, Infrastructure. Всё по порядку:

BusinessModels – папка, которая будет содержать в себе специальные бизнес-объекты, которые, в отличие от DataTransferObjects будут не только хранить в себе состояние, но и выполнять определенные действия.

DataTransferObjects – следовательно нужны для передачи состояния и данных между слоями приложения. Зачастую эти объекты повторяют модели из слоя доступа к данным, но это не всегда так. Такие объекты нужны для того, что бы окончательно инкапсулировать слой доступа к данным и слои бизнес логики, представления.

1540916663701.png


Infrastructure – папка для инфраструктурных классов. Чаще всего для того, чтоб очистить код от рутинных вещей, таких как, разрешение зависимостей, вводят специальные объекты. Так в нашем случае, я использую DI-контейнер ninject, один из способов разрешения зависимостей требует создания настроечного класса-реализации NinjectModule. Выглядит это так:

1540916682565.png


1540916690009.png


Это опять же о «сложной теме, которая на самом деле простая, но надо погуглить». Структура проекта и UML диаграмма:

1540916701641.png


1540916712479.png


В следующей статье поговорим про Presentation Layer, а также
  • Расскажу про хорошие архитектурные трюки
  • Подключим бд
  • Начнём писать sqlmap и даже больше – свой легко масштабируемый и расширяемы фреймворк.
 

Вложения

  • 1540916391660.png
    1540916391660.png
    79 КБ · Просмотры: 286

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Чтоб не копипастили. Конкретно в этом случае неначто смотреть
Именно так я и увидел, но ждал вашего ответа.

Моё мнение такое - если статья идёт с примерами кодов, то код обязательно должен копироваться. Иначе код нельзя проверить, применить, попробовать модифицировать и т.д. То есть статья становится бесполезной.

Что ещё тут я увидел - к чему это предисловие о "светлом будущем", типа напишу кучу интересного софта (кинуть замануху - голосуйте за меня). А может не напишу (главное пообещать, есть такие люди), а может напишу статью типа этой, с обрывками кода на скриншотах...

Если речь идёт о программировании, то должна быть возможность практического применения, а не голая теория.
В общем, это моё субъективное мнение, которое может отличаться от других.
 

mrOkey

Well-known member
14.11.2017
967
975
BIT
0
Именно так я и увидел, но ждал вашего ответа.
Моё мнение такое - если статья идёт с примерами кодов, то код обязательно должен копироваться. Иначе код нельзя проверить, применить, попробовать модифицировать и т.д. То есть статья становится бесполезной.
Зачем делать код копируемым если будет ссылка на гитлаб?

Что ещё тут я увидел - к чему это предисловие о "светлом будущем", типа напишу кучу интересного софта (кинуть замануху - голосуйте за меня). А может не напишу (главное пообещать, есть такие люди), а может напишу статью типа этой, с обрывками кода на скриншотах...
А может ты не будешь делать выводы спустя 16 часов после поста?
я готовлю приложение к командной разработке. Статью я пишу уже две недели, или ты думаешь я 12к символов за 4 часа наколошматил? Как я и сказал в статье, единственная причина почему я выложил её раньше времени - это внезапное объявление конкурса. О светлом будущем упоминание как о планах на цикл.


Если речь идёт о программировании, то должна быть возможность практического применения, а не голая теория.
В общем, это моё субъективное мнение, которое может отличаться от других.
В описании pycharm форматера, практической применимости, конечно больше, чем в моей теоритической статье.
 
  • Нравится
Реакции: 1 человек

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
На самом деле, я обрадовался, когда увидел что кто-то написал статью для конкурса, но после прочтения, у меня осталось то, о чём я написал выше.

Зачем делать код копируемым если будет ссылка на гитлаб?

Опять же, это всё в будущем, а статья написана сейчас и для КОНКУРСА.
В ваших старых статьях было тоже самое - обрывки кода на скриншотах. Именно поэтому, я и обратил на это внимание.
 

mrOkey

Well-known member
14.11.2017
967
975
BIT
0
На самом деле, я обрадовался, когда увидел что кто-то написал статью для конкурса, но после прочтения, у меня осталось то, о чём я написал выше.
Опять же, это всё в будущем, а статья написана сейчас и для КОНКУРСА.
В ваших старых статьях было тоже самое - обрывки кода на скриншотах. Именно поэтому, я и обратил на это внимание.

Просто если я буду выкладывать листинг кода всех файлов с проекта, то тут будет один сплошной код. я могу выложить прямо сейчас ссылку, однако не думаю что это будет хоть сколь-нибудь разумно, учитывая местный уровень надо сначала объяснить вещи как устроен проект. Что я и делаю. Все статьи о программировании написаны в декларативном стиле, особенно с ООП кодом. Не вижу смысла отступать от этого вектора, если кто-то не понимает хоть строчку кода, он может поинтересоваться в комментариях. Что конкретно вам пояснить? Работоспособность чего здесь вы хотите проверить? Вы всерьёз думаете, что я пишу код просто как пишу и не проверяю его?
 

wj6zc

Green Team
06.07.2018
17
11
BIT
0
Ворвусь.
Вот это:
раз
в моей теоритической статье
два
надо сначала объяснить вещи как устроен проект
Претензий вообще никаких. Полезно изучить теорию прежде чем приступить к практике.

Вот это:
Что делается в этом методе… Создаётся HttpClient (ВНЕЗАПНО!) что это такое? Давайте-ка подумаем… кхмм… даже не знаю! Вероятно, это такая штука, которая как-то (ВНЕЗАПНО!) взаимодействует с http? Так, рассуждаем дальше, я только валидол под язык положу… Неужели это такая штука, которая каким-то образом работает с http протоколом? Кхм.. ВЕРОЯТНО!

Ладно, я больше не буду разговаривать с тобой как с дауном, дорогой читатель, прости!
Вызывает к вам отвращение, как к автору. Хотя по техническому содержанию статьи вроде видно, что опыт программирования есть.

Ну и наконец, вот это:
А может ты не будешь делать выводы спустя 16 часов после поста?
учитывая местный уровень
А может ты поглубже своё чсв засунешь?
Да, здесь много откровенных ламеров. Да, много тех, кто только начал свой путь, разбирается в проблемах, учится, задаёт вопросы, пусть они (вопросы) и кажутся кому-то глупыми. Но это вовсе не означает, что можно перестать по-человечески относиться к людям.
Моё первое сообщение на форуме было написано в довольно грубой, как потом выяснилось, форме. Приведу вам тот ответ, что был дан мне. А вы уже сами сделаете выводы. Я сделал.
У нас принято в более спокойном тоне людям помогать. Не нужно ставить себя выше других.
 
  • Нравится
Реакции: DefWolf и n01n02h

mrOkey

Well-known member
14.11.2017
967
975
BIT
0
но это вовсе не означает, что можно перестать по-человечески относиться к людям.
Так я нормально к местным отношусь. И цитата «учитывая местный уровень» оторванна от контекста. Как раз из-за того, что тут большая часть именно обучается я и расписываю эти вещи максимально тупым образом. О чем и заявляю словами «не буду больше говорить как с дауном». Чсв тут не причём )
 
  • Нравится
Реакции: vag4b0nd

DefWolf

Green Team
24.10.2017
288
795
BIT
0
Статья интересная, очень нравится особенно с технической частью, но статья растянута не нужными фразами:
(ВНЕЗАПНО!) что это такое? Давайте-ка подумаем… кхмм… даже не знаю! Вероятно, это такая штука, которая как-то (ВНЕЗАПНО!) взаимодействует с http? Так, рассуждаем дальше, я только валидол под язык положу… Неужели это такая штука, которая каким-то образом работает с http протоколом? Кхм.. ВЕРОЯТНО!

С удовольствием хотел бы почитать продолжение
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!