Как готовят пентестеров? Разбор вступительных испытаний для стажеров «Digital Security»

Summer of Hack 2019 в Digital Security уже идёт полным ходом, а значит самое время рассказать, как мы набирали людей.

ivefudzwssbwskpfaxaxkczsxvu.jpeg

Под катом объемный и интересный материал о том, как мы отбираем молодых специалистов к нам на стажировку «Summer of Hack 2019», а конкретно — в департамент аудита защищенности.

Рассмотрим, что должен, на на взгляд, знать пентестер, чтобы успешно делать свою работу.

Разберём ряд непростых задачек, которыми мы мучали ребят, в том числе и от лица одного из них.
Пожалуй, наиболее интересной частью отбора на стажировку в департамент аудита защищенности являлась наша анкета. Каждый год мы собираемся всем отделом и обсуждаем, какие навыки, на наш взгляд, являются востребованными для современного специалиста в области практической безопасности, вспоминаем самые интересные задачи, которые приходилось решать в этом году, и выписываем области знаний, без которых сложно представить успешного аудитора. Когда все шутки пошучены, а истории рассказаны, в сухом остатке остается набор идей.

В этом году мы отталкивались от следующих требований:

  • Базовое знание устройства web-приложений и атак на них;
  • Базовое знание браузерных механизмов защиты и разграничения доступа (да-да, тот самый SOP и CORS, куда же без них);
  • Базовые навыки чтения кода и умение видеть за ним логику;
  • Понимание работы компьютерных сетей и маршрутизации в них;
  • Опыт взаимодействия с Linux-подобными системами;
  • Умение не бояться незнакомых технологий. Умение гуглить и систематизировать полученную информацию;
  • И щепотка Android (впрочем, необязательно, но это наша небольшая прихоть).


После были разработаны вопросы. Частично мы их позаимствовали из вопросов, задаваемых нами на собеседованиях, но более половины были специально подготовлены для данной анкеты. Наши специалисты тратили своё личное время на подготовку дампов трафика, спорили, как лучше сформулировать вопрос, а какие уязвимости «слишком специфичны, зачем мучать стажеров». За подобное рвение мы не можем не снять перед ними шляпу (белую, само собой).

Разбор каждого вопроса состоит из двух частей. Первая часть представляет собой ответ одного из наших стажеров — Данила Korgik_0 Леонтьева (он же автор публикации), а вторая — комментарии специалистов, корпевших над анкетой.


Привет, Хабр!

Для начала немного лирического отступления.
А конкретней «Откуда я узнал о Summ3r 0f h4ck».
Об анонсе стажировки я услышал из выступления Дениса Рыбина и Ильи Булатова на конференции RuCTF2019.

Буквально через 4 дня был выложен пост на habr-е об открытии набора на стажировку.

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


Изучите код. Опишите, какие недостатки вы видите и как бы вы их исправили.

s19_e_ersppflil_bq2s-dhxyiw.png

Разбор задания
4 строка — использование md5 хеша.
Проблематика — md5 можно брутить за приемлемое время с использованием hashcat.
How to fix?

Использование более «ресурсоемких» алгоритмов хеширования.
В данном случае необходимо полностью отказаться от куки user и подвязать всю логику к phpsession.

6 строка — PostgreSQL-injections.
How to fix?
Использование prepared statement.
Реализация prepared statement для проверка login-а

$query = "SELECT username FROM login WHERE username=?";
    $stmt = $conn->prepare($query);
	$stmt->execute(array($username));
	$username = $stmt->fetchColumn();
	if($username == FALSE)
	{
		die("Неверный логин!");
	}

11 строка — ряд неудачных решений.
  1. Слишком длинная жизнь сессии. Целый год — это много. При успешном «угоне» cookie возможен длинный доступ к учетной записи пользователя со стороны злоумышленника.
  2. Отсутствие флага httpOnly. Если задано TRUE, cookie будут доступны только через HTTP-протокол. То есть cookie в этом случае не будут доступны скриптовым языкам, вроде JavaScript.
  3. Отсутствие хеширование cookie.
  4. Отсутствие установки флага secure. Флаг secure указывает на то, что значение cookie должно передаваться от клиента по защищенному соединению HTTPS. Если задано TRUE, cookie от клиента будет передано на сервер, только если установлено защищенное соединение.

