Конкурс [Истории за кодом] На пути к правильному коду.

mrOkey

mrOkey

Red Team
14.11.2017
719
742
Статья для участия в конкурсе Тестирование Веб-Приложений на проникновение.​
Часть 1 - [Истории за кодом] Притча о тривиальности. Брутфорс атака.

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

Presentation Layer. Честно сказать, всё-таки я не определился с вопросом о том, что у нас будет в итоге: консольное приложение, web spa application или вообще оконный интерфейс. Но этот факт, лишь подтверждает, что у нас уже получилась хорошая архитектура. Так как хорошая архитектура позволяет откладывать решения как можно дольше! Действительно, как бы то не было, пользовательский интерфейс мы можем делать каким угодно, в итоге мы просто будем обрабатывать информацию от пользователя и передавать её нашему слою с бизнес логикой. Поэтому пока давайте обойдёмся unit и интеграционными тестами, а интерфейс напишем, когда решим.

Итак, дорогие, мы получили достаточно хорошую архитектуру:

  • Она легко масштабируется:
  • За счёт DI-техник мы получили слабосвязанные слои приложения, которые можно менять независимо друг от друга.
  • Теперь для того, чтоб добавить новую функциональность в приложение у нас есть достаточно чёткий алгоритм действий, достаточно сделать себе чек-лист чтоб не путаться, в дальнейшем всё это будет уже на автомате.
  • Применяя SOLID принципы к нашим классам, мы продолжим поддерживать чистую архитектуру и код.
  • За счёт нашего архитектурного решения – приложение легко тестировать, что мы увидим в дальнейшем на примере. У нас будет код, поведение которого мы можем проверить «от сих до сих», а за счёт того, что тесты будут автоматизированными мы не пропустим неожиданных поломок, что несравненно скажется на скорости разработки.
  • Мы можем выбрать абсолютно любую базу данных, так как мы не завязаны ни на реляционных ни на nosql. Мы вообще распоряжаемся своими моделями на каждом уровне, которые пишем сами.
  • При соблюдении общего подхода к добавлению функциональности мы легко можем работать в команде в параллель и особо не конфликтовать (в изменениях) друг с другом. (оффтоп: когда хотел писать курс для школы codeby, собирался пустить какое-нибудь такое приложение в качестве стажировки для своих… Кто знает может ещё всё впереди)
Но помните, возможно и от этой архитектуры нам придётся отказаться. Пока же поработаем над уровнем доступа к данным, а именно прицепим бд – пусть это будет MSSql, раз уж я придерживаюсь стека Microsoft. Конечно же работать с бд будем через ORM, я возьму Entity Framework. Однако я не буду использовать Code First подход, так как некоторая часть операций будет вынесена на сторону базы данных.

Создадим новую базу данных и сразу переключимся на неё. Я использую SQL Operations Studio, для работы с базами.

1541228451115.png

Далее сделаем таблицу для хранения словаря

1541228458605.png

Особо пока не заворачиваемся с ограничениями. Заполним данными.
1541228477600.png


3 не валидных и один валидный пароль (исключительно для чистоты эксперимента)

Настраиваем EF. Для начала создадим папку DB в ForAticle.DataAccessLayer. Далее добавим новый предмет. RightClick по папке, добавляем ADO.NET Entity Data Model, называем ForArticle.DataBaseModel

1541228499162.png

Далее выбираем способ подключения


1541228515165.png

Дальше всё просто, подключаемся к sql серверу (он должен быть установлен) выбираем нашу таблицу и в результате у нас будет edmx модель, контекст и прочие прелести.

1541228527257.png

Далее напишем реализацию интерфейса IBruteForceDictionaryHandler назовём её просто BruteForceDictionaryHandler. В ней определим метод фрагментированного чтения

1541228542263.png

Поменяем зависимость ServicesDependencies

было

1541228551756.png


Стало

1541228556128.png


Вот мы и переписали часть приложения с файловой системы на базу данных.
Теперь давайте остановимся и подумаем. Специфика работы с базой данных подразумевает определенный алгоритм, который будет неизменен:
  • Открыть соединение с базой данных
  • Выполнить действия
  • Закрыть соединение с базой данных
Давайте воспользуемся этим знанием и определим базовый классы для handler’ов и сервисов. Итак, приступим.
В проекте DataAcessLayer в папке Interfaces создадим папку Base, где и будем создавать абстракции. Первым делом опредеилим интерфейс IDataContextHandler

1541228595207.png

Этот интерфейс будут реализовывать все интерфейсы наших обработчиков. Так же напишем базовый абстрактный класс для наших обработчиков - DataContextHandlerBase.

1541228605919.png

Теперь сделаем интерфейс для процесса исполнения обработчика.

1541228628424.png

И класс

1541228872300.png

Поле _kernel с типом IKernel нужно для разрешение зависимостей, дальше объясню. В методах Do и DoWithTransaction происходит инкапсуляция основного алгоритма, описанного мной выше для работы с бд. Вот так они выглядят:

1541228660766.png

Мы открываем соединение с базой данных. Выполняем действия из Handlera, затем возвращаем результат. Кроме того, в дальнейшем тут будет входная точка для подключения логера.
Теперь напишем базовый класс для всех сервисов.

1541228781881.png

Внимание на метод Exec и ExecWithTransaction. Про оператор using: это такой синтаксический сахар, для классов реализующих IDisposable. После закрывающей фигурной скобки выполняется вызов Dispose для объекта созданного в using, в этом методе мы высвобождаем занятые ресурсы. Напомню, что Dispose для DataContextHandlerProcess выглядит следующим образом

1541228790963.png

Т.е. мы таким образом закрываем соединение. Перепишем класс BruteForceDictionaryService следующим образом.

1541228970466.png

На строке 13 мы прокидываем kernel для разрешения зависимости в вниз по иерархии. На строке 17 мы вызываем метод Exec из базового класса, которому передаём делегат, который будет выполняется в контексте класса DataContextHandlerProccess. Вызовом p.GetHandler<T>() мы инициализируем обработчик данных BruteForceDictionaryHandler. Далее на строке 18 мы получаем словарь из бд. На строке 20 переводим этот словарь в объект DTO и приводим к коллекции методом ToList. Делегат для метода Exec закончил своё выполнение, а значит вызовется метод Dispose, который закроет соединение с бд. Все живы и здоровы.

В следующий статье:
  • Определимся с интерфейсом ( у нас будет web spa приложение на react+redux) покажу как использовать webpack и еже с ним. Напишим компоненты: тулбар, основное меню, таблицу и диалог на добавления\редактирования сущностей нашей системы.
  • Начнём писать тз для нашего приложения.
  • Сделаем сервис по определению столбцов через union в уже упомянутой уязвимости на rootme.
  • Наконец появится ссылка на gitlab с тасками, которые вы сможете брать, для практики.
  • Заменим DI-контейнер на TiniIOC, вследствие чего произведём необходимый рефакторинг.
 
Последнее редактирование:
Мы в соцсетях: