Если вы хороший программист, то наверное у вас появлялась мысль — заняться поиском уязвимостей сайтов (в веб-приложениях) и заработать на программе Bug bounty. Это хорошая идея, но для начала не плохо бы попрактиковаться в поиске уязвимостей на сайтах и сделать это не нарушая закон. В этом поможет поможет площадка Juice Shop, созданная спецами OWASP.
Еще по теме: Инструменты для поиска уязвимостей при участии в Bug Bounty
Сегодня я покажу, как установить и использовать OWASP Juice Shop для поиска уязвимостей веб-приложений. Погнали!
Установка и запуск OWASP Juice Shop
Установить Juice Shop можно по разному, я предпочитаю и рекомендую сделать это с помощью Node.js, так как Docker есть не все возможные уязвимости.
Никогда не применяйте такие вещи в реальных интернет‑магазинах! Это уголовно наказуемо практически во всех странах. Исключением может быть участие магазина в программе bug bounty, но там много разных нюансов, с которыми нужно ознакомиться до начала поиска уязвимостей на сайте!
Установка Node.js
Juice Shop работает с разными релизами Node.js. На сегодня последняя версия — LTS (Long Term Support) Node.js 14, ее и поставим. Для начала установим Node Version Manager. Он был создан для того чтобы не захламлять свою операционную систему пакетами и иметь возможность использовать различные релизы.
На момент написания статьи последняя версия — 0.38. Установка Node Version Manager выполняется одной командой в домашней папке.
1 |
$curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash |
Теперь необходимо открыть и закрыть терминал, чтобы применить изменения внесенные скриптом .
Проверьте установленную версию nvm и переходите непосредственно к установке Node.js.
1 2 |
$nvm -v $nvm install --lts |
Проверьте версию установленной команды node и запомните ее.
1 |
$node --version |
Если вам надо несколько разных версий одновременно, тогда установите нужные и выберите актуальную по необходимости.
1 2 |
$nvm install <номер версии> $nvm use <номер версии> |
Установка OWASP Juice Shop
В GitHub часто появляются новые релизы, поэтому всегда качайте самый последний. Но не забудьте, он должен быть совместимым с вашим Node.js. Если на предыдущем этапе вы установили Node.js 14, то вам будет нужен juice-shop-xx.x.x_node14_linux_x64.tgz. Скачайте и распакуй его.
1 |
$tar -xzf juice-shop-xx.x.x_node14_linux_x64.tgz |
На этом установка завершена. Передем в папку с Juice Shop и запускаему его:
1 |
$npm start |
Если установка прошла хорошо, вы увидите сообщение «info: Server listening on port 3000».
Откройте свой браузер и зайдите на http://localhost:3000.
С права вверху выберите английский язык. Почему английский? Так в будущем не возникнут проблемы перевода всяких терминов.
Настройка Burp Suite
В моем случае будет использоваться Burp Suite, но вы можете использовать любой другой инструмент.
Еще по теме: Лучшие расширения для Burp Suite
Поиск доски с заданиями
Вы наверное при первом запуске уже заметили пакет с соком, предлагающий решить очень простую задачу, а именно найти доску с заданиями и результатами, она же Score Board. У этой крайне простой задачи есть два варианта решения.
- Внимательно посмотрите на адресную строку вида /#/search, /#/login и так далее и подумайте, а какой бы была строка для доступа к Score Board? Сразу скажу, этот вариант мне не очень нравится, поскольку нужно играть в угадайку, и не всегда успешно. Поэтому я предпочитаю вариант номер два.
- Давайте изучим исходный код сайта и посмотрим, нет ли там чего интересного. Я надеюсь, вы умеете читать исходный код сайта в своем любимом браузере? В Firefox достаточно просто нажать F12.

