• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья REcollapse

Azrv3l

win32kfull
Эксперт
Регистрация
30.03.2019
Сообщения
215
Реакции
539
Добро пожаловать в мой блог. В этом посте я объясню технику REcollapse. Я исследовал её последние пару лет. Занимаясь Bug Bounty и участвуя в HackerOne LHE, я обнаружил до странности простые, но важные уязвимости в защищенных целях,. Этот метод можно использовать для захвата аккаунтов, обнаружения новых способов обхода брандмауэров веб-приложений и многого другого.

Этот пост в основан на моем выступлении на BSidesLisbon 2022 и следует за запуском инструмента recollapse, который теперь доступен на GitHub. Это также то, что мы начали исследовать внутри компании Ethiack.

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

Вот несколько примеров проверки и очистки:
Python:
>>> re.match(r"^\S+@\S+\.\S+$", "aa.com")
>>> re.match(r"^\S+@\S+\.\S+$", "a@a.com")
<re.Match object; span=(0, 7), match='a@a.com'>
PHP:
> htmlspecialchars("input'\"><script>alert(1);</script>");
= "input&#039;&quot;&gt;&lt;script&gt;alert(1);&lt;/script&gt;"

Цель всегда состоит в том, чтобы в первую очередь предотвратить сохранение опасного пользовательского ввода. Давайте рассмотрим приложение, которое отклоняет специальные символы в поле name на конечной точке /signup. Злоумышленник не может внедрить полезную нагрузку в name, но это не обязательно означает, что впоследствии имя не будет где-то очищено, что приведет к уязвимостям, таким как XSS. В этом случае мы можем попытаться найти альтернативные конечные точки, которые являются более разрешительными и допускают использование специальных символов в одном и том же параметре. Это то, что я сделал с @itscachemoney еще в 2019 году в Dropbox, или… мы можем попытаться найти обход регулярного выражения с помощью метода черного ящика, как я покажу позже в этом посте.

С другой стороны, нормализация используется для обеспечения согласованности пользовательского ввода. Это удобно для приложений с несколькими потоками учетных записей, чтобы избежать дублирования адресов электронной почты, таких как a@a.com, A@a.COM, á@ª.com и т. д. Библиотеки нормализации имеют разные выходные данные, как вы можете видеть в этих примерах, которые могут быть полезны для обнаружения технологий, используемых серверной частью.
Python:
> iconv("UTF-8", "ASCII//TRANSLIT", "Ãéï°úç");
= "~A'e\"i^0'uc"
PHP:
>>> unidecode.unidecode("Ãéï°úç")
'Aeideguc'

Вы можете найти дополнительную информацию о нормализации, если вы не знакомы с ней, здесь: https://🅂𝖍𝐤ₛᵖ𝒓.ⓜ𝕠𝒃𝓲/🆆🆃🅵/. Однако нормализующее поведение браузера — это лишь верхушка айсберга.

В чём проблема?
Регулярные выражения обычно повторно используются из StackOverflow, Github или других источников. Разработчики обычно не тестируют их должным образом и иногда вставляют разные регулярные выражения в конечные точки бэкенда. Например, вышеупомянутое регулярное выражение «^\S+@\S+\.\S+$» не подходит для правильной проверки электронной почты:

1.png


Для серьёзных целей существует код тестирования, но он может быть специфичен для подмножества возможных случаев. В следующем сценарии вставка кавычек все еще проходит через утверждение:
Python:
>>> msg = 'Entity "test" is not available'
>>> assert re.match(r'^Entity ".+" is not available$', msg)
>>> msg = 'Entity ""><h1>x" is not available'
>>> assert re.match(r'^Entity ".+" is not available$', msg)

С GitHub Copilot все становится интереснее. Генерация кода для проверки того, является ли URL-адрес частью домена из white list, дает следующий результат в Python:
Python:
def url_is_subdomain(url, domain):
    """Return True if url is a subdomain of domain."""
    return re.match(r'^(?:https?://)?(?:[^/]+\.)?%s(?:/.*)?$' % domain, url)

Фаззинг этого регулярного выражения с помощью инструмента REcollapse, представленного ниже, дает ввод https://example՟com, который будет принят для example.com в качестве аргумента домена, но будет преобразован в xn--examplecom-ehl (punycode), что позволит злоумышленнику обойти проверку.

