уязвимости в исходном коде
Поиск уязвимостей по исходному коду? Легко!
Многие программисты мучаются во время сна — им снится, что их проект был взломан, а исходники попали в открытый доступ.
Бывало такое? Нет? Как бы не так!
Сейчас я расскажу об очень простом методе поиска уязвимостей по исходному коду.
Да, именно по исходному коду, а не через GET/POST запросы с использованием различных программ.
Интересно — читайте дальше, а если не интересно — есть куда других интересных постов.
Введение
Для начала хотелось бы ввести вас в курс дела — поведать об задумке в целом и прочих мыслях.
Что же вы предлагаете?
Я предлагаю поиск узявимостей в PHP-сценариях с помощью специального PHP-сценария.
Почему именно такой подход?
Такой подход был выбран по причине того, что данный подход даст нам удобство в поиске уязвимости — возможность запуска на сервере с работающим сайтом.
Какие же гарантии по нахождению уязвимости?
Как и многие специалисты в области поиска уязвимостей, я не даю 100 % гарантию на то, что все уязвимости будут найдены с помощью сего скрипта.
Но большинство, уж поверьте, обнаружить удастся.
Подготовимся к написанию?
Анализ самых распостранённых уязвимостей
Как же можно искать уязвимости?
Вспомните как вы в спешке, очень в спешке, писали код. Часто ли вы фильтровали переменные?
Уверен, что 60% вспомнят себя. Поэтому продумаем список возможных кодовых уязвимостей.
Список уязвимостей
Итог подготовки
Пишем скрипт!
Я предоставлю вам уже готовый скрипт, но не без комментариев.
Надеюсь, что вам будет понятен мой код.
# Запуск фунции для просмотра каталогов для нашей папки.
open_dir($dir);
Безопасность веб-приложений: от уязвимостей до мониторинга
Уязвимости веб-приложений возникают тогда, когда разработчики добавляют небезопасный код в веб-приложение. Это может происходить как на этапе разработки, так и на этапе доработки или исправления найденных ранее уязвимостей. Недостатки часто классифицируются по степени критичности и их распространенности. Объективной и наиболее популярной классификацией уязвимостей считается OWASP Top 10. Рейтинг составляется специалистами OWASP Project и актуализируется каждые 3-4 года. Текущий релиз выпущен в 2017 году, а следующий ожидается в 2020-2021.
Распространенные уязвимости
Для начала рассмотрим типовые уязвимости, которым подвержены многие веб-приложения.
Инъекции
Как и полагается, атаки класса «Инъекции» занимают лидирующую строчку рейтинга OWASP Top 10, встречаясь практически повсеместно и являясь крайне разнообразными в реализации. Уязвимости подобного класса начинаются SQL-инъекциями, в различных его вариациях, и заканчивая RCE — удаленным выполнением кода.
Межсайтовый скриптинг — уязвимость, встречающаяся на данный момент куда реже, чем раньше, если верить рейтингу OWASP Top 10, но несмотря на это не стала менее опасной для веб-приложений и пользователей. Особенно для пользователей, ведь атака XSS нацелена именно на них. В общем случае злоумышленник внедряет скрипт в веб-приложение, который срабатывает для каждого пользователя, посетившего вредоносную страницу.
LFI/RFI
Уязвимости данного класса позволяют злоумышленникам через браузер включать локальные и удаленные файлы на сервере в ответ от веб-приложения. Эта брешь присутствует там, где отсутствует корректная обработка входных данных, которой может манипулировать злоумышленник, инжектировать символы типа path traversal и включать другие файлы с веб-сервера.
Атаки через JSON и XML
Веб-приложения и API, обрабатывающие запросы в формате JSON или XML, также подвержены атакам, поскольку такие форматы имеют свои недостатки.
JSON (JavaScript Object Notation) — это облегченный формат обмена данными, используемый для связи между приложениями. Он похож на XML, но проще и лучше подходит для обработки с помощью JavaScript. Многие веб-приложения используют этот формат для обмена данными между собой и сериализации/десериализации данных. Некоторые веб-приложения также используют JSON для хранения важной информации, например, данных пользователя. Обычно используется в RESTful API и приложениях AJAX.
JSON чаще всего ассоциируется с API, тем не менее, часто используется даже в обычных и хорошо известных веб-приложениях. Например, редактирование материалов в WordPress производится именно через отправку запросов в формате JSON:
JSON Injection
Простая инъекция JSON на стороне сервера может быть выполнена в PHP следующим образом:
Простая инъекция JSON на стороне клиента может быть выполнена следующим образом:
JSON Hijacking
Захват JSON — атака, в некотором смысле похожая на подделку межсайтовых запросов (CSRF), при которой злоумышленник старается перехватить данные JSON, отправленные веб-приложению с веб-сервера:
XML External Entity
Атака внешней сущности XML (XXE) — это тип атаки, в котором используется широко доступная, но редко используемая функция синтаксических анализаторов XML. Используя XXE, злоумышленник может вызвать отказ в обслуживании (DoS), а также получить доступ к локальному и удаленному контенту и службам. XXE может использоваться для выполнения подделки запросов на стороне сервера (SSRF), заставляя веб-приложение выполнять запросы к другим приложениям. В некоторых случаях c помощью XXE может даже выполнить сканирование портов и удаленное выполнение кода.
XML (Extensible Markup Language) — очень популярный формат данных. Он используется во всем: от веб-сервисов (XML-RPC, SOAP, REST) до документов (XML, HTML, DOCX) и файлов изображений (данные SVG, EXIF). Для интерпретации данных XML приложению требуется анализатор XML, известный как XML-процессор. XML можно использовать не только для объявления элементов, атрибутов и текста. XML-документы могут быть определенного типа. Тип указывается в самом документе, объявляя определение типа. Анализатор XML проверяет, соответствует ли XML-документ указанному типу, прежде чем обрабатывать документ. Вы можете использовать два варианта определений типов: определение схемы XML (XSD) или определение типа документа (DTD). Уязвимости XXE встречаются в последнем варианте. Хотя DTD можно считать устаревшими, но он все еще широко используются.
Фактически, объекты XML могут поступать практически откуда угодно, включая внешние источники (отсюда и название XML External Entity). При этом, XXE может стать разновидностью атаки подделки запросов на стороне сервера (SSRF). Злоумышленник может создать запрос, используя URI (известный в XML как системный идентификатор). Если синтаксический анализатор XML настроен для обработки внешних сущностей, а по умолчанию многие популярные анализаторы XML на это настроены, веб-сервер вернет содержимое файла в системе, потенциально содержащего конфиденциальные данные.
Злоумышленник, разумеется, не ограничивается системными файлами. Можно легко заполучить и другие локальные файлы, включая исходный код, если известно расположение файлов на сервере или структура веб-приложения. Атаки на внешние объекты XML могут позволить злоумышленнику выполнять HTTP-запросы к файлам в локальной сети т.е. доступным только из-за брандмауэра.
Как использовать простую утилиту для поиска уязвимостей в программном коде
Graudit поддерживает множество языков программирования и позволяет интегрировать тестирование безопасности кодовой базы непосредственно в процесс разработки.
Источник: Unsplash (Markus Spiske)
Тестирование — важная часть жизненного цикла разработки программного обеспечения. Существует очень много видов тестирования, каждый из них решает свою задачу. Сегодня я хочу поговорить о поиске проблем безопасности в коде.
Очевидно, что в современных реалиях разработки программного обеспечения важно обеспечить безопасность процессов. В своё время был даже введён специальный термин DevSecOps. Под этим термином понимают ряд процедур, направленных на выявление и устранение уязвимостей в приложении. Существуют специализированные open source решения для проверки уязвимостей в соответствии со стандартами OWASP, которые описывают различные типы и поведение уязвимостей в исходном коде.
Существуют разные подходы к решению проблем безопасности, например, статическое тестирование безопасности приложений (SAST), динамическое тестирование безопасности приложений (DAST), интерактивное тестирование безопасности приложений (IAST), анализ компонентов программного обеспечения (Software Composition Analysis) и так далее.
Статическое тестирование безопасности приложений выявляет ошибки в уже написанном коде. Этот подход не требует запуска приложения, поэтому он называется статическим анализом.
Я остановлюсь на статическом анализе кода и воспользуюсь простым open source инструментом, чтобы продемонстрировать всё на практике.
Почему я выбрал open source инструмент для статического анализа безопасности кода
На то есть ряд причин: во-первых, это бесплатно, так как вы используете инструмент, разработанный сообществом единомышленников, которые хотят помочь другим разработчикам. Если у вас небольшая команда или стартап, у вас есть отличная возможность сэкономить, используя программное обеспечение с открытым исходным кодом для проверки безопасности своей кодовой базы. Во-вторых, это избавляет вас от необходимости нанимать отдельную команду DevSecOps, что ещё больше снижает ваши расходы.
Хорошие open source инструменты всегда создают с учётом повышенных требований к гибкости. Поэтому их можно использовать практически в любом окружении, охватывая широкий круг задач. Разработчикам намного проще подружить такие инструменты с системой, которую они уже построили, работая над своими проектами.
Но могут возникнуть ситуации, когда вам понадобится функция, которой нет в выбранном вами инструменте. В этом случае у вас есть возможность форкнуть его код и разработать на его основе свой собственный инструмент с необходимой вам функциональностью.
Поскольку в большинстве случаев на разработку программного обеспечения с открытым исходным кодом активно влияет сообщество, решение о внесении изменений принимают достаточно быстро и по делу: разработчики open source проекта опираются на отзывы и предложения пользователей, на их сообщения о найденных ошибках и других проблемах.
Использование Graudit для анализа безопасности кода
Для статического анализа кода можно использовать разные инструменты с открытым исходным кодом, не существует универсального инструмента для всех языков программирования. Разработчики некоторых из них следуют рекомендациям OWASP и стараются охватить как можно больше языков.
Здесь мы будем использовать Graudit, простую утилиту для командной строки, которая позволит нам найти уязвимости в нашей кодовой базе. Он поддерживает разные языки, но всё-таки их набор ограничен. Graudit разработан на основе служебной утилиты grep, которая в своё время вышла под лицензией GNU.
Существуют похожие инструменты для статического анализа кода — Rough Auditing Tool for Security (RATS), Securitycompass Web Application Analysis Tool (SWAAT), flawfinder и так далее. Но Graudit очень гибок и имеет минимальные технические требования. Тем не менее, у вас могут появиться задачи, которые Graudit решить не в состоянии. Тогда можно поискать другие варианты вот в этом списке.
Мы можем интегрировать этот инструмент в конкретный проект, или сделать его доступным для выбранного пользователя, либо — использовать его одновременно во всех наших проектах. В этом тоже проявляется гибкость Graudit. Итак, давайте сначала клонируем репо:
Теперь давайте создадим для Graudit символическую ссылку, чтобы использовать его в формате команды
Проверим, успешно ли прошла установка:
Если вы увидите что-то похожее, то, значит, всё хорошо.
Я буду тестировать один из уже существующих моих проектов. Перед запуском инструмента ему нужно передать базу данных, соответствующую языку, на котором написан мой проект. Базы данных находятся в папке
Итак, я протестировал два js-файла из моего проекта, и Graudit вывел в консоль информацию об уязвимостях в моём коде:
Можете попробовать таким же образом протестировать ваши проекты. Список баз данных для разных языков программирования можно посмотреть здесь.
Преимущества и недостатки Graudit
Graudit поддерживает множество языков программирования. Поэтому он подходит для широкого круга пользователей. Он может достойно конкурировать с любыми бесплатными или платными аналогами. И очень важно, что в проект по-прежнему вносят доработки, а сообщество не только помогает разработчикам, но и другим пользователям, которые пытаются разобраться с инструментом.
Это удобный инструмент, но пока он не всегда может точно указать, в чём именно заключается проблема, связанная с подозрительным участком кода. Разработчики продолжают дорабатывать Graudit.
Но в любом случае полезно обращать внимание на потенциальные проблемы безопасности в коде, используя подобные инструменты.
Начало.
В этой статье я рассмотрел только один из многих способов поиска уязвимостей — статическое тестирование безопасности приложений. Провести статический анализ кода легко, но это только начало. Чтобы больше узнать о безопасности вашей кодовой базы, нужно интегрировать в жизненный цикл разработки ПО другие виды тестирования.
На правах рекламы
Надёжный VPS и правильный выбор тарифного плана позволят меньше отвлекаться от разработки на неприятные проблемы — всё будет работать без сбоев и с очень высоким uptime!
Контроль уязвимостей в программных приложениях
Дефекты программного кода
Задача высококлассного менеджера состоит в умении не только подбирать команду, но и укладываться в бюджеты. Зачастую они не позволяют нанимать специалистов с безупречной квалификацией. В этой ситуации необходимо создавать такие условия работы и процессы ее выполнения, которые даже при среднем уровне компетенций исполнителей позволяли бы получать результаты, превышающие аналогичные показатели по рынку. Тем самым достигаются конкурентные преимущества.
Какие дефекты присутствуют в ПО и все ли они одинаковы? На этот вопрос можно отвечать по-разному, строя различные теории их классификации. Здесь мы приведем разделение дефектов программного обеспечения на классы с точки зрения различий в управлении ими в процессе повышения качества ПО в соответствии с требованиями информационной безопасности.
Самый распространенный дефект – это ошибки программистов при разработке кода. Зачастую причиной их появления является дефицит времени или потеря внимания во время работы. Например, программист разрабатывает код, который в определенных условиях должен выполнять одни действия, а во всех остальных случаях – другие. Программист уделяет большое внимание разработке кода, который будет выполняться в 90% случаях исполнения ПО. Когда же дело доходит до обработки альтернативы, он устает, его внимание рассеивается, и какие-то важные аспекты, такие как оператор, определяющий выполнение данного фрагмента кода, только если условие выполнения основного фрагмента не выполнилось, теряются.
Другая характерная причина появления ошибок в программном коде – внесение в него изменений. Разработчик меняет один кусок кода, который может влиять на функциональность другого фрагмента программы. Тогда та функциональность, трансформация которой не предполагалась, становится измененной.
Обычно такие ошибки обнаруживаются на этапе тестирования либо самими разработчиками, либо специальной группой тестировщиков. Для обнаружения таких ошибок существуют различные теории и успешные практики разработки наборов тестов по техническому заданию, регрессионные тесты и другие методы, позволяющие написать качественный набор исходных данных, чтобы проверить больший процент возможных сценариев выполнения программы.
Другие дефекты, которые в большей степени интересуют специалистов по информационной безопасности, нежели разработчиков, – это уязвимости. Уязвимость – ошибка разработчика, которая потенциально может эксплуатироваться злоумышленниками с целью получения несанкционированного доступа к управлению программным приложением. Уязвимость – это код, который выполняет правильные действия с точки зрения требуемого функционала, но его исполнение имеет побочный эффект, о наличии которого программист зачастую может не знать. Наличие таких фрагментов кода не является следствием усталости, невнимательности или отсутствия достаточного времени на тестирование у разработчика, как в случае ошибки. Нередко причиной появления уязвимостей является незнание программистов о наличии побочных возможностей тех языковых конструкций, которые они используют для реализации задуманного функционала.
Уязвимости выявляют эксперты в области анализа кода, знающие о наличии побочных эффектов у тех или иных языковых конструкций. Также многие уязвимости можно обнаруживать в результате тестирования ПО по требованиям информационной безопасности специальными тестами на проникновение. Однако более эффективный метод их обнаружения – это полуавтоматический статический анализ кода, который выполняется экспертами с применением специальных инструментальных средств.
Самые неприятные с точки зрения возможности обнаружения дефекты – недекларированные возможности ПО (НДВ). Недекларированные возможности – это правильный код с точки зрения и функциональности, и информационной безопасности, поэтому его трудно обнаружить автоматическими методами. Однако этот код реализует функциональность, которая не была задумана заказчиком – ее для своих целей привнес разработчик. Обычно НДВ разделяют на закладки и секретный вход (back door).
Закладка – это функциональность, которая выполняется при наступлении определенных условий и выполняет действия, задуманные разработчиком. Часто закладки используются для того чтобы неявно манипулировать программным обеспечением. Один из наиболее известных случаев наличия закладки – история разработчика City Bank. Программист не знал, что делать с разницей, возникающей при округлении результатов арифметических операций при начислении процентов на вклады клиентов, и не придумал ничего лучше, чем накапливать ее на своем персональном счете.
Секретный вход – это код, позволяющий программисту получать контроль над ПО в обход правил, указанных в техническом задании. Наиболее часто секретными входами наполняют программное обеспечение, которое разрабатывается на заказ, для того, чтобы можно было выполнять удаленную диагностику ошибок при эксплуатации программного приложения заказчиком.
Обнаружить недекларированные возможности полностью в автоматическом режиме нельзя, так как такой код является правильным. Подобные дефекты эксперты в области информационной безопасности находят посредством ручного анализа кода или с помощью программных инструментов, позволяющих обнаруживать в исходном коде шаблоны языковых конструкций, характерных для построения НДВ.
Откуда берутся дефекты в программном коде?
Ошибки и уязвимости в программном коде обычно появляются не только вследствие того, что технологии меняются, а разработчики не успевают к ним адаптироваться, но также по причине неправильного построения процесса разработки ПО.
Зачастую требования к программному обеспечению меняются быстрее, чем ИТ-команда успевает их реализовывать. Дается одно техническое задание, оно прорабатывается архитектором, конструкторами и передается в работу. Но в процессе заказчик разработки понимает: новые условия рынка требуют, чтобы разрабатываемое ПО выполняло другой функционал. Несмотря на возражения ИТ-команды, вносятся изменения в проектную документацию, а зачастую и непосредственно в код, ломая при этом проработанную архитектуру.
Другой причиной появления ошибок и уязвимостей является сложность технологий, использующихся в современной ИТ-индустрии.
Разработчики вынуждены использовать технологии, которые сами по себе могут содержать ошибки и уязвимости, а также способствовать появлению новых в результате их неправильного внедрения в разрабатываемое ПО. Современные программные продукты многоязычные, кроссплатформенные, связи между компонентами, из которых они состоят, настолько обширны, что программист просто не в состоянии удерживать все особенности в поле своего внимания. Помимо этого, поскольку программные системы разрабатываются командой специалистов, ошибки и уязвимости часто прячутся на стыке компонент, за которые отвечают разные люди.
Появление в коде недекларированных возможностей носит исключительно личностный характер и с трудом контролируется посредством внедрения современных технологий разработки ПО. Хотя практика перекрестного контроля разработки (прежде чем код попадает в основную ветку разработки, его обязательно проверяет другой программист) и другие организационные меры имеют определенный успех. Обнаружить недекларированные возможности в коде, который разрабатывался на заказ и куда НДВ были внедрены специально, можно только посредством его анализа.
Можно ли контролировать наличие дефектов в программном коде?
На сегодняшний день на рынке представлено несколько инструментальных систем анализа кода, как статического (по исходному коду методом «белого ящика»), так и динамического (без исходного кода методом «черного ящика»). Помимо этого, ведущие инструментальные системы анализа кода от таких производителей, как HP и IBM, предлагают комбинированный статический и динамический анализ, который позволяет отображать результаты динамического анализа на исходный код. Можно сказать, что в настоящее время наиболее эффективным инструментальным средством анализа кода, которое предлагает статический, динамический, а также гибридный анализ в сочетании с удобным интерфейсом и хорошей библиотекой правил поиска уязвимостей, является инструментальное средство HP Fortify.
Если программное обеспечение разрабатывается на заказ, то при приемке оно обязательно должно подвергаться проверке на наличие дефектов. Это может сделать внутренняя команда по контролю качества программных продуктов в части функциональности и требований информационной безопасности. Проверка также может быть сторонней, что подразумевает привлечение независимых экспертов.
Контролировать уязвимости в программном обеспечении, которое поставляется на заказ, сложно, так как информация о наличии дефектов проходит долгий путь проверок, а затем следует не менее длительный процесс их устранения. Однако это не значит, что такое ПО не нужно проверять и стоит эксплуатировать как «кота в мешке». Рекомендуется выполнять контроль уязвимостей посредством правильной настройки защиты периметра эксплуатации.
Роковые ошибки. Как искать логические уязвимости в веб-приложениях
Содержание статьи
Эта статья — конспект вебинара по веб‑уязвимостям, который я проводил для читателей «Хакера». В конце будет приведена его запись, где ты сможешь увидеть то, что не попало в текстовую версию. Если тебе интересны такие темы и ты бы хотел разобраться в них глубже, записывайся на мой курс по безопасности веб‑приложений!
Сразу предупрежу, что большинство задач, которые мы сегодня разберем, будут на языке PHP. Оно неспроста — подавляющее большинство сайтов и сервисов в интернете написаны именно на нем. Так что, несмотря на подпорченную репутацию этого языка, тебе придется разбираться в нем, чтобы хакерствовать серьезно. Сейчас же, в рамках этого занятия, знание PHP не является необходимостью, но, конечно, будет очень серьезным подспорьем.
Впрочем, большинство уязвимостей не привязаны к конкретному языку или стеку технологий, так что, узнав их на примере PHP, ты легко сможешь эксплуатировать подобные баги и в ASP.NET, и в каком‑нибудь Node.JS.
А еще предупрежу, что задачки, которые мы сегодня разберем, не совсем начального уровня и совсем уж «валенкам» тут делать нечего — сначала стоит почитать матчасть и хоть немного представлять, с чем хочешь иметь дело. Если же ты можешь отличить HTTP от XML и у тебя не возникает вопросов вида «а что за доллары в коде?», то добро пожаловать!
warning
Ни автор курса, ни редакция «Хакера» не несут ответственности за твои действия. Применение материалов этой статьи против любой системы без разрешения ее владельца преследуется по закону.
Сегодня мы разберем несколько задач, которые я решал сам в рамках тренировки. Возможно, они покажутся тебе сложными, но не пугайся — всегда есть возможность отточить свои навыки на сайтах правительств специализированных сайтах для хакеров. Я сейчас говорю о HackTheBox и Root-me, которыми пользуюсь сам и всячески советую другим. Две из сегодняшних задач взяты именно оттуда.
Задача 1
Сначала я приведу код, с которым мы сейчас будем работать.
По сути, тут всего три строки кода. Казалось бы, где тут может закрасться уязвимость?
Чтобы это понять, давай разберем алгоритм, который здесь реализован. Вообще, при аудите кода стоит уметь читать его построчно. Тогда проще понять, что именно может пойти не так.
В конце очищенное имя файла подставляется в путь и загружается файл с этим именем. Ничего плохого.
Итак, что может пойти не по плану?
Как ты уже, конечно, догадался — проблема в функции очистки ввода (которая preg_replace ). Давай обратимся к первой попавшейся шпаргалке по регулярным выражениям.
Шпаргалка
Тут прямо написан ответ, как обойти защиту (подсказка: ищи справа).
Видишь точку? А шапочку ( ^ )? Та строка читается как «если в начале строки находится любое количество любых символов, кроме переноса строки, и это заканчивается слешем, удалить соответствующую часть строки».
Ключевое тут «кроме переноса строки». Если в начале строки будет перенос строки — регулярка не отработает и введенная строка попадет в include( ) без фильтрации.
Результат
Задача 2
Это задачка с root-me, где ты, возможно, уже видел ее. Но мы все равно рассмотрим ее подробнее — она относится к реалистичным, и шансы встретить что‑то подобное в жизни немаленькие.
В задании нам дается простой файлообменник и просят получить доступ к панели админа.
Интерфейс файлообменника
Интерфейс крайне прост: есть кнопка загрузки файла на сервер и просмотр загруженных файлов по прямым ссылкам. Забегая вперед, скажу, что грузить скрипты на PHP, bash и прочие — бесполезно, проверки реализованы верно и ошибка в другом месте.
Обрати внимание на нижнюю часть страницы, а точнее — на фразу «frequent backups: this opensource script is launched every 5 minutes for saving your files». И приведена ссылка на скрипт, вызываемый каждые пять минут в системе.
Давай глянем на него пристальнее:
Казалось бы — что тут такого? На параметры ты влиять не можешь, а мантру призыва tar вообще знаешь как свои пять пальцев. А проблема в самой мантре: тут она написана не полностью. Точнее, не в том виде, как ее увидит сам tar.
Что делает звездочка? Вместо нее bash подставит имена всех файлов в текущей папке. Вроде ничего криминального.
А давай обратимся к мануалу на Tar, который нам любезно предоставлен вместе с условием задачи.
Интересности в Tar
Теперь вспомним про звездочку: вместо нее шелл (bash) подставит список всех файлов в текущей папке, при этом они могут иметь любые имена. В том числе такие, которые будут восприняты архиватором как специальные параметры.
Просто заголовок и команда копирования админской панели в текущую папку. Естественно, тут мог быть реверс‑шелл или еще что‑то, но для решения конкретно этой задачи такая «тяжелая артиллерия» не нужна.
Теперь дожидаемся выполнения нашего шелла — и увидим в окне файлообменника файл админ‑панели в виде простого текста. Осталось только открыть его и найти там пароль!
Пароль в чистом виде
Задача 3
Тут у нас плагин для WordPress, который позволяет запись аудио и видео.
Я не буду просить тебя найти уязвимость, а сразу покажу ее.
Уязвимое место
Как видно из строк 247–251 на скриншоте, не предусмотрено никаких проверок на тип или содержимое файла — это просто классическая загрузка!
Есть, правда, ограничение: файл грузится в стандартную директорию WordPress ( / wordpress/ wp-content/ uploads/< YEAR>/ < MONTH>). Это значит, что листинг содержимого нам по умолчанию недоступен. А в строке 247 генерируется случайный идентификатор, который подставляется в начало имени файла, то есть обратиться к / wordpress/ wp-content/ uploads/ 2021/ 01/ shell. php уже не выйдет. Непорядок!
Получает уникальный идентификатор с префиксом, основанный на текущем времени в микросекундах.
Внимание. Эта функция не гарантирует получения уникального значения. Большинство операционных систем синхронизирует время с NTP либо его аналогами, так что системное время постоянно меняется. Следовательно, возможна ситуация, когда эта функция вернет неуникальный идентификатор для процесса/потока.
Так как PHP — проект открытый, мы можем подсмотреть исходники функций стандартной библиотеки. Открываем исходник uniqid( ) на GitHub, переходим к строке 76 и наблюдаем следующее:
Что тут происходит? А то, что возвращаемое значение зависит исключительно от текущего времени, которое в рамках одной планеты вполне предсказуемо.
Хоть выходная последовательность и выглядит случайной, она таковой не является. Чтобы не быть голословным, вот пример имени файла, сгенерированного таким алгоритмом:
Полученное значение легко можно конвертировать обратно в дату и время его генерации:
Конечно, брутить все 13 символов — вши заедят, но у нас есть способ получше: мы можем пробрутить варианты на основе времени загрузки плюс‑минус полсекунды, чтобы нивелировать разбежки часов на клиенте и сервере. А можно просто поверить, что часы у обоих хостов точные, а значит, можно проверить не миллион вариантов (1 секунду), а только варианты, возможные между временем отправки запроса и временем получения ответа. На шустром канале это будет порядка 300–700 мс, что не так и много.
Конечно, не все реальные кейсы требуют глубоких познаний в PHP или другом серверном языке. Многие ошибки можно найти, даже не открывая код — с помощью автоматических сканеров. Подробнее о них — в нашей статье об автоматическом взломе. Они здорово помогают, так что не грех иметь парочку под рукой для экспресс‑анализа!
Я набросал простой скрипт на Python для демонстрации такой возможности. Его код представлен ниже:
Нам нужно запустить его несколько раз, чтобы подобрать минимальное время между отправкой запроса и получением ответа — это позволит уменьшить время перебора.
Также нужно помнить, что разбежки все же могут быть, и чисто на всякий случай стоит проверить, насколько локальное время соответствует времени на сервере. Частенько оно возвращается сервером в заголовке Last-Modified и позволяет понять, какую величину коррекции внести в свои расчеты.
Как бы еще оптимизировать перебор?
Ну, во‑первых, питон сам по себе очень медленный и, конечно, не смог бы выполнить соединение, передачу заголовков, отправку файла и прочие мелкие накладные расходы в тот же момент. А интерпретатор PHP на стороне сервера едва ли моментально проверит права, запустит скрипт, отработает служебные функции и дойдет до собственно уязвимого места. Тут можно накинуть эдак тысяч сто микросекунд без малейших потерь.
Во‑вторых, выполнение uniqid( ) очевидно происходит не в самом конце функции. Еще нужно время на обработку загруженного файла, запись ответа (заголовков), отправку этого всего по сети и на обработку ответа интерпретатором Python. Тут тоже можно порядка 100 000 микросекунд вычесть.
Вот так на ровном месте мы сократили перебор на 200 000 запросов. Много это или мало? В моем случае это сократило количество запросов еще примерно на треть.
Осталось порядка 500 000 вариантов, которые можно перебрать в пределах часа или даже меньше — у меня это заняло минут 15.
Теперь давай напишем еще один скрипт, который и будет искать наш шелл с использованием этого алгоритма:
Вот и всё: запускаешь, через некоторое время получаешь путь, и хост захвачен!
Наверняка у тебя возник вопрос, нельзя ли как‑то еще усовершенствовать этот перебор, потому что 500 тысяч вариантов — это все равно как‑то многовато? Можно, но такого значимого ускорения, как раньше, уже не будет. Суть в том, что можно идти не от начала промежутка времени к концу, а от середины к краям. По опыту, это работает несколько быстрее.
Другой способ
Задача 4
Последняя на сегодня задачка — тоже с root-me и тоже из категории реалистичных, но заметно посложнее. Сервис Web TV — новейшая французская разработка в сфере интернет‑телевидения. Но нас интересует не новая дешевая трагедия, а админка.
Главная страница Web TV. Простите за мой французский
Только — вот незадача — Gobuster никаких признаков админки не обнаружил. Придется изучать, что нам доступно. А доступен логин (там форма авторизации) и ссылка на неработающий эфир.
Попробуем залогиниться и перехватить запрос на авторизацию с помощью Burp.
Буква З в слове «реальность» означает «защищенность»
Запрос отправляем в Repeater (повторитель). Пусть пока там полежит.
Взглянем еще разок на форму логина. Какие мысли тебя посещают, когда ты видишь форму для авторизации? Конечно, SQL-инъекция! А давай ткнем туда кавычку. Написали. Отправляем. Хм, ничего не поменялось. А как вообще узнать, что что‑то поменялось? Смотри на заголовок Content-Length в ответе: в нашем случае там приходит ровно 2079 байт, если инъекции не было, и, очевидно, придет сильно другой результат в противном случае. Я попробовал еще немного, и инъекция так просто не выявилась, так что давай поищем в другом месте, а потом вернемся к этому запросу.
Я попробовал перейти на страницу / page_index и получил ошибку как на скрине ниже.
Ошибка интерпретатора
/?action=../../index.php
Видно не все, но если открыть ответ в Burp или даже просто просмотреть код страницы браузером — открывается полный исходник. Вот тебе и directory traversal налицо.
Результат обхода каталога
Помнишь, мы не могли найти путь к админке? А на скриншоте он есть: именно на него будет редирект, когда скрипт проверит логин и пароль.
Давай, не отходя от кассы, сразу и его прочитаем — вдруг там что‑нибудь интересное есть.