Что сразу же бросается в глаза? Огромное количество подключаемых скриптов на JS! Нас будет интересовать скрипт main. За что отвечают другие скрипты, вы можете выяснить на досуге с помощью любимых анонимных поисковиков.
Теперь переходим во вкладку Debugger и смотрим на исходный код main. Выглядит не очень, правда? Тут есть два пути: или пытаться восстановить код после минимизатора JS c помощью одного из множества сайтов‑деобфускаторов или просто выбрать в Firefox (кликнув по закладке с названием файла) Pretty print source и получить более читаемый исходный код. Для наших целей пока хватит и этого.
Код внушительный. Это плохо и хорошо одновременно. Обычно это говорит о том, что очень много логики сайта вынесли в клиентский JavaScript, а значит, ее можно будет легко обойти простым дебаггером. Найдем же наконец Score Board. Как эффективнее искать в исходниках, каждый решает сам, но в результате вы должны добраться до куска с уже знакомыми вам маршрутами вроде /#/search.

Вбивайте в адресную строку:
1 |
http://localhost:3000/#/score-board |
и успешно выполняйте первое задание. Кстати, теперь в левом меню появился соответствующий пункт и возможность быстро открывать доску.

На просторах интернета и в YouTube есть полные решения всех задач Juice Shop. Кроме того, вы всегда можете почитать подробное объяснение почти каждого задания с решением в книге разработчиков, но я рекомендую смотреть решение только в самом крайнем случае. Более того, некоторые задачи можно решить совершенно разными методами.
В версии Juice Shop 12.7.0 появилась замечательная функция — теперь, нажав кнопку с треугольными скобками, можно увидеть исходный код уязвимого модуля и строку, в которой и происходит ошибка. Просто сравните исходный код до минимизации и тот, что вы увидели в браузере. Возможно, вы найдете новые интересные маршруты, скрытые от вас интерфейсом сайта.
Кстати, на скриншоте выше у меня уже выполнено два задания. Я просто задался вопросом, а что будет, если попробовать открыть маршрут /#/complain, не регистрируясь на сайте? Вы же помните, что без входа в учетную запись его нет в левом меню? Попробуйте открыть его как гость и отправить анонимную жалобу! Получили новую ачивку? Вот так делать не стоит и всегда нужно учитывать, что любой маршрут может быть открыт простым набором нужного адреса в адресной строке. О том, почему не стоит доверять совершенно ничему, пришедшему вам по сети, я покажу чуть позже.
Открытие админки
Прежде чем бросаться с головой выполнять задания, я рекомендую внимательно ознакомиться с содержимым доски. Все задания на ней разделены по уровню сложности от одной до шести звездочек. Деление достаточно условное. Например, нужно сообщить магазину об использовании «слабой» криптографии. Сама по себе задача решается простой отправкой в чат названия уязвимого алгоритма, вот только узнать и определить эти алгоритмы можно, выполняя задания более высокого уровня сложности. Поэтому не старайтесь выполнить все задания одного уровня сложности и лишь потом переходить к другому. Я рекомендую руководствоваться категориями (кстати, вы заметили их удивительную схожесть с OWASP Top 10?). Теги напротив каждого задания могут показать вам верное направление поиска.
Некоторые задания имеют подсказку или туториал. Попробуйте вначале обойтись без помощи. Однако некоторые задания настолько туманны, что есть смысл почитать более подробное описание в книге разработчиков. Вот, к примеру, категория «Разнообразное».

Теперь давайте перейдем к поиску админки и попытаемся в нее попасть. Надеюсь, вы еще не забыли место, где мы нашли адрес Score Board? Там же можно обнаружить и адрес админки! Однако при попытке перейти по этому адресу нас встретит красный баннер с ошибкой 403… Самое время запустить Burp Suite и посмотреть на сетевой обмен.

Удивительно, но ничего похожего на доступ к админке тут нет! Помните про огромный размер скрипта main? Наверняка вся проверка доступа обрабатывается в нем. Время поработать с дебаггером. Проще всего найти нужное место в коде по ошибке доступа — 403.

Видите первую и вторую функцию CanActivate()? Если у нас нет токена или нам запрещен доступ, то мы получаем ошибку 403. Чтобы сократить количество скриншотов, сразу скажу — придется зарегистрироваться. У незарегистрированных пользователей токена доступа нет. Так что самое время войти под созданным ранее пользователем или создать нового.
Теперь давайте попробуем обмануть скрипт. Для этого установим точку останова (breakpoint) на строке 579 и добавим в Watch переменную t.

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

