В прошлый раз наша команда провела небольшой семинар по JavaScript (Посмотрите статью здесь: 8 викторин по Javascript, которые могут сбить вас с толку). И у нас все получилось довольно хорошо. Всем понравилось решать эти небольшие задачи.
На этот раз мой товарищ по команде принес практикум по поиску уязвимостей в веб-приложениях Node.js.
Это несложно. В веб-приложении есть 2 уязвимости. Способ «захватить флаг» — означает успешно войти в систему. Если вам все удалось, текст flag будет отображен на странице.
Начать работу
Следуйте инструкциям и убедитесь, что вы все сделали правильно. Теперь вам разрешено просматривать только файлы репозитория
-
README.md
-
vuln1/index.js
-
uploads/*
-
package*.json
Помните, что нельзя мошенничать до завершения теста (Всевышний наблюдает за вами). Вот несколько предупреждений перед началом.
-
Пожалуйста, не открывайте файл
.env
. -
Пожалуйста, завершите тест, не изменяя исходный код (однако, отладка разрешена).
-
Пожалуйста, следуйте приведенным выше советам
0. Предварительные условия
Убедитесь, что в вашей системе установлен Node 16+ (требуется NPM v8). Рекомендуемый способ установки Node.js через nvm
$ nvm install 16 ... $ nvm use 16
1. Клонируйте репозиторий
Вот ссылка на репозиторий.
$ git clone git@github.com:daiyanze/vulnerability-code-challenge.git $ cd crack-the-code-challenge & npm i
2. Запустите сервер
$ npm -w challenges/vuln1 run start > vuln1@1.0.0 start > node index.js Started on http://localhost:81
3. Откройте http://localhost:81
Затем появится следующий экран.
Все, что касается взлома кода, начинается отсюда.
На этой странице администратора можно сделать 4 вещи:
-
Изменить имя и содержимое файла JSON.
-
Загрузить свой JSON-файл.
-
Распечатать содержимое JSON-файла.
-
Вход в систему.
Теперь ваша задача — пройти этап входа в систему, чтобы на странице отобразился текст flag
.
Подсказки
Если вы все еще не знаете, как это сделать, воспользуйтесь приведенными ниже подсказками, по порядку. Но, пожалуйста, не забудьте сначала прочитать код в файле index.js
. В нем вы найдете много полезных сведений.
Подсказка 1
А как насчет просмотра других файлов на сервере?
Подсказка 2
Посмотрите внимательно на сообщения вашего терминала.
Подсказка 3
Как насчет изменения содержимого файла parsed.json?
Подсказка 4
Вы же знаете, что могли бы мутировать prototypes и __proto__, не так ли?
Подсказка 5
Просто перейдите в раздел ответов. Там будет написано, как это сделать.
Когда флаг захвачен
Не читайте этот раздел, если вы еще не захватили флаг. Но я очень надеюсь, что вы уже сделали это. В противном случае изложенное ниже просто даст вам возможность подробно разобраться с загадкой, прежде чем вы сумеете разгадать ее самостоятельно.
Объяснение
В первых нескольких абзацах этой статьи упоминается, что у нас есть 2 уязвимости. И обе они представляют угрозу на этапе входа в систему.
Ключевыми моментами являются:
-
Где мы получаем пароль?
-
Как мы можем обмануть аутентификацию?
Когда мы поймем, как справиться с этими проблемами, ответ окажется прямо на поверхности.
Не так уж сложно связать пароль с таинственным файлом .env
, верно? Поскольку вам сказали не смотреть на него, то любопытство могло подтолкнуть вас к «методу» открытия этого файла, как написано в «Подсказке 1».
Итак, если вы попытаетесь открыть содержимое файла .env
через «Read uploaded JSON (Прочитать загруженный JSON)», появится пароль. О, теперь у нас есть пароль. Значит, это должно сработать? Конечно, нет. Это только начало.
Помните, что написано в исходном коде об аутентификации?
const user = { // just pretend this comes from a db password: "$2a$12$3cSdZFdEIG9FizllB9.5E.M8DTQQ185zyITtBTBz7Lz3Va8s0xjSy", }; switch (user.auth_method ?? "bcrypt") { case "bcrypt": passed = bcrypt.compareSync(req.body.password, user.password); break; case "superadmin": passed = req.body.password === process.env.SUPER_ADMIN_PASS; break; default: throw new Error("invaid auth method"); }
Зашифрованный password
уже имеется, но расшифровать его не так-то просто. Поэтому точкой прорыва является user.auth_method
. Вам нужно найти способ превратить значение user.auth_method
в «superadmin». Но как?
Что ж, вот одна полезная информация из терминала при инсталляции пакета. В вашем пакете есть одна уязвимость с критическим уровнем серьезности.
added 110 packages, and audited 111 packages in 8s 5 packages are looking for funding run `npm fund` for details 1 critical severity vulnerability To address all issues, run: npm audit fix Run `npm audit` for details.
Когда вы пробовали npm audit fix, решение легко могло прийти в голову, если у вас имелся опыт работы с «загрязнением прототипов».
added 1 package, removed 1 package, and audited 120 packages in 2s 10 packages are looking for funding run `npm fund` for details # npm audit report lodash <=4.17.20 Severity: critical Prototype Pollution in lodash - https://github.com/advisories/GHSA-jf85-cpcp-j695 Prototype Pollution in lodash - https://github.com/advisories/GHSA-fvqr-27wr-82fm Command Injection in lodash - https://github.com/advisories/GHSA-35jh-r3h4-6jhm Regular Expression Denial of Service (ReDoS) in lodash - https://github.com/advisories/GHSA-x5rq-j2xg-h7qm Prototype Pollution in lodash - https://github.com/advisories/GHSA-p6mc-m468-83gw fix available via `npm audit fix --force` Will install lodash@4.17.21, which is outside the stated dependency range node_modules/lodash 1 critical severity vulnerability To address all issues, run: npm audit fix --force
Вот очень хорошая статья о «загрязнении прототипов».
Простыми словами, «загрязнение прототипа» — это «расширение/изменение глобальных объектов».
Object.__proto__.auth_method = "superadmin" Object.constructor.prototype.auth_method = "superadmin"
С помощью описанной выше уловки вы запросто добавите некоторые дополнительные специи к содержимому JSON. Теперь можно захватить флаг.
{"__proto__":{"auth_method":"superadmin"}}
Уязвимость, которая помогает вам «преодолеть» аутентификацию по паролю, исходит от lodash <= 4.17.20
. Обратитесь к этой странице, чтобы получить более подробную информацию.
Ответ
Решение занимает всего 3 шага.
-
Введите следующее в «Secure JSON formatter»
<textarea>
и нажмите кнопку «Format & Upload».{"__proto__":{"auth_method":"superadmin"}}
-
Введите
../.env
в поле «Read uploaded JSON» и нажмите кнопку «Read». -
Введите то, что вы получили на шаге 2, в поле «Логин».
Затем на странице вы получите текст flag
.
Резюме
Сама по себе эта практика не особо сложна. Тем не менее, я думаю, что она предоставила нам несколько хороших предостережений о том, как заботиться о безопасности проекта.
Первое, что важно в создании безопасных приложений — это постоянно проводить «валидацию и санацию пользовательских входов» и никогда не использовать их сразу напрямую.
Когда мы будем доверять конечным пользователям? Когда нет никакого ввода вообще.
Второй важный момент — наши проекты. Некоторые разработчики обычно не обращают внимания на информацию из npm audit
. «Это нам не нужно». Но когда речь идет о некоторых проблемах безопасности, npm audit
уже дал нам достаточно подсказок для дальнейших действий. Таким образом, постоянная проверка и обновление наших зависимостей, вероятно, помогут в создании достаточно безопасного приложения.
Сегодня вечером в Otus состоится открытое занятие по теме «Web Servers», на котором расскажем про HTTP серверы, разберем плюсы и минусы популярных серверов. Регистрация доступна по ссылке для всех желающих.
ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/667926/
Добавить комментарий