How to fix?
По умолчанию в php время жизни сессий всего 24 минуты, давайте это и реализуем.
Установим флаг secure, httpOnly.

В данной случае стоит отказаться от странной куки user и подвязать всю логику к phpsession.

18 строка — XSS (англ. Cross-Site Scripting — «межсайтовый скриптинг»).
How to fix? Преобразовывать все возможные символы в соответствующие HTML-сущности.

$query = htmlentities($query, ENT_QUOTES, "UTF-8");

Явно укажем кодировку, для того чтобы избежать её подмены на UTF-7.
header("Content-Type: text/html; charset=utf-8");

22 строка — недочеты системы аутентификации и хранения сессий.

Проблематика — если установить в cookie user id-шник пользователя, закодированный в base64, можно войти в его аккаунт!

How to fix? При авторизации пользователя записываем сессию в БД и при установке сессии проверяем её наличие в БД.

	$query = "SELECT sessions FROM login WHERE sessions=?";
	$stmt = $conn->prepare($query);
	$stmt->execute(array($_COOKIE["user"]));
	$session = $stmt->fetchColumn();
	if($session == TRUE)
	{
		do_login($_COOKIE["user"]);
	}


Комментарий эксперта D:
Первый вопрос, которым анкета встречала будущих стажеров, касался основных и широко известных веб-уязвимостей. Единственной сложностью тут является необходимость увидеть их в исходном коде на PHP. Впрочем, задачу «прятать баги» никто не ставил.

Приведем перечень уязвимостей, которые можно обнаружить в данном листинге в порядке частоты их обнаружения:

Хэширование паролей с использованием алгоритма MD5 замечали даже далекие от веба кандидаты. Впрочем, тут тоже были интересные нюансы, например, многие кандидаты использовали очень некорректные термины, пытаясь своими словами описать проблематику. В бой шли «уязвимости алгоритма», «односторонние функции», «существование коллизий» и другие странные обороты, при ближайшем рассмотрении оказывающимися не более чем набором громких слов, не раскрывающих сути. Конечно, тут мы шли на встречу и не придирались к тем людям, кто только готовится вступить на путь познания премудростей информационной безопасности. Для получения же «зачета» хватило бы и упоминания угрозы, что в случае компрометации базы данных md5-хеши могут быть перебраны злоумышленником за приемлемое время и получены пароли (или эквивалентные им строки) в открытом виде. А, ну и конечно же, многие упоминали отсутствие соли и перебор, основанный на использовании радужных таблиц. Таких комментарии тоже воспринимались нами положительно, особенно, если отвечающий пояснял, почему это является угрозой.

Потенциальная SQL-инъекция. Сложно что-то добавить; при формировании обращения к базе пользовательский ввод логина и пароля напрямую конкатенируются с запросом. Если же манипулировать значением пароля на данном этапе вряд ли получится (от него берётся хэш), то внедрить инъекцию в username не составит труда для потенциального злоумышленника.

Вывод лишней debug информации приводящей к XSS-атаке. Внимательно читая листинг, можно было обратить внимание на вызов echo, отображающий сформированный запрос к базе в HTML-комментарии на страницу. Конечно, подобный вывод дополнительной информации на страницу совсем необязателен и, скорее всего, просто забыт разработчиком после проведения тестов. Такая дополнительная информация очень на руку злоумышленнику и позволяет намного лучше понять принцип работы приложения. Однако, к сожалению, это только полбеды. Дело в том, что злоумышленник может манипулировать содержимым переменной query, а её содержимое никак не фильтруется или экранируется перед выводом на страницу пользователю — налицо потенциальная XSS-атака. Впрочем, эксплуатация её может оказаться той ещё головной болью из-за неудачно расположенной функции strtoupper. Внедряемый злоумышленником вектор будет приведён в верхний регистр, и если для HTML-тегов это не проблема, то вот Javascript сильно обижается на подобное обращение. В этом легко убедиться, воспользовавшись консолью браузера.

cgevoykot6pzht0mx5ppeqyxwne.png

Что ж хоть, видимо, злоумышленнику придётся обратиться к так называемым «scriptless-атакам» или изощренным техникам обхода фильтрации (в данном случае подошел бы JSFUCK), так что факт наличия угрозы безопасности это не отменяет.

