Анализ неуязвимости Koa.JS, также известный как Почему индустрия безопасности не понимает программное обеспечение?
Мое разочарование все время высоко, потому что это только что произошло снова. Если вы читали мой предыдущий анализ под названием CVE-2022–29622: анализ (не)уязвимостей , вы можете подозревать, о чем я говорю. Та же история, другая жертва. Однако в данном случае важны даты. Мой предыдущий анализ неуязвимости относится к 2022 году, сегодня я собираюсь проанализировать еще одну проблему из 2018 года.
Вы можете спросить: «Почему вы должны иметь дело с чем-то из 2018 года?» Отличный вопрос! Потому что я только недавно включил Dependency Track для извлечения информации об уязвимостях из индекса OSS Sonatype.

Сегодня, когда я бегло просматривал SCA , чтобы увидеть, есть ли у нас какие-либо уязвимые компоненты, и, если они есть, расставить приоритеты по исправлению. Я столкнулся с чем-то очень удивительным. В Koa.JS есть критическая уязвимость?! После моего обычного «#FFS, вся моя неделя нуждается в перестановке», я сказал: «Сделайте глубокий вдох и посмотрите, о чем идет речь. Ты помнишь, что было в прошлый раз…

Так я и сделал. Во-первых, из названия ясно, что «проблема» была обнаружена в 2018 году. Так зачем мне иметь уязвимость в библиотеке, которая все еще поддерживается, и я постоянно обновляюсь до последней версии? В этот момент включилась исследовательская часть моего мозга.
Что мы знаем/видим на данный момент?
- Якобы в 2018 году в Koa была обнаружена уязвимость с присвоенным критическим уровнем серьезности.
- Согласно Sonatype OSS Index и Dependency Track, проблема затронет меня в 2022 году при использовании последней версии Koa.
- Какие версии библиотеки Koa.JS были затронуты «уязвимостью»
- Если «уязвимость» присутствует в последней версии Koa.JS
Анализ проблемы
Давайте посмотрим, что такое «уязвимость». Позвольте мне быстро связать связанную проблему № 1250 с GitHub здесь. Я просто скопирую и вставлю пример (PoC?) ниже, чтобы мы могли его проанализировать.
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.redirect("javascript:alert(1);")
});
app.listen(3000);
«Как разработчик веб-приложения или веб-службы, я могу перенаправить ваш браузер туда, куда захочу, если вы посетите мой веб-сайт».
Вот что означает приведенный выше код. В приведенном выше PoC не представлен вектор атаки, чтобы злоумышленник мог что-либо использовать.
Если вы хотите предоставить правильный «PoC» для этой неуязвимости (ага, я только что это сказал), это будет выглядеть так:
const Koa = require('koa');
const app = new Koa();
// Try: http://localhost:3000/?vector=javascript:alert(1);
app.use(async ctx => {
ctx.redirect(ctx.request.query.vector);
});
app.listen(3000);
Говоря об уязвимости XSS, если бы то, что я ввел в качестве значения vector
параметра, небезопасно отображалось в контексте HTML, реализованное мной приложение было бы уязвимо для межсайтового скриптинга. (Подробнее об этом позже)
Увеличив масштаб того, как Sonatype представила это, и проанализировав его немного дальше:

«Открыть перенаправление, ведущее к межсайтовому скриптингу»? Во-первых, не было открытого редиректа. Он открывается только в том случае, если вы его открываете, и разница между двумя PoC (оригинальным и моим) ясно показывает это. В первом не было вектора атаки, а значит, и открытого редиректа. У моего PoC был вектор атаки, без фильтрации, поэтому был открытый редирект. Но, как видите, был или не был открытый редирект, зависело от меня, разработчика, а не от Koa.JS. Даже лучше, был ли редирект или нет, тоже зависело от меня. Включил ли я введенные пользователем данные как/в URL-адрес перенаправления небезопасным способом, также зависел от меня. О какой уязвимости Koa.JS тогда идет речь? Технически уязвимости не было, и кто-то все равно присвоил ей критический уровень серьезности. Не совсем профессионально.
В любом случае, давайте «эксплуатируем» упомянутую «уязвимость», реализованную соответствующим PoC. Обратите внимание, что мне пришлось изменить порт службы с 3000 на 4444, так как у меня уже было что-то, прослушивающее порт 3000.

Мы видим, что Location
заголовок ответа имеет значение javascript:alert(1)
. Затем браузер перенаправляет на…

