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



Язык программирования Go является довольно молодым языком программирования – разработан компанией Google в 2007 и был официально представлен в 2009 году. Программистам очень понравился данный язык: компилируемый, многопоточный, структурированный и императивный. Его используют такие компании как Microsoft, GitHub, Cloudflare, Heroku, Вконтакте, Mail.Ru. Сразу после релиза языка появились и продолжают создаваться библиотеки и инструменты, помогающие в разработке на Go. Среди этих инструментов также появились и библиотеки для защиты web-приложений. Многие библиотеки, написанные как отдельными разработчиками, так и встроены в стандартный набор библиотек.

Приведем наиболее типичные способы атак на сайты и основные способы их избежать или хотя бы минимизировать данные угрозы:
  1. Предсказуемое значение идентификатора сессии (Credential/Session Prediction).
  2. Межсайтовой подделкой запроса (CSRF).
  3. Межсайтовое выполнение сценариев (Cross-site Scripting, XSS).
  4. Clickjacking.
  5. Внедрение операторов SQL (SQL Injection).

Обзор инструментов для защиты от подобных типов атак я и хотел бы сделать.

Защищаем правильно сессию и cookie

Сессии — явная цель для хакера, поскольку с их помощью можно получить доступ к веб-серверу без необходимости аутентификации. И получается, что не грамотная реализация сессий может подставить под угрозу весь ваш сервис. Если вы решили использовать на своем веб-сервисе сессии то тут Вам пригодится библиотека gorilla . Сессия Gorilla’s помогает справиться с хранением ваших cookie на сервере, а также просто передавать уникальные токены. Помимо этого, может быть полезна библиотека SecureCookie. Такие безопасные cookies не могут быть подделаны, потому что их значения проверяются с помощью HMAC.
В последнее время также очень часто используется технология JSON WebTokens. В этом вам поможет библиотека jwt-go. Подробнее о JWT in Go можно почитать здесь.

CSRF

Теперь рассмотрим борьбу с межсайтовой подделкой запроса или CSRF атаками на сайт. CSRF атака проводится на авторизованного пользователя веб-приложения с помощью уязвимости в данном приложении. Например, злоумышленник может вынудить (с помощью послания письма ссылкой) перейти пользователя на специально подготовленный сайт, осуществляющий некую вредоносную операцию (например, перевод денег на счёт злоумышленника или смену пароля). Для осуществления данной атаки жертва должна быть аутентифицированана на том сервере, куда отправляется запрос. Для предотвращения CSRF атаки – сгенерировать специальный секретный ключ и сохранить в сессию пользователя и на основе этого секретного ключа сформировать по определенному правилу токен. Токен делается так, чтобы, с одной стороны, он был отличен от ключа (в частности, может быть много токенов для одного ключа), с другой – чтобы было легко проверить по токену, сгенерирован ли он на основе данного ключа или нет. В 2015 году исследователь Михаил Фирстов наткнулся на подобную уязвимость на сайте Yota. Недавно нахождение csrf уязвимости на многих сервисах Microsoft принесло 13 000 $ одному британскому исследователю. Это говорит о том, что разработчики до сих пор плохо решают данную проблему и не всегда грамотно.
С этой задачей в Go очень хорошо справляется библиотека NoSurf. Для примера работы библиотеки приведем код программы.



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



Исходный код html документа:



При попытке изменить токен в форме запроса сервер отдает ошибку номер 400 BadRequest.

Также я нашел подобную библиотеку GojiCSRF . Она работает из коробки сразу с SecureCookie и генерирует токены длиной 32 байта. Работает только с запросами, которые могут модифицировать данные и не работает с безопасными http методами (GET, HEAD, OPTIONS, TRACE).
Почти то же самое, но только в упрощенном режиме, позволяет генерировать стандартная библиотека Go XSRFtoken . Она имеет всего две функции — это funcGenerate и funcValid, а также возможность задать время жизни токена.

XSS

Атака XSS или межсайтинговый скриптинг — это тип атаки на веб-систему, заключающийся во внедрении в выдаваемую веб-системой страницу вредоносного кода. Самый известный пример — это угон пользовательских cookies злоумышленником.
На этот случай написано неплохие, на мой взгляд, библиотеки с созвучными названиями. Это blackfriday и bluemonday. Библиотеки быстро настраиваются и удобно запускаются. Могут работать как вместе, так и раздельно. Привел пример кода простой программы, которая получает строку с консоли, экранирует определенные символы, а некоторые просто затирает. Я взял несколько примеров JS скриптов, которые можно использовать при реализации атаки. Пример работы программы приведен на скриншоте ниже, отфильтрованная последовательность выводится между тегами
<p></p>