Ошибка в логике механизма управления сессий являлась наиболее интересной частью задания. Её обнаружение требовало не просто читать исходник построчно, но и понимать логику работы всего листинга. Почувствовать неладное можно было, заметив выставление cookie, содержащей base64-кодированный id пользователя в блоке remember-me. Дальнейший анализ логики работы данного механизма приводит нас к мысли: «Получается, злоумышленник, знающий или перебравший id, может войти в любой аккаунт без ввода логина и пароля?!». Да, действительно, злоумышленник может на своей стороне самостоятельно сформировать cookie user и присвоить ей любое значение id, закодированное base64. Отправление запроса с такой cookie без username и password привело бы к срабатыванию функции do_login и к входу в чужой аккаунт.

Упоминание этих 4 уязвимостей в ответе кандидатов напрямую влияло на набранные ими баллы.

Однако, многое зависело и от качества ответа. Упоминание способов исправить ситуацию, замечания касательно дополнительных факторов, влияющих на реализуемость той или иной атаки, использование правильных терминов и способность структурировано подать свою мысль, комментарии по поводу дополнительных слабостей или потенциальных угроз — всё это грело нам душу и приводило к повышению итоговой оценки.




В ходе исследования веб-приложения вы обнаружили, что приложение в качестве авторизации использует JWT-токен.

Какие проблемы безопасности вы видите, какие проверки вы бы сделали?

JWT-токен:

eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InNla2EiL CJpYXQiOjE1MTYyMzkwMjIsInJvbGUiOiJub2JvZHkiLCJpc0FkbWluIjoiRmFsc2UiLCJwYX Nzd29yZCI6IjFkMDBjYUgifQ.F7Y1mCAmg5-QFok-rkpLdwe8prCyiKsCyJ-3Z5f7luI


Разбор задания
Дан JSON Web Tokens (JWT).
Его структура → [base64url (HEADER)].[base64url (PAYLOAD)].[base64url (SIGNATURE)]
[base64url (HEADER)] = eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0
base64url decode → {«alg»: «None», «typ»: «JWT»}
Сразу можно отметить тот факт, что не используется алгоритм подписи («alg»: «None») сигнатурки. Некоторые библиотеки JWT не поддерживают алгоритм «none», то есть алгоритм подписи. Когда заголовок alg равен «none», серверная часть не будет выполнять проверку подписи.
Т.е можно записать любой payload в base64url, и подпись к нему не будет проверяться.
Что позволяет нам создать пользователя с правами admin-а.

Также нам упрощает жизнь тот факт, что в части payload не используются такие заголовки как aud (определяет получателей, для которого предназначен JWT-токен) и exp (время жизни токена).

Предполагаемая полезная нагрузка
eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImhhY2siLCJpYXQiOjE1MTYyMzkwMjIsInJvbGUiOiJub2JvZHkiLCJpc0FkbWluIjoiVHJ1ZSIsInBhc3N3b3JkIjoiaGFjayJ9

base64url decode payload → {«sub»:»1234567890», «name»: «hack», «iat»:1516239022, «role»: «nobody», «isAdmin»: «True», «password»: «hack»}


Комментарий эксперта D:
В работе аудитора часто приходится сталкиваться с новыми технологиями, и умение разбираться в них очень важно. Включая этот вопрос в анкету мы предполагали, что большая часть кандидатов вряд ли слышало о технологии JWT-токенов что-то, кроме названия. Поэтому этот вопрос, в первую очередь, был направлен на умение искать и анализировать информацию из публичных источников. В итоге, человек, пропустивший через себя выдачу гугла по запросу «JWT» и «jwt vulnerability», мог прийти к следующим выводам:

1. У данного токена отсутствует алгоритм подписи, поэтому злоумышленник способен модифицировать любые поля внутри токена, что не предполагается концепцией JWT-токенов.

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

3. Помня про отсутствие подписи и нашу возможность модифицировать поля внутри токена, логично предположить, что изменение значения isAdmin может повысить наши привилегии до привилегий администратора.

4. Ещё одна интересная мысль, которую мало кто упоминал в своем ответе, касается самого факта возможности передавать пользовательский ввод в полях JWT-токена. В обычной ситуации злоумышленник никак не может повлиять на данные в токене, а значит, зачастую разработчики могут пренебрегать введением дополнительных проверок в код обработчиков. Отсюда напрашивается простая идея:, а давайте попробуем провести классические атаки не через GET/POST-параметры, а через поля токена. Это может дать неожиданно неплохой результат. Подобный креативный подход с правильным обоснованием своих действий высоко ценился нами при оценивании как данного, так и других вопросов.