Ха, я в безопасности! Окно предупреждения не появлялось. Да, я мог ввести https://google.com
в качестве значения vector
параметра запроса и получить перенаправление в Google, поэтому мое приложение (PoC) уязвимо для открытого перенаправления, но не из-за Koa, а из-за того, что я передал в ctx.redirect
. Это не то, о чем я беспокоюсь, я бы никогда не сделал этого.
В комментариях к проблеме на GitHub важно отметить следующее:
Проблема связана с тем, что Koa печатает гиперссылку HTML в теле ответа перенаправления, что может вызвать атаку межсайтового скриптинга.
Ах, это имеет немного больше смысла! Посмотрим, так ли это по-прежнему.

Нет, это больше не так. Нет тела ответа. Думаю, я могу сделать вывод, что эта «уязвимость» не влияет на меня. Я могу просто пойти и отметить это как ложное срабатывание в отслеживании зависимостей.
Контекстный анализ
Я предлагаю всем специалистам по безопасности принять «Анализ контекста» и выполнять его перед тем, как сообщать о «проблемах». Пусть это будет еще одним примером и покажет вам, как это делается. (Я по-прежнему рекомендую вам прочитать CVE-2022–29622: Анализ (не)уязвимости , поскольку он намного лучше объясняет важность контекста.)
- Koa.JS из коробки никуда вас не перенаправляет. Следовательно, нет и не было «открытого перенаправления», как указано в Sonatype OSS Index.
- Основываясь на «PoC», представленном на GitHub, у разработчика была возможность сделать что-то глупое, что могло привести к XSS. Но см. № 1 выше. Koa.JS не делал никаких перенаправлений самостоятельно. См. № 2 ниже.
- Разработчик должен внедрить свое приложение небезопасным способом, чтобы сообщаемая «уязвимость» присутствовала. Это в значительной степени означает, что Koa.JS, хотя и мог бы работать лучше, нельзя назвать его уязвимым. Это контекстуально неуместно. Рассматриваемая уязвимость может присутствовать только в небезопасно реализованном веб-приложении .
Позвольте мне привести пример того, как лучше всего поступать в подобных ситуациях. Посмотрите на эту проблему, которую я отправил в Swagger Parser, и как она была передана. Проанализируем отчет о проблеме:
- В заголовке написано «Небезопасное поведение распознавателя». Я не говорю о LFI (локальное включение файлов) в заголовке. Это связано с тем, что, хотя есть вероятность включения локального файла, ЕСЛИ Я НАРУШУ ВЕЩИ, я как разработчик действительно должен знать, с чем я работаю и как я с этим работаю. Поведение по умолчанию было (возможно, до сих пор) небезопасным. Но библиотека сама по себе, без моего участия ничего не сделает.
- Затем я четко указываю, о какой версии библиотеки я говорю. Я делаю контекст еще более ясным, перечисляя условия, при которых небезопасное поведение библиотеки по умолчанию повлияет на приложение. Это ясно показывает, что сама библиотека не уязвима, но имеет небезопасное поведение, которое можно улучшить, чтобы помочь разработчикам.
- Итак, теперь, когда контекст установлен, я предоставляю рабочий PoC, уязвимый фрагмент кода (который я написал как PoC, он не является частью Swagger Parser!) и реальный результат эксплуатации уязвимого приложения/сервиса, использующего библиотека небезопасно.
- Я провел некоторое исследование и обнаружил, что как разработчик я могу настроить библиотеку таким образом, чтобы смягчить проблему. (до некоторой степени) я поделился этим с разработчиками. Если ничего другого, по крайней мере, они могут обновить документацию, чтобы повысить осведомленность.
- Я предоставил дополнительный контекст, анализ и пример того, как можно улучшить ситуацию.
Заключение
Прежде всего, Sonatype следует улучшить индекс OSS и убедиться, что информация о версии доступна для каждой уязвимости в базе данных. Это минимум. (Бонусные баллы за полное удаление этой конкретной записи из базы данных.)
Я подозреваю, что Dependency Track страдает от FOMO, поэтому он готов сообщать о проблемах исключительно на основе совпадения имени компонента, если номер версии недоступен. Я понимаю, что они не рискнули бы пропустить критическую уязвимость. Проблема с таким поведением (ложные срабатывания) заключается в том, что оно не способствует принятию анализа состава программного обеспечения. Это отпугнет разработчиков, как ложные срабатывания статического анализа кода. Контрпродуктивно.
Контекст! Кровавый контекст, люди! Я предлагаю:
- «Анализ контекста», который должен быть принят всеми специалистами по безопасности и выполняться перед сообщением о «проблемах».
- Отличие «небезопасного поведения» от «уязвимости»
- Понимание различий между библиотекой программного обеспечения и приложением/службой