Код программы:



Вывод результата работы двух библиотек совместно:



А если вы вдруг по какому-то желанию не хотите использовать сторонние библиотеки, то в Go из коробки есть пара полезных функций содержащихся в пакетe html/template:

•funcHTMLEscape(w io.Writer, b []byte) отправляет в w версию b с заменой потенциально опасных символов на их escape-последовательности.
•funcHTMLEscapeString(s string) string возвращает версию s с заменой потенциально опасных символов на их escape-последовательности.
•funcHTMLEscaper(args ...interface{}) string формирует строку из множества аргументов с заменой потенциально опасных символов на escape-последовательности.

Также ваши входные параметры сможет легко «очистить» Sanitizing. На гитхабе этой библиотеки имеется довольно полный тест с входными данными из того же OWASP’a.

Clickjacking

Существует также атака, известная как Clickjacking. Атака «кликджекинг» (англ. Clickjacking) позволяет хакеру выполнить клик на сайте-жертве «от имени посетителя», также известна как подмена пользовательского интерфейса. Тем самым хакер может придумать различные сценарии и, например, перевести с вашего мобильного банка деньги себе на счет всего за пару кликов. Как ни странно, но подобные уязвимости до сих пор находят даже в системах дистанционного банковского обслуживания DBO, хотя, казалось бы, банковские системы должны быть защищены гораздо лучше, чем обычные веб-приложения.

Также для защиты рекомендуется к каждому ответу вашего сервера прикреплять заголовок X-Frame-Options. Сейчас все современные браузеры поддерживают заголовок X-Frame-Options. Он разрешает или запрещает отображение страницы, если она открыта во фрейме. У заголовка может быть три значения:
•SAMEORIGIN — Рендеринг документа, при открытии во фрейме, производится только в том случае, когда верхний (top) документ – с того же домена.
•DENY — Рендеринг документа внутри фрейма запрещён.
•ALLOW-FROM domain — Разрешает рендеринг, если внешний документ с данного домена (не поддерживается в Safari, Firefox).

Пример реализации добавления заголовок ответа в Go.



Secure — небольшая прослойка для удобной настройки безопасных параметров вашего сервиса. Secure умеет работать как с большим количеством фреймворков, так и со стандартным пакетом net/http.

SQL-injection

SQl-injection — один из распространённых способов взлома сайтов и программ, работающих с базами данных, основанный на внедрении в запрос произвольного SQL-кода.
В Go можно использовать параметризованные запросы или как еще называют подготовленные выражения. которые помогают избежать некоторых проблем с SQL-injection.



Также можно использую фильтрацию по регулярному выражению. В данном случае используем рабочую ссылку, содержащую только цифры в id и uid. Пример того как в Go это можно сделать красиво.



Используем экранирование определенных символов. Например, одинарную кавычку.



Вывод программы. Видно, что символ «’» заменяется на последовательность символов «'».
Но также не стоит забывать, что при реализации sql-injection у нас не обязательно должна быть кавычка. Переменная vuln1 как раз содержит данную строку и, проходя через функцию EscapeString, совсем не изменяется.



SafeSQL

SafeSQL – это статический анализатор кода для Go, который позволяет находить SQL injections.

Заключение

Несмотря на то, что Go довольно новый язык программирования, комьюнити очень быстро разрастается и реализует базовые решения, которые встречаются почти в каждом проекте. В том числе и решения, основанные на безопасности веб-приложения. В статье были рассмотрены способы избежания SQL-injection, CSRF, XSS, Clickjacking. Рассмотренные способы не являются панацеей для полной безопасности веб-приложения. Но помогают решить большинство фундаментальных проблем, связанных с информационной безопасностью.

Использованная литература


https://learn.javascript.ru/csrf
https://nvisium.com/blog/2014/11/26/developing-secure-applications-with/
https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/09.1.html
https://learn.javascript.ru/clickjacking
http://0xdabbad00.com/2015/04/18/go_code_auditing/
http://dghubble.com/blog/posts/json-web-tokens-and-go/
Поделиться с друзьями
-->