Многие кандидаты в своих ответах устраивали краткий пересказ того, как устроен JWT токен, и где он используется, нам было интересно почитать, и всё же, в первую очередь оценивались аспекты ответа касательно безопасности.



В веб-приложении пароль пользователя меняется с помощью следующего запроса (см. Вариант 1). Какие потенциальные угрозы безопасности вы видите? Какие проверки вы бы осуществили? Изменится ли ситуация в случае следующего поведения (см. Вариант 2)? Объясните свой ответ.
mrb-seaadzkgqbmqvsq-zcqflyo.jpeg

Разбор задания
Вариант 1.
«Какие потенциальные угрозы безопасности вы видите?»

1) Отсутствие контроля доступа.
Если не проверяется номер user-a, к которому осуществляется запрос на изменение пароля, то можно изменить пароль любому зарегистрированному пользователю в системе.
How to fix? — Сопоставление JSESSION из БД и запрашиваемого id-шника.

2) Возможность проведения CSRF атаки
Завлекаем авторизованного пользователя на подконтрольный нам хост и сделав запрос, на сайт example.com от имени жертвы, на изменение пароля.
How to fix? — Добавление CSRF токена.

Вариант 2.
«Какие потенциальные угрозы безопасности вы видите?»
Недочет в CORS политике.
Рекомендуется настроить белый список заголовку Аccess-Control-Allow-Origin.

How to fix? —

1) Изменение файла .htaccess


  Header always set Access-Control-Allow-Origin: "https://whitelist.domain.ru"
  Header always set Access-Control-Allow-Methods "PUT"


2) PHP


«Изменится ли ситуация в случае следующего поведения?»

Да. Поскольку во втором случае используется PUT запрос, что важно, поскольку использование PUT запроса делает CORS запрос «сложным», а это в свою очередь полностью лишает нас возможности провести CSRF атаку + отсутствие такого заголовка как Access-Control-Allow-Credentials: true лишает нас возможности отсылать в месте с другими http заголовками и cookie пользователя.


Комментарий эксперта I:
Рассмотрим по порядку, какие основные проблемы видны на приводимых запросах:

1) Действительно, раз в запросе наблюдается числовой идентификатор пользователя »10012», то первым делом стоит проверить, а можно ли сменить пароль другому пользователю? Может достаточно указать чужой id?
Уязвимости класса «IDOR» достаточно легко эксплуатируются и часто имеют высокую критичность.

2) Запрос на смену пароля происходит методом POST, CSRF-токена не наблюдается, а тип содержимого — «text/plain». Налицо возможность подделки такого запроса.

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

3) В заголовках ответа сервер раскрывает версию используемого ПО. Уязвимостью это назвать можно с большой натяжкой, но подобные баннеры лучше скрывать — злоумышленники по ним могут легко найти известные 1-day эксплойты, плюс значение используемого ПО значительно упрощает планирование дальнейших атак.

4) Нам было бы очень приятно увидеть предложение «А что будет, если поменять формат данных с JSON на XML

Дело в том, что современные фреймворки умные, всеядные и могут обрабатывать данные в разных форматах. А в при парсинге XML часто допускается опасная уязвимость XXE. C её помощью нарушитель может и во внутреннюю сеть «сходить», может и файлы конфигурации с сервера прочитать, а изредка и RCE исполнить.

5) Также хотелось увидеть замечание вида «А почему при смене пароля не проверяется знание старого

Что касается «Варианта №2», то в нём кроется «ловушка» — тут используются CORS-заголовки, а Content-Type запроса уже выставлен в «application/json».

Ошибкой, которую допустили абсолютное большинство кандидатов, является ответ вида »-Вот тут в Allow-Origin «звездочка», а значит с любого сайта запросы отправлять можно!»

Нет, нельзя. Во-первых, отсутствует заголовок Allow-Credentials: True означающий, что браузеру следует выполнить запрос «с куками», так что запрос был бы анонимный, без сессии. А во-вторых, даже если бы такой заголовок присутствовал, браузер все равно бы запретил отправку кук — как раз из-за «звездочки». Их комбинация является запрещенной, и браузером игнорируется.



Представьте, что вы попали во внутреннюю сеть компании и перехватили трафик, дамп которого приложен ниже. Распишите, какие атаки вы бы попробовали провести и какими инструментами?

Дамп: yadi.sk/d/qkLcfwSCzdxcwg

Разбор задания
1) LLMNR Spoofing
Злоумышленник в локальной подсети может прослушивать широковещательные сообщения и отвечать на них, утверждая, что запрошенное имя хоста — это его собственный IP-адрес.
Это приводит к тому, что запрашивающий клиентский компьютер подключается к компьютеру злоумышленника и, в зависимости от протокола, может попытаться выполнить аутентификацию.

Используемые утилиты — Intercepter-NG, проект на githab VindicateTool.

2) Злоупотребление протоколом HSRP.
Проблематика — при установленном параметре «preempt» в 1 атакующему доступна возможность «вытеснять» другие роутеры, благодаря более высокому приоритету. После рассылки HSRP по мультикасту подконтрольный роутер становится главным роутером (Active Router) в сети, и весь трафик будет проходить через него. По сути, мы пришли к реализации mitm атаки.

Для данного вектора атаки нам необходимо знать группу и пароль.
Из данного нам дампа трафика мы узнаём группу (она равна — 3) и пароль. Пароль в нашем случае дефолтный — cisco.

Используемые утилиты — yersinia, scapy.


Комментарий эксперта X:
Задачей вопроса являлось определение ознакомленности стажера с современными (и не очень) методиками проведения MitM-атак. Давайте рассмотрим потенциально возможные сценарии, основываясь на имеющемся дампе трафика:

1) ARP спуфинг
ARP-spoofing является самым старым и простым в реализации способом проведения MitM-атак. Заключается он в отправке gratuitous ARP запроса на хост А.

В качестве IP-адреса, указывается IP-адрес хоста B, а в качестве MAC-адрес — наш MAC-адрес. Такой запрос позволяет модифицировать ARP-таблицу на хосте A, заставляя его отправлять запросы на наше устройство, при попытке обратиться к хосту B. Хостом B обычно является шлюз по-умолчанию.

Рекомендуемые инструменты: bettercap, arpspoof

2) LLMNR, NBNS спуфинг
Link-Local Multicast Name Resolution и NetBIOS Name Service — это протоколы, используемые для резолва хостнеймов в локальной сети. В отличие от протокола DNS, тут отсутствует выделенный сервер, хранящий всю информацию, вместо этого запрос отправляется широковещательно на все хосты в сети, если хостнейма в запросе совпадет с хостнеймом устройства — оно отправит ответ.

Как было верно подмечено в ответе, злоумышленник может отвечать на такие запросы, отправляя в ответе свой IP адрес, что приведет к тому, что в будущем жертва будет обращаться на устройство злоумышленника, вместо устройства, хостнейм которого фигурировал в запросе. Помимо этого злоумышленник может запросить у жертвы NTLM-аутентификацию, что заставит устройство жертвы отправить NTLM-хэш, который может быть в дальнейшем использован для перебора.

Рекомендуемые инструменты: Responder

3) WPAD спуфинг
WPAD spoofing можно отнести к частному случаю LLMNR- и NBNS-спуфинга. Web Proxy Auto Discovery protocol служит для автоматической конфигурации HTTP-прокси сервера.

Устройство отправляет LLMNR/NBNS запрос с хостнеймом wpad, получает соответствующий IP-адрес и пытается обратиться по HTTP к файлу wpad.dat, в котором хранится информация о настройках прокси.

Как следствие, злоумышленник может выполнить LLMNR/NBNS-спуфинг и предоставить жертве свой файл wpad.dat, в результате весь HTTP- и HTTPS-трафик пойдет через злоумышленника.

Рекомендуемые инструменты: Responder, mitm6

4) Router Advertisement
Как видно из дампа, в сети присутствуют устройства с включенным IPv6. Находясь в сети, можно попробовать отправить жертве IPv6 Router Advertisement сообщения с целью сменить шлюз по-умолчанию или DNS-сервер.

Router Advertisement (RA) сообщения являются частью механизма SLAAC (Stateless Address Autoconfiguration), который необходим для автоматического получения IPv6 адресов в сети, без использования DHCPv6 сервера, или совместно с ним. Достигается это путем периодической отправки мультикаст RA сообщений маршрутизатором, которые содержат в себе адрес шлюза по-умолчанию, префикс сети, адрес DNS-сервера, префикс домена.

Рекомендуемые инструменты: raw-packet

5) DHCP-спуфинг
Также в дампе с некоторой периодичностью повторяются DHCP Discover-запросы от одного и того же устройства. Можно сделать выводы об отсутствии DHCP-сервера в данной сети и ответить на следующий Discover-запрос, указав жертве свое устройство как шлюз по-умолчанию.

Рекомендуемые инструменты: Yersinia

6) HSRP спуфинг
Помимо этого, в дампе можно заметить HSRP-пакеты. Hot Standby Router Protocol позволяет увеличить доступность маршрутизаторов, выполняющих роль шлюза по-умолчанию. Маршрутизаторы объединяются в одну группу и получают один общий IP-адрес, который используется как шлюз по-умолчанию. С помощью Hello мультикаст-пакетов маршрутизаторы обнаруживают друг друга и добавляются в группу, как раз эти пакеты и присутствуют в имеющемся у нас дампе. На основании этого можно сделать выводы о включенном в сети HSRP, и, как было верно сказано в ответе, можно притвориться маршрутизатором с включенным HSRP и анонсировать себя в качестве главного маршрутизатор в группе.

Рекомендуемые инструменты: Yersinia

7) STP-спуфинг
Spanning Tree Protocol необходим для защиты от возникновения L2-петель в сети. Коммутаторы отправляют специальные BPDU-пакеты, чтобы определить корневой коммутатор и отключить все избыточные пути до него, оставив их в качестве резервных. Так как в дампе мы можем увидеть те самые BPDU-пакеты, можно сделать вывод, что порт коммутатора, смотрящий в сторону устройства, не настроен должным образом, и злоумышленник может анонсировать себя в качестве корневого коммутатора, тем не менее, для достижения успеха, в виду особенностей работы STP, необходимо контролировать не один, а два таких порта.

Рекомендуемые инструменты: Yersinia


Перед вами конфигурация веб-сервера nginx. Подробно опишите, какие проблемы безопасности вы в ней видите?

Конфигурация: pastebin.com/nYp7uVbB

Разбор задания
Дан конфиг nginx, после просмотра конфига мне удалось найти множественные недочеты контроля доступа:
1) В 86 строке, если установить http заголовок X-Managed и присвоить это хедеру значение secured, то nginx пустит нас в директорию /management/
2) Отсутствие какой либо авторизации при доступе к API в 70 и 105 строке.


Комментарий эксперта J:
Задание было добавлено в анкету с целью узнать, насколько хорошо стажеры умеют разбираться в новых для них вещах. Хоть с nginx косвенно знакомы практически все, кто имел дело с web-приложениями, но в большинстве случаев знания об nginx сводятся к настройке web-сервера по примеру/гайду. В больших и архитектурно сложных проектах зачастую можно увидеть запутанные nginx конфиги, через которые, например, связаны друг с другом микросервисы.

Конфиг, предложенный потенциальным кандидатам на стажировку, получился достаточно объемным, и в него было заложено около десятка мелких и достаточно критичных ошибок. Несмотря на такое количество заложенных проблем, заполнившие анкету не очень хорошо справились с этим вопросом. Возможно, многих спугнул объем задания, либо нежелание копаться в документации.

Найти небольшое количество багов можно было воспользовавшись утилитой gixy.

Gixy находит 4 проблемы в нашим конфиге:

1) Alias travesal:

Со строки 80 можно увидеть следующий блок кода:

location /static {
          	alias /prod_static/;
   	}

Такая конструкция позволяет почесть какой-либо файл, находящийся на директорию ниже. Пример эксплуатации: //host/static…/etc/passwd. Происходит это из-за особенностей обработки путей директивой alias: в нашем случае часть пути, стоящая после /static, конкатенируется с /prod_static/, и по итогу мы получим такой путь: /prod_static/…/etc/passwd, что приведет нас к чтению /etc/passwd. Подробнее прочитать про alias traversal можно здесь

2) Http Splitting (CRLF injection)
Некоторые директивы в nginx доверяют данным, передаваемым в заголовок, и не валидируя их при подстановке в запрос. Это может повлечь инъекцию в сам HTTP-запрос.
Подробнее: github.com/yandex/gixy/blob/master/docs/ru/plugins/httpsplitting.md