Почему нормализация может стать проблемой?
С точки зрения нормализации иногда может возникать путаница и повторяющиеся состояния, если нормализация не используется последовательно во всех конечных точках и потоках. Допустим, у нас есть жертва с адресом электронной почты hildegarde@example.com. Злоумышленник может попытаться исследовать все потоки с электронной почтой hil°arde@example.com.
Python:
>>> unidecode.unidecode("hil°arde@example.com")
'hildegarde@example.com'
>>> unidecode.unidecode("victim@exámple.com")
'victim@example.com'

Это также относится к доменной части, что может привести к возможности получить ссылку восстановления в домене punycode для victim@example.com на victim@exa[mple.com], которая преобразуется в victim@xn--exmple-qta.com, потенциально приводя к ATO.

Это также можно применить к потокам SSO или OAuth, если исходное или целевое приложение нормализует важные идентификаторы, такие как адреса электронной почты.

Мы не такие
Основные библиотеки регулярных выражений разных языков программирования могут иметь небольшие различия при обработке одного и того же регулярного выражения. Рассмотрим следующее общее описание знака доллара:
$ устанавливает позицию в конце строки или перед разделителем строки прямо в конце строки (если такой есть)

JavaScript:
> "aaa".match(/^[a-z]+$/)
[ 'aaa', index: 0, input: 'aaa', groups: undefined ]
> "aaa123".match(/^[a-z]+$/)
null
> "aaa\n".match(/^[a-z]+$/)
null
> "aaa\n123".match(/^[a-z]+$/)
null
Python:
>>> re.match(r"^[a-z]+$", "aaa")
<re.Match object; span=(0, 3), match='aaa'>
>>> re.match(r"^[a-z]+$", "aaa123")
>>> re.match(r"^[a-z]+$", "aaa\n")
<re.Match object; span=(0, 3), match='aaa'>

>>> re.match(r"^[a-z]+$", "aaa\n123")
Ruby:
irb(main):001:0> "aaa".match(/^[a-z]+$/)
=> #<MatchData "aaa">
irb(main):002:0> "aaa123".match(/^[a-z]+$/)
=> nil
irb(main):003:0> "aaa\n".match(/^[a-z]+$/)
=> #<MatchData "aaa">
irb(main):004:0> "aaa\n123".match(/^[a-z]+$/)
=> #<MatchData "aaa">

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

2.png


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

Техника REcollapse
Итак, как обойти проверку и очистку? Кроме того, как мы можем использовать преобразования пользовательского ввода? Фазить параметры умным способом!

Рассмотрим следующий сценарий:
Код:
[+] https://example.com/redirect?url=https://legit.example.com
[-] https://example.com/redirect?url=https://evil.com

На первый взгляд мы не можем перенаправить на URL-адрес, контролируемый злоумышленником. Пробовать кучу пейлоадов тоже не работает. Что мы можем сделать?

1) Определить опорные позиции регулярных выражений
  • Начальная и конечная позиции (красный)
    • Начало и конец ввода
  • Места разделения (зелёный)
    • До и после специальных символов
  • Позиции нормализации (синий)
    • Обычно это гласные ª > a
3.png


4.png


5.png


2) Фазить все позиции со всеми возможными байтами от %00 до %ff. Вот несколько примеров:

6.png


3) Проанализировать результаты: отсортируйте по коду ответа или длине ответа

Инструмент REcollapse

Инструмент REcollapse может генерировать входные данные в соответствии с этими правилами и поддерживает различные размеры и кодировки фаззинга. Также может быть полезно обойти WAF и слабые средства устранения уязвимостей. Цель этого инструмента — генерировать полезные нагрузки для тестирования. Фактический фаззинг должен выполняться с помощью других инструментов, таких как Burp (intruder), ffuf или подобных. Ручная и творческая работа по-прежнему требуется, чтобы перейти на следующий уровень.

Инструмент доступен тут: https://github.com/0xacb/recollapse

Примечание
Примеры ошибок смотрите в слайдах моего выступления на BSidesLisbon.
Таблица нормализации также доступна здесь: https://0xacb.com/normalization_table

От ТС
Я опустил часть с напутствиями и благодарностями. За ними обращайтесь к оригинальному посту.
Давно ничего не переводил и не писал для форума. Постараюсь находить для этого больше времени

Оригинал:

Перевод:
Azrv3l cпециально для xss.pro
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх