# Web. Практическая работа №3 ## Цель работы: Изучить основные атаки на WEB По вашей просьбе выкладываю скрин прогресса на portswigger ![](https://i.imgur.com/PRs5F0V.jpg) ## Задания Практической работы: На стенде по адресу [https://portswigger.net/web-security](https://portswigger.net/web-security) разобрать следующие задания: ## SQL-injection уязвимости: - [https://portswigger.net/web-security/sql-injection/lab-login-bypass](https://portswigger.net/web-security/sql-injection/lab-login-bypass) - [https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data](https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data) - [https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables](https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables) - [https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-mysql-microsoft](https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-mysql-microsoft) Все решения задач по атакам на SQL базы данных сводяться к модификации запросов к БД сервера. Делается это (чаще всего) путем дописывания команд SQL в поля ввода интерфейса приложения. Т.е. атакующий, исходя из своих предположений о том, как выглядит SQL-запрос внутри сервера, дописывает его так, чтобы можно было использовать уязвимость приложения. Для удобства будем использовать BurpSuite хотя можно обойтись и без него. **1. Обход аутентификации.** Предположим, что сервер получаяя аутентификационные данные использует запрос: `SELECT * FROM users WHERE username = 'administrator' AND password ='StrongPa$$w0rd'` Дописывать мы можем только в поля логина/пароля (а у нас это слова administrator и StrongPa$$w0rd). Как здесь можно "отключить" проверку пароля? Да просто закомментировать его. Модифицируем запрос так, чтобы не нарушить синтаксис языка: SELECT * FROM users WHERE username = 'administrator =='- -== ' AND password ='StrongPa$$w0rd' При этом, все что идет после нашей модификации - становиться комментарием и никак не учитывается сервером БД. Отправляем POST-запрос со страницы в входа в Репитер: ![](https://i.imgur.com/v2rT7gy.jpg) Модифицируем запрос: ![](https://i.imgur.com/h5jNVP9.jpg) Сайт перенаправляет нас в аккаунт. Это можно видеть в истории запросов - 302 редирект с POST-запроса на страницу аккаунта. Страница открылась с кодом 200 ОК. ![](https://i.imgur.com/JlvNoyL.jpg) ![](https://i.imgur.com/ug7MlF1.jpg) **2. Извлечение скрытых данных** Нам нужно извлечь скрытый список товаров. В данном случае тех, которых нет в продаже (либо есть в продаже, но для отдельных категорий граждан :)). Зайдем в любую категорию и посмотрим, какой отправляется запрос к серверу. ![](https://i.imgur.com/srUx5Ww.jpg) Мы предполагаем (или уже знаем) что запрос с отображением только доступных товаров выглядит так: `SELECT * FROM products WHERE category = 'Pets' AND released = 1` Можно модифицировать запрос как в прошлом примере: `... Pets'-- ...` Но тогда мы будем видеть все товары только в категории Pets. А чтобы вывести ВЕСЬ список товаров, по всем категориям, нужно модифицировать запрос так, чтобы для любого элемента таблицы WHERE всегда возвращал true Т.е. чтобы `SELECT * FROM products WHERE true` что равносильно `SELECT * FROM products` Делаем SELECT * FROM products WHERE category = 'Pets ==' OR 1=1- -==' AND released = 1 Поскольку 1 всегда равен 1 , то WHERE будет возвращать либо товар из категории Pets либо true Проверяем ![](https://i.imgur.com/zE8bQ2J.jpg) ![](https://i.imgur.com/XtgohTz.jpg) **3. Union-based - атака** У нас есть ОДНА уязвимая таблица, выводом которой мы можем управлять. Каким образом можно получить доступ к другим таблицам БД используя текущую таблицу? Нужно попробовать объединить обе таблицы в одну. В SQL 'то позволяет сделать оператор UNION Предопложим, что приложение выполняет запрос к БД, содержащий пользовательский ввод «Gifts»: `SELECT name, description FROM products WHERE category = 'Gifts'` тогда злоумышленник может отправить ввод: `' UNION SELECT username, password FROM users-- ` образуя тем самым запрос вида SELECT name, description FROM products WHERE category ='Gifts ==' UNION SELECT username, password FROM users- -==' :::warning ВАЖНО! Количество столбцов в обеих таблицах должно совпадать. ::: Проверяем: ![](https://i.imgur.com/xaTceMK.jpg) Авторизуемся ![](https://i.imgur.com/97dQ9DC.jpg) **4. Узнаем тип базы данных** Чтобы быстрее и качественнее проникнуть в БД, нужно знать тип базы данных, какие есть в ней таблицы и прочее. Информацию можно получить выполнив запрос `SELECT @@version` А куда нам его поместить? Нам поможет UNION оператор! Возьмем запрос из предыдущего примера и дополним его нашей командой. SELECT name, description FROM products WHERE category ='Gifts ==' UNION SELECT @@version, NULL- -==' Как я писал выше, нужно чтобы количество столбцов в обоих запросах совпадало. Поэтому во втором запросе мы добавляем пустой столбец NULL, чтобы получить... Чтобы вообще хоть что-то получить. С разным количеством столбцов ответа не будет. Пробуем, и получаем версию БД: ![](https://i.imgur.com/1vWvd9I.jpg) ## XSS уязвимости: - [https://portswigger.net/web-security/cross-site-scripting/stored/lab-html-context-nothing-encoded](https://portswigger.net/web-security/cross-site-scripting/stored/lab-html-context-nothing-encoded) - [https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink](https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-document-write-sink) - [https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-string-angle-brackets-html-encoded](https://portswigger.net/web-security/cross-site-scripting/contexts/lab-javascript-string-angle-brackets-html-encoded) - [https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-dom-xss-reflected](https://portswigger.net/web-security/cross-site-scripting/dom-based/lab-dom-xss-reflected) **1. Хранимые XSS в HTML-коде** Чтобы внедрить XXS нужно, как и в случае с SQL внедрить свой код в страницу таким образом, чтобы он: 1. Работал 2. Не был заметен (не поползла верстка) В нашей задаче важно только первое. Решение простое. Пробуем внедрить js-код alert("1") прямо в коммент. Можно так и написать в комментарии к посту: ``` <script> alert("1") </script> ``` Но я сделаю это через Берп. ![](https://i.imgur.com/IodB37J.jpg) Попроубем посетить страницу с комментариями снова. Код исполняется ![](https://i.imgur.com/7PdMzvP.jpg) Если мы теперь заглянем в структуру страницы, то мы найдет наш код, внедренный в HTML "безшовно". ![](https://i.imgur.com/ZPpBcCe.jpg) :::info Используя `alert("1")` мы рискуем попасть "на карандаш" системе безопасности целевого сайта. Чтобы снизить риски, лучше использовать теги (например <img src=x>). Так тоже можно проверить уязвимость полей ввода, но при этом не быть замеченным ::: **2. DOM XSS в document.write** Приложение может быть уязвимо для DOM XSS, если есть исполняемый путь, по которому данные могут распространяться от источника к приемнику. Есть очень много приемников, которые относятся к уязвимостям на основе DOM. Введем любой запрос на нашей странице и рассмотрим его результаты в Инспекторе браузера. Ага! Мы обнаружили приемник document.write. Мало того, он работает со скриптами. Какое счастье! Как видно, после выполнения скрита, наш запрос помещается в атрибут src, тега img в теле документа. ![](https://i.imgur.com/f0y8Z7c.jpg) Осталось только модифицировать наш поисковый запрос так, чтобы он как минимум исполнялся не вызывая синтаксических ошибок скрипта. Вывод запроса: `<img src="/resources/images/tracker.gif?searchTerms=GIFT">` Модификация: `<img src="/resources/images/tracker.gif?searchTerms=GIFT`=="\>\<svg onload=alert(1)>=="> Я специально оставил в конце "> чтобы показать, куда мы вставили наш пэйлоад и что эта часть исходного кода никуда не девается. Она останется в теле документа. ![](https://i.imgur.com/Mw6DXsL.jpg) **3. Отраженные XSS в строковых литералах** В некоторых случаях, когда контекст XSS находится внутри строкового литерала в кавычках, можно выйти за пределы строки и выполнить JavaScript напрямую. для выхода из строкового литерала можн оспользовать следующий пейлоад: `'-alert(1)-'` Исполняем. Запустим лабораторию и выполним любой запрос Допишем наш пейлоад прямо в адресную строку, в появившемся запросе параметров ?search= ![](https://i.imgur.com/PetTh2L.jpg) После того, как мы выполним запрос и уберем всплывший alert, мы увидим, что задача решена. Мы выбрались из строки. ![](https://i.imgur.com/RrHNWnH.jpg) Теперь эту ссылку можно отправить жертве. Код будет исполняться на любой машине, с которой перейдут по этой ссылке. Не открывайте незнакомые или подозрительные ссылки. **4. Отраженная DOM XSS** Уязвимость этой лабораторки возникает в случае, когда клиентский запрос получен на сервере, обработан, результат упакован в json и отправлен обратно клиенту. Но на клиентской стороне, результат в конечном счете записывается в приемник. Но небезопасным способом. Этим мы и воспользуемся. Выполним любой запрос в поиске лаборатории. В истории мы видим, что на самом деле выполняется два запроса, один из которых отправляется из пути /search-results/ в формате json. ![](https://i.imgur.com/JUHhM8T.jpg) Также видим, что в ответе выполняется скрипт. `script src='resources/js/searchResults.js'` Посмотрим скрипт поближе. И тут мы находим небезопасную функцию eval которая может выполнить код! Значит, нам надо выбраться из формата json, и наш код выполнится. Сайт проглатывает (не экранирует) обратный слеш. Поэтому, мы вводим в поисковую строку следующий пэйлоад `\"-alert(1)}//` Который прочитается скриптом как `{"results":[],"searchTerm":""-alert(1)}` Почему так? Разберем. Обратный слеш сайт пропускает. Однако, видя двойные кавычки, сайт добавляет свой обратный слеш. В итоге вместо команды "экранируй кавычки" (помести их в строку) мы получаем команду "Экранируй обратный слеш, а кавычки не трогай". Далее идет "минус" как разделитель выражений, после чего наш alert и закрываем формат json. Потом комментарий. И это сработало. ![](https://i.imgur.com/XD9gmRp.jpg) ## CSRF: - [https://portswigger.net/web-security/csrf/lab-no-defenses](https://portswigger.net/web-security/csrf/lab-no-defenses) - [https://portswigger.net/web-security/csrf/lab-token-validation-depends-on-request-method](https://portswigger.net/web-security/csrf/lab-token-validation-depends-on-request-method) **1. CSRF без защиты** В этой лабе моделируется ситуация, когда жертва открывает ссылку, перейдя по которой, произойдет что-то нехорошее. В нашем случае это будет смена почты аккаунта жертвы. Естественно, без уведомления последней. Как это происходит? Атакующий пишет эксплойт и помещает его на своей контролируемой странице (для этого мы используем сервер эксплойтов). ![](https://i.imgur.com/iknK6gn.jpg) ```htmlembedded <form method="POST" action="https://0ad9005104ef5131c0990e2d00d70040.web-security-academy.net/my-account/change-email"> <input type="hidden" name="email" value="attack@hack.ru"> </form> <script> document.forms[0].submit(); </script> ``` Затем, отправляет ссылку жертве (нажимаем отправить жертве). При переходе по ссылке жертву перебрасывает на URL из эксплойта, происходит автозаполнение поля почты и отправка данных на сервер. ![](https://i.imgur.com/FNg9iAd.jpg) Возможно, жертва даже не увидит ответа сервера. Да это и не нужно. Запрос мы все равно уже отправили. **2. CSRF, с проверкой токена** Некоторые приложения проверяют токен лишь методе POST "забывая" про метод GET. Воспользуемся этим. Для начала проверим нашу теорию. Поменяем почту как обычно, по всем правилам. Затем откроем Burp и посмотрим что происходит в запросе. ![](https://i.imgur.com/TKLu6TW.jpg) В этот раз приложение использует токен csrf для большей безопасности. Попробуем произвольно изменить токен ![](https://i.imgur.com/iY46RG5.jpg) Ничего не вышло. Тогда попробуем изменить метод запроса на GET ![](https://i.imgur.com/eFmbTWx.jpg) Даже с неправильным токеном удалось изменить почту. Дальше действуем по накатанной схеме: Создаем и отправляем эксплойт жертве. Жертва открывает ссылку Задача выполнена В эксплойте, мы также всего лишь меняем метод ![](https://i.imgur.com/5qNYjBu.jpg) ## SSRF: - [https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-localhost](https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-localhost) - [https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection](https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection) 1. **SSRF на внутреннюю инфраструктуру** Если мы видим, что приложение использует запросы к внутренним серверам. То можно попытаться выполнить атаку SSRF, подменив запрос на свой. Посмотрим, что отправляет приложение серверу в POST-запросе, когда нам надо проверить остатки по товару. ![](https://i.imgur.com/FYR99Nu.jpg) Выполняется некий запрос на внутренние сервера. А если попробовать зайти на другие ресурсы инфраструктуры? Изменим запрос в Репитере. Приведем его к виду `stockApi=http://localhost/admin` и выполним. ![](https://i.imgur.com/OFdGhN3.jpg) Оба-на! Админка! Немного похулиганим и удалим аккаунт Карлоса. Для этого еще раз изменим запрос, чтобы выполнить удаление. ![](https://i.imgur.com/HriTGmi.jpg) ## 2. SSRF с обходом фильтра через открытое перенаправление Приложение может проверять что мы ему подсовываем под видом запроса. Но иногда, проверка может быть неполной. Попробуем изменить запрос к внутреннему серверу как в прошлый раз ![](https://i.imgur.com/fdpMljK.jpg) Ничего не выходит. А вот внизу справа, есть кнопка "Следующий продукт". И от этой кнопки ведет ссылка, содержащая в себе открытое перенаправление. `http: ... /product/nextProduct?currentProductId=7&path=/product?productId=8` Более того, часть этой ссылки помещается в заголовок, при при нажатии. `http: ... /product?productId=8` Это как раз и есть то самое перенаправление. Вот интересно, проверяет его приложение или нет? Попробуем поместить наш адрес внутреннего ресурса в такую ссылку. `stockApi=/product/nextProduct?path=http://192.168.0.12:8080/admin` Нас перенаправило на внутренний сервер. ![](https://i.imgur.com/J6UFSWS.jpg) Ура! Мы внутри. Удалим несчастного Каролоса. ![](https://i.imgur.com/ghsC8jx.jpg) ## RCE - удаленное выполение кода Голубая мечта каждого пентестера - найти RCE. Ведь это дает, как правило, полный или значительный контроль над ресурсом. - [https://portswigger.net/web-security/os-command-injection/lab-simple](https://portswigger.net/web-security/os-command-injection/lab-simple) **1. Простая RCE** Условиями задачи предполагается, что параметры запроса передаются на сервер "как есть" без проверки и выполняются скриптом. Найдем сначала передаваемые параметры ![](https://i.imgur.com/NX7lJkg.jpg) Понятно, что скрипт будет запрашивать, скорее всего значения самих параметров. Вот их и попробуем изменять. Кроме логического или, которое дается в решении, похожий результат выдает точка с запятой ![](https://i.imgur.com/6ZyeSvD.jpg) Логин уже есть. Теперь можно брутфорсить пароль. ## Path traversal - [https://portswigger.net/web-security/file-path-traversal/lab-simple](https://portswigger.net/web-security/file-path-traversal/lab-simple) - [https://portswigger.net/web-security/file-path-traversal/lab-absolute-path-bypass](https://portswigger.net/web-security/file-path-traversal/lab-absolute-path-bypass) Path traversal - уязвимость которая возникает на серверах nginx в случае неправильной настройки конфигурации. Я бы сказал невнимательной настройки. Заключается в том, что используя последовательность /../ можно подняться на один уровень вверх в каталоге. Рассмотрим на примере задачи. **1. Простой случай Path traversal** Включим Intercept- перехват запросов в Proxy. Откроем страницу с товаром, нажмем Forward и модифицируем текущий запрос так, чтобы подняться в корень сайта. ![](https://i.imgur.com/u9Nj33D.jpg) Наш запрос: `/image?filename=25.jpg` Мы предполагаем, что наши картинки находяться в каталоге /var/www/image/25.jpg До корня - 3 уровня. Поднимаемся `/image?filename=../../../` Теперь мы в корне. Но это еще не все. Дальше нам надо спуститься отсюда к файлу passwd. Он находится в каталоге /etc. Делаем `/image?filename=../../../etc/passwd` Вставляем полученный пейлоад в наш запрос, выключаем перехват и смотрим на результат ![](https://i.imgur.com/YwVATyO.jpg) Вот и список пользователей. Кстати. Еще одно подтверждение тому, что используется nginx - наличие пользователя www-data. 2. Path traversal обход с помощью абсолютного пути Многие приложения, помещающие пользовательский ввод в пути к файлам, реализуют некоторую защиту от атак Path traversal, но и эти защиты можно обойти. Наприме, можно попробовать использовать абсолютный путь от корня файловой системы, например filename=/etc/passwd. Реализуем. Порядок действий абсолютно такой же, как в предыдущем примере. Только вместо последовательностей `/../../..` в запросе, мы сразу пишем `filename=/etc/passwd` Смотрим что получилось ![](https://i.imgur.com/TXugHDB.jpg) Задача выполнена.