3) Плохая валидация из-за некорректного регулярного выражения
На строчке 75 можно увидеть проверку значения заголовка «Оrigin» по регулярному выражению. Регулярное выражение обрабатывается некорректно, из-за этого можно получить выполнение условия при использовании, например, домена production.host.evil.com.
Подробнее: github.com/yandex/gixy/blob/master/docs/ru/plugins/origins.md

4) Переопределение заголовков с вложенным add_header
У nginx есть особенность: если во вложенном условии сделать add_header, когда вне условия уже использована эта директива, заголовки, которые прописаны вне условия, не поставятся. То есть в нашем случае CSP не будет при вхождении в условие.
Подробнее: github.com/yandex/gixy/blob/master/docs/ru/plugins/addheaderredefinition.md


Помимо того, что нашел gixy, можно отметить еще несколько не менее интересных багов и недочетов. Просто пойдем по конфигу строка за строкой:

1) В строке 17 можно заметить использование директивы default_type с аргументом text/html. Данная директива работает следующим образом: если тип файла, к которому обращается пользователь неизвестен, то nginx вернет его с Content-Type, равным установленному в default_type. В нашем случае, любой файл с неизвестным расширением будет приходить с Content-Type: text/html. Вкупе с загрузкой файлов эта ошибка может позволить злоумышленнику загружать произвольные HTML-файлы на сервер, которые могут содержать, например, XSS-вектор или фишинговую страницу.

2) Общедоступные логи с POST-параметрами
На 29–30 строке можно заметить, что логи посещений записываются в корневую директорию одного из виртуальных хостов. Более того, в логах «оседают» POST-параметры. Это может повлечь серьезные утечки пользовательских данных. Но! Этот недостаток можно эксплуатировать либо получив SSRF с выводом, либо доступ к файловой системе, так как хост, где будет хранится лог файл, локальный.

3) Потенциально общедоступный php-fpm
На строчке 48 можно увидеть, что FastCGI-сервер находится не на unix сокете, а на порту 9000. Можно предположить, что порт не локальный, а доступен снаружи. Если это так, то существует возможность исполнять произвольный PHP-код.

4) «Плохой» CSP
Для production.host установлен Content-Security-Policy, который позволяет исполнять Javascript, встроенный напрямую в страницу.

5) «Плохой» CORS
На строках 76–77 задается динамический CORS, который позволяет делать запросы к нашему хосту с любого другого, при этом браузер автоматически будет подставлять cookie в запрос.

6) Выше в ответе верно отмечено, что на 86 строке присутствует слабая проверка доступа в директорию. Просто установив определенный заголовок со значением secured позволит войти в директорию /managed.

7) Второй пункт ответа также частично корректный, но отвечающий не учел, что проверка зачастую находится именно на стороне приложения, а не самого веб-сервера. Но, тем не менее, стоит проверить, уязвимы ли роуты /user/{userid} к IDOR.

Задание было непростым, в нем есть достаточно много спорных моментов, и мы хотели посмотреть, как ребята справятся с этим.



В каких случаях пользователь Linux может читать домашние директории других пользователей?

Разбор задания
Оператор ~ (тильда) в Debian
C помощью этого оператора можно получить путь до домашней директории любого пользователя в системе (при условии, что пользователь прописан в файле /etc/passwd).
Например, посмотреть содержимое домашнего каталога пользователя ftp можно так, поставив перед ним тильду ~.

Пример:
* root@server:~# ls ~ftp
* welcome.msg
А теперь посмотреть содержимое этого файла:
* root@server:~# cat ~ftp/welcome.msg
* Welcome, archive user %U@%R!
Ну и то, к чему мы стремились: посмотреть путь к домашней директории пользователя:
* root@amorale:~# echo ~ftp
* /srv/ftp


Комментарий эксперта K:
Этот вопрос довольно простой, и критерием оценки на него было несколько пунктов:
  • Описание устройства прав в файловой системе
  • Упоминание ACL и описание принципов их работы
  • Упоминание дополнительных свойств
  • Какая стоит по умолчанию маска
  • Упоминание capabilities

Самым частым ответом, который не может быть оценен высоко, является фраза вида:
«Можно читать, когда пользователь root» и её вариации.

Вопрос сводится к простому пониманию того, как устроены права в Linux/Unix.
Для начала надо оговориться, что мы имеем в виду под словосочетанием «прочитать директорию» — в данном случае нас интересует только получение списка файлов внутри директории.
Чтобы наглядно представить, о чем будет идти речь, возьмем некоторый файл funky_test.txt и посмотрим на его права