Теперь осталось самое простое. Скрипт выше проверяет, соответствует ли роль значению admin. Если нет, вы увидите ошибку доступа. Поэтому вам просто нужно исправить значение роли на admin. К сожалению, с появлением новой консоли разработчика в Firefox возможность редактирования переменных в окне просмотра сломали и пока так и не вернули… Запомните путь к нужному значению t.data.role, переключитесь в окне разработчика на вкладку Console и поменяйте там значение роли на admin.

Теперь вернитесь в отладчик и продолжите исполнение скрипта. Поздравляю, вы получите доступ к административной части сайта! Почему так произошло? Нельзя надеяться на контроль доступа на уровне клиентского кода, поскольку клиент всегда может этот код изменить. Кстати, это решение по уровню сложности тянет звездочки на три. Чуть позже вы зарегистрируете нормальную админскую учетку и воспользуетесь SQLi для доступа к админке. Они намного проще, так как не требуют изучения исходного кода.
Хочу заметить, что правильный серверный код не показал бы и список пользователей или отзывов, поскольку при запросе их с сервера он должен был проверить токен прав пользователя. В нашем же случае этого не происходит и, попав в админку, вы спокойно видите все данные…
Если вы не выключили Burp, то можете найти эти строки в обмене и убедиться, что проверка прав доступа на серверной стороне не происходит! Откуда это можно понять? Видите куку token? Это так называемый тoкен JWT, и его можно легко раскодировать.


В этом токене, по сути, содержится весь профиль пользователя и явно указана его оригинальная роль customer, однако серверный бэкенд не проверяет права при запросе всех отзывов или профилей. Это значит, что, перехватив такой запрос, вы можете легко получать информацию о зарегистрированных пользователях, даже не открывая админку. Если вы разработчик, никогда так не делайте! Это яркий пример Broken Access Control по классификации OWASP. К сожалению, и в реальной жизни он встречается на каждом шагу… Особенно этим грешат микросервисные архитектуры.
Регистрация учетной записи администратора
Самое время зарегистрировать себе полноценную учетную запись администратора! Для этого нужно разобраться, какая же информация отправляется при регистрации обычной учетной записи с сайта. В этом вам поможет Burp Suite. Запускайте его и проходите процесс регистрации полностью.

Как видите, отправив информацию из формы, в ответ вы получите профиль пользователя с ролью customer. Одна из традиционных ошибок разработчика связана с так называемым mass assignment, или массовым заполнением полей. Код регистрации пользователя принимает список полей профиля для обработки, а для отсутствующих полей назначается значение по умолчанию. Видите пустое поле username в ответе? Попробуйте перехватить этот запрос до отправки и вставить в него поле username, как на скриншоте ниже.

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

Использование SQL-инъекции для входа
Я очень надеюсь, вы не раз слышали об SQL-инъекциях и причинах их возникновения. Если нет, то самое время отправиться изучать теорию. Мне очень нравится обширный справочник по инъекциям. Откройте окно логина пользователя и начните с самого простого, вставив одинарную обратную кавычку в поле логина и произвольный пароль. Судя по ярко‑красной ошибке, мы на правильном пути!

К сожалению, совершенно непонятно, что же именно происходит и как дальше развивать эту инъекцию. Здесь есть два варианта решения: либо вы обладаете большим опытом инъекций и планомерно подбираете нужные значения, либо, если это не о вас, запускайте Burp и смотрите, что же происходит в сети. Помните, это очень уязвимое приложение, и наверняка разработчики допустили не одну ошибку…

Кто бы сомневался, тут даже есть код оригинального SQL-запроса. Теперь подобрать правильную нагрузку для окна логина не составит особого труда!