Комментарии (11)


  1. avdien
    19.08.2016 10:43

    Пишите еще.


    1. 1024bita
      19.08.2016 13:00

      Да, буду стараться писать больше.


  1. ktretyak
    19.08.2016 16:09
    +1

    Интересно, зачем так усложнять CSRF-токен? Разве не достаточно ограничится, скажем, 20 символами? По-моему этого будет более чем достаточно.


    1. kirill_danshin
      20.08.2016 12:09

      Вам кажется, что токен слишком длинный, или что такая техника генерации и валидации токена усложнена? Если кажется, что длинный токен, то нужно помнить, что чем длиннее токен, тем меньше вероятность обойти его тупым подбором. Если же сама техника генерации/валидации усложнена, то я вот, более логичных реализаций csrf-токенов не вижу.


      1. ktretyak
        20.08.2016 12:20
        +2

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


        1. 1024bita
          20.08.2016 20:07

          Ну здесь мы уже исходим из вывода, что безопасность всей системы равна ее самой слабой части. И вот, что бы токены не стали этой самой частью лучше пусть будут они хорошо укомплектованы. А вообще, мне кажется, что разработчики этой библиотеки опирались уже на математику и наверное, на свой опыт.


  1. soshnikov
    20.08.2016 12:10
    +1

    Раз уж вы озадачились просвещением нубов…
    Я питонист. У нас тут все как-то устаканилось: Django, Flask, экзотика для любителей извращений.
    С Go все совсем наоборот. За последний год раза три пытался поковырять, написал несколько небольших утилит. Но, что касается веба — полный фейл.
    Насколько я понимаю, живее всех живых только ортодоксы, которые считают, что для веб-разработки достаточно стандартной библиотеки. Оно конечно можно, но. Если бы не было потребности, не писали бы фреймвоки.
    А с фреймвоками в Go вообще беда. Попуглил, вроде как. Выбрал. Начинаешь разбираться… И тут, херак — выясняется, что за месяц оно уже все устарело и нынче на троне другой фреймвок.
    Так что же есть пришедшее «в серьёз и на долго»? Что можно использовать для того, чтобы обучаясь переводить мелкие проекты и потом не пришлось их переписывать, ибо фреймвок сдох? Или еще подождать пока не устаканится?
    Спасибо


    1. kotenkovandrey
      20.08.2016 19:50

      фреймворки пишут не из-за потребности, а для упрощения (ускорения) разработки.
      Стандартная библиотека Го предоставляет достаточный функционал для работы с вебом. Для отдельных вещей можно библиотеки подключить, например для websocket. На Го пишу в основном микросервисы, а там и без фреймворков хорошо.
      Я не против фрейморков, но иногда складывается впечатление, что некоторые люди могут писать только на фреймворках, чистый язык их пугает.


    1. 1024bita
      20.08.2016 20:00

      Я когда начинал писать api на Go тоже глянул фреймворки, но в то время ничего такого не было тем более типа Django, поэтому взял за основу гориллу и дальше все руками писал,ORM тогда тоже не было. Сейчас хоть можно даже выбирать из нескольких штук. Так что я думаю в ближайшее время стоит ожидать некий монстрообразный фреймворк. Хотя сейчас уже есть некие решения но я их не пробовал и сказать ничего не могу.


  1. mgrigorov_ua
    20.08.2016 22:47

    Автору спасибо за статью!

    Работает только с запросами, которые могут модифицировать данные и не работает с безопасными http методами (GET, HEAD, OPTIONS, TRACE).

    И всё таки TRACE никак нельзя отнести к безопасным HTTP методам.

    TRACE: This method simply echoes back to the client whatever string has been sent to the server, and is used mainly for debugging purposes. This method, originally assumed harmless, can be used to mount an attack known as Cross Site Tracing, which has been discovered by Jeremiah Grossman (OWASP).

    Плюс, понятие безопасного HTTP метода, как-то режет слух. Сколько угодно приложений, где через GET запрос передаются токены/куки/etc, где GET запрос используется вместо POST-запроса, и т.д. и т.п.


    1. 1024bita
      20.08.2016 22:53

      Тут имелось ввиду, что эти запросы ничего не изменяют на стороне сервера. А только запрашивают. Слегка не точно перевел.