-rwxrw-r-x  1 alice interns   12 июл  4 13:00 funky_test.txt

Известно, что права в Linux/Unix выражаются тремя группами:
  • права пользователя-владельца — в данном случае «rwx» для alice
  • права группы — в данном случае «rw» для группы interns
  • права всех остальных — в данном случае «r-x» для others

Для каждой из группы возможна любая комбинация из прав read, write, execute.

Соответственно, кажется логичным следующий факт — чтобы у пользователя была возможность читать папку, необходимо выполнение одного из следующих условий:

  • Пользователь является владельцем файла, и для владельца есть право read
  • Пользователь принадлежит группе файла, и для группы есть право read
  • Для остальных есть право read

Следует заметить, что если наличие одного только права read на папку дает возможность только посмотреть список имен содержащихся внутри нее файлов. Узнать их размер или права нельзя, для этого необходимо обладать правом execute для папки.

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

Подобный ответ приходит в голову сразу и является самым простым, однако, он совсем не исчерпывающий. Все дело в двух критических вещах:

1. Как на самом деле ядро ОС смотрит и применяет права, которые мы видим с помощью команды ls.

2. Возможность наличия списков контроля доступа — POSIX Access Control Lists.

Уточнения работы ОС c правами на файл.


Пример 1
Предположим, вы пользователь alice и вы принадлежите группе interns. Ниже представлены права на файл funny_test.txt и попытка его прочитать:
$ whoami
alice
$ id
uid=1001(alice) gid=1001(alice) groups=1001(alice),1002(interns)
$ ls -la
----rwx---  1 alice interns   12 июл  4 13:00 funky_test.txt
$ cat funky_test.txt
cat: funky_test.txt: Permission denied
$ 

Пример 2
Следующий пример — меняем права funky_test.txt на 604. Заходим под пользователем bob, который принадлежит группе interns и пытаемся прочитать файл:
$ whoami
bob
$ id
uid=1002(bob) gid=1003(bob) groups=1003(bob),1002(interns)
$ ls -la funky_test.txt
-rw----r--  1 alice interns   12 июл  4 13:00 funky_test.txt
$ cat funky_test.txt
cat: funky_test.txt: Permission denied

Замечания
В первом примере alice владелец файла и потому может поменять права, как хочет. Таким образом, permission_denied для нее не ограничение:
$ id               
uid=1001(alice) gid=1001(alice) groups=1001(alice),1002(interns)
$ ls -la
----rwx---  1 alice interns   12 июл  4 13:00 funky_test.txt
$ chmod 777 funky_test.txt
$ ls -la funky_test.txt
-rwxrwxrwx 1 alice interns 12 июл  4 13:00 funky_test.txt
$ cat funky_test.txt
secret_pass

А вот во втором примере bob сделать ничего не может.Почему так
Все дело в том, что ядро берет только один набор прав который наиболее «подходит для пользователя», а именно:
  • Если ID владельца файла совпадает с вашим effective UID — тогда используются права для владельца
  • Если GID группы файла совпадает с одним из ваших effective GID — тогда используются права для группы
  • В остальных случая используются права others.

Дополненный ответ
Таким образом, дополненный ответ бы содержал оговорку — в силу того, что ОС не будет искать самые «сильные» права для текущего пользователя, а вместо этого пойдет по описанному выше алгоритму, то необходимо учитывать сценарий, когда:
  • пользователь владелец без прав, но принадлежит группе, у которой есть права на чтение или же для others есть права на чтение
  • пользователь не владелец, но принадлежит группе без прав, однако для others существуют права на чтение

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

POSIX Access Control Lists


Еще одно возможное дополнение ответа — это когда выставлены списки контроля доступа для конкретного файла/директории. При просмотре прав, можно увидеть что выполняются ACL, благодаря тому, в конец списка прав добавляется знак »+»

Не вдаваясь в подробности работы POSIX ACLs, можно сказать следующее — их главная возможность в том, что мы можем задавать отдельные права для пользователей и групп на файл. То есть когда файл с ACL, то для него могут действовать права нескольких групп.

Пример
Как это работает. Вернемся к нашему изначальному примеру с пользователем alice и файлом funky_test.txt с правами, представленными ниже
-rwxrw-r-x 1 alice interns 12 июл  4 13:00 funky_test.txt

Для данного файла не установлены ACL. Ко

© Habrahabr.ru