Здесь я должен сделать несколько важных замечаний.
- Вы нигде не указали почту, но вошли как администратор. Это произошло потому, что в этом варианте инъекции выбирается первая строка в базе, она же чаще всего будет первым зарегистрированным пользователем или суперадминистратором. Такое поведение есть в большинстве CMS.
- Если у вас есть адрес почты интересующего вас пользователя, то вы можеыр немного модифицировать инъекцию и войти сразу же от его лица.
- Это самый простой и яркий пример класса Injection. Недаром они стоят на первом месте по классификации ОWASP.
- В коде приложения еще много мест с инъекциями, как и заданиями на нее, но они уже сложнее по уровню исполнения и наносимому урону. Например, можно получить всю базу данных вместе с паролями пользователей!
Подбор пароля администратора
Мне кажется, администратор этого магазина уже достаточно настрадался от вас, однако в списке заданий есть достаточно интересное — на подбор пароля администратора. Судя по всего двум звездочкам рейтинга, оно крайне простое – мы же решим его более сложным, но универсальным методом!
Какие же ошибки в реализации аутентификации допустили разработчики этого приложения? А все самые популярные из раздела Broken Authentication:
- отсутствует защита от перебора пароля;
- пользователь может установить слабый пароль;
- пользователь может установить простой, как раз‑два‑три, пароль…
Вы можете попробовать просто угадать пароль администратора, это не так сложно, как кажется на первый взгляд (или нажмите кнопку Tutorial, и пакет с соком вам поможет). Кроме того, я оставил вам небольшую подсказку в предыдущем абзаце. Я же покажу, как можно решить эту задачу с помощью перебора и списка популярных паролей rockyou.txt.
Для начала вам нужно перехватить запрос на аутентификацию. Для этого просто откройте Burp и попробуйте поочередно войти как любой пользователь с правильным и неправильными паролями.

Как видите, для логина достаточно отправить JSON с двумя полями, если пароль неправильный — вам вернется код 401. Тут я попробовал настроить самый известный подборщик паролей Hydra, но после получаса борьбы с ним просто написал вот такой небольшой код на Python.
Дело в том, что Hydra очень не любит JSON и некоторые нюансы поведения этого приложения. Если хотите, можете сами попробовать решить эти проблемы.
1 2 3 4 5 6 7 8 9 10 |
import requests passwords = open('/usr/share/wordlists/rockyou.txt','r') for password in passwords: password = password.rstrip("\n") data = {'email':'admin@juice-sh.op','password':password} r = requests.post('http://localhost:3000/rest/user/login',json=data) if r.status_code == 200: print("Password is ",password) break print("That's all... ") |
Маленькая рекомендация: прежде чем запускать перебор по всему словарю для неизвестных пользователей, убедитесь, что вы сможете подобрать свой собственный пароль и в коде нет никаких ошибок. В моем случае пришлось добавить код удаления символа переноса строки из пароля.
Еще по теме: Уязвимость Broken authentication на примере bWAPP
Получение Deluxe Membership бесплатно
Напоследок я покажу вам, как можно решить более сложную задачу, а именно получение Deluxe Membership бесплатно!
Для начала запустите Burp и посмотрите на весь обмен с сервером при попытке купить Deluxe без денег в кошельке и карт. Как видите, в одном из запросов вам возвращают стоимость в 49 условных единиц. Воспользуйтесь своими навыками работы в Burp и превратите их в 0.

После этого на следующем экране вы сможете оплатить 0 из кошелька, но почему‑то это так просто не получится… Если посмотреть обмен, то увидите платеж из кошелька и ошибку «недостаточно денег».

А что, если заменить paymentMode на что‑то более интересное, например free или deluxe?

Поздравляю! Вы только что обманули магазин на 49 условных единиц. Более того, если вы внимательно поэкспериментируетес разными вариантами оплаты, то выясните, что менять цену на 0 на первом этапе совершенно необязательно. Главное — превратить GET-запрос /rest/deluxe-membership в POST-запрос и добавить в него JSON-данные paymentMode с любым отличным от wallet или card значением.
Выводы
Очень надеюсь, что эта статья подтолкнула вас к более глубокому изучению рекомендаций OWASP и типовых ошибок веб‑приложений. В Juice Shop еще много интересных задач как для начинающих, так и для опытных пентестеров. Я же прощаюсь с вами до следующей статьи, в которой вы попробуете решить задачи с большим количеством звездочек!
Еще по теме: Обзор лучших сканеров уязвимостей