В библиотеке PharStreamWrapper (https://github.com/TYPO3/phar-stream-wrapper), предоставляющей обработчики для защиты от проведения (https://www.opennet.me/opennews/art.shtml?num=49746) атак (https://www.opennet.me/opennews/art.shtml?num=49641) через подстановку файлов в формате "Phar", выявлена уязвимость (https://www.drupal.org/sa-core-2019-007) (CVE-2019-11831 (https://security-tracker.debian.org/tracker/CVE-2019-11831)), позволяющая обойти защиту от десериализации кода через подстановку символов ".." в пути. Например, атакующий может использовать для атаки URL вида "phar:///path/bad.phar/../good.phar".
Библиотека разработана создателями CMS TYPO3, но также применяется в проектах Drupal и Joomla, что делает их также подверженными уязвимости. Проблема устранена в выпусках PharStreamWrapper 2.1.1 и 3.1.1 (https://github.com/TYPO3/phar-stream-wrapper/releases). Проект Drupal устранил проблему в обновлениях 7.67, 8.6.16 и 8.7.1. В Joomla проблема проявляется начиная с версии 3.9.3 и устранена в выпуске 3.9.6. Для устранения проблемы в TYPO3 требуется обновить библиотеку PharStreamWapper.
С практической стороны уязвимость в PharStreamWapper позволяет пользователю Drupal Core, имеющему полномочия администратора тем оформления ('Administer theme'), загрузить вредоносный phar-файл и добиться выполнения размещённого в нём PHP-кода под видом легитимного phar-архива. Напомним, что суть атаки "Phar deserialization" в том, что при проверке загруженных файлов помощи PHP-функции file_exists(), эта функция автоматически выполняет десериализацию метаданных из файлов Phar (PHP Archive) при обработке путей, начинающихся с "phar://". Передача phar-файла возможна под видом картинки, так как функция file_exists() определяет MIME-тип по содержимому, а не по расширению.URL: https://arstechnica.com/information-technology/2019/05/open-.../
Новость: https://www.opennet.me/opennews/art.shtml?num=50665
Красиво
Мы написали костыль, чтобы починить дырявый костыль. Но новый костыль тоже оказался с дырой…
Ответ очевиден - нужен ещё один костыль
Эх, это ж типовой косяк двадцатилетней давности...
> Библиотека разработана создателями CMS TYPO3Михаил, это не та ли CMS, переходить на которую ты постоянно советовал, в комментах к новостям об уязвимостях Drupal или WordPress? :)
>> Библиотека разработана создателями CMS TYPO3
> Михаил, это не та ли CMS, переходить на которую ты постоянно
> советовал, в комментах к новостям об уязвимостях Drupal
> или WordPress? :)Та самая. Заметьте, советы обычно были с присказкой вроде "вскакивать приходится раз-два в год, а не каждую неделю".
Из документации PHP:
> file_exists — Проверяет существование указанного файла или каталогаДа и имя функции намекает.
А тут ВНЕЗАПНО читаем
> функция file_exists() определяет MIME-тип по содержимомуЧто-то тут не так)
Не так тут PHP.
вам в пехепе 4. Ну или максимум - 5.2 (который пожалуй и был последним true php)
С тех пор было объявлено что все есть стрим, и "файловые" операции внезапно начали делать странное, если имя файла начиналось на someshit://
Правда, для большинства этого шита доступны только самые примитивные операции, да еще и требуются явные разрешения или установка extension, а вот phar настолько прекрасен, что косплеит файловую систему целиком и включен из коробки (можно, конечно, выключить, но по неистребимой тяге разработчиков обмазываться всяким дерьмом, работать ничего кроме хеловротов и не будет).вопрос наличия мозгов у тех кто это придумывал - закрыт еще со времен демарша автора сухосина.
Ерунду не говорите, создание своего стримвроппера в 4.3.2 появилось.
только вот что-то я не слышал о подобных уязвимостях не то что в 4, а и в ранних 5.
Возможно именно потому, что из коробки ничего не работало, поэтому макаки на эти фичи не полагались, а если даже и включали - ничего кроме банальных read/write даже из приснопамятного rar было недоступно.кстати, наличие rar при отсутствии tar как бе намекает нам на то, какая операционная система была на столе у горе-разработчиков этого чудо-язычка.
жаль что в ней их поделка не прижилась, поскольку там и с asp все было хорошо (и как-то он не торопился исполнять что ни попадя при попытке проверить существование файла)
У меня для вас очень плохие новости: уязвимости в glob() существовали безотносительно языка. Однако их удалённая эксплуатация (без наличия у атакующего каких-либо локальных привилегий в системе) возможна опять же только при передаче невалидированного ввода.
> уязвимости в glob()а вот тут список непотребных символов вполне себе конечен (маловероятно появление завтра новых или вообще создания их методом подключения плагина), причем явно определен метод экранирования, и, вообще-то, аналогом этой уязвимости была бы передача не невалидированной строки в glob (во многих случаях вполне допустимая), а исполнение кода при передаче неправильной строки - через срыв стека где-нибудь в недрах regex или чем оно там их раскрывает.
что было бы багом реализации, а не by design.
Вот с чем соглашусь - так это с тем, что вся механика phar - редкостное удолбище. Оно по уму эксплицитно должно быть, через mount_phar($alias, $phar_file) например, который бы включал конкретный файл в конкретный путь phar://<alias>/...
пожалуй что и да - я тут бегло полистал остальные стримы - нигде такой жопищи нет, если назвать кошку rar:// - абсолютно никакого ущерба окружающим она не нанесет, пока не попытаешься ее распаковать (да и тут это баг в конкретном модуле, а не by design)
Вы прочитали неправильно. file_exists не определяет mime-тип.
то есть написано неправильно
file_exists выполняет вначале код контейнера phar.
Лучше бы вы не писали, и не показывали свою собственную безграмотность.Никакого исполняемого кода в контейнере Phar нет, если конечно криворучки - горе-писатели - не пытаются сделать include из пользовательского контента :D Что в современном хипста-мирке - норма жизни, также, как и eval.
Есть возможность инстанциировать имеющиеся объекты и заполнять их проперти / вызывать десериализатор. Вкупе с автолоудерами и кривыми руками объектописателей (особенно горячих любителей eval, за который надо отлучать от кода пожизненно) это может привести и к выполнению произвольного кода.
Если в file_exists не передавать пользовательский ввод без валидации (префикс phar:// в имени файла должен существовать) - ничего само собой случится не может. Криворучкам 100500 раз говорили, что при использовании пользовательского ввода его надо 100% валидировать, но они так и остаются криворучками.
> Криворучкам 100500 раз говорили, что при использовании пользовательского ввода его надо 100% валидироватьно забыли опубликовать Официальные Таблицы Валидных Символов Допустимых для file_exists.
я у вас уже сто раз спрашивал - что не так в моем прекрасном файле phar://cat.jpeg и каков ваш _формальный_ критерий отличать такой файл от допустимых к проверке существования.
Пока что я вижу дыру by design, и неудачные камлания на тему "нет, наш язычок прекрасен, валидируйте лучше"
Нет у меня формального критерия отличать ваш файл. Я его просто априори переименую в то, что валидно для моей файловой системы, и сохраню так, как мне надо - в нужный шард, каталог, etc. А оригинальное имя запишу в книжечку метаданных.---
Весь пост совершенно к другому:
Не делающие 100% валидации инпута - обречены иметь совершенно разнородные грабли, впрочем, туда и дорога.
> Нет у меня формального критерия отличать ваш файл. Я его просто априори
> переименую в то, что валидно для моей файловой системыя вам уже демонстрировал, что для моей файловой системы этот файл совершенно валиден.
Почему я не могу назвать свою кошку phar:// и какие еще имена запретят альтернативно-одаренные разработчики?> так, как мне надо - в нужный шард, каталог, etc. А
> оригинальное имя запишу в книжечку метаданных.то есть будете героически подменять то, что и так прекрасно делает файловая система - наколеночной реализацией, и потом бороться за синхронизацию и последствия ее слета, просто потому что такой вот замысловатый язычок - вместо апи работы с fs подсовывает оверинженеренное нечто.
завтра вам и в апи для метаданных что-нибудь завезут, а чо - прикольно же ж, делая селект из базы сразу же незаметно заполнить пяток объектов. И будете изучать, какие where (например) сегодня годятся, а какие - ни-ни.кстати, надо бы фичреквест оформить - идея хранить куски кода в базе давно не новая, но вручную делать eval результату селекта - каменный век, окаменелое уг битрикса. Надо вот чтоб само сразу делалось!
Можешь называть свою кошку как угодно, поскольку ты даже не увидишь, что на сервисе твой файл назвался просто /shards/uploads/0/1/2/c/b/012cbdzfgp212smnrw2oxubvz.contentsИ нет - это не подмена действий файловой системы. Это называется "организация хранения пользовательских данных" на базе файловой системы. Впрочем, в рамках единого и один раз разработанного класса "хранения" может использоваться S3, SQL/noSQL блобы, и много чего ещё.
Я просто из старых ассемблерщиков, и у меня строка - это не просто набор символов, а набор символов и хранимая/заранее известная длина или вместо неё терминатор в конце, плюс ещё известная заранее кодировка. И файловая система - она, во-первых, не одна, а во-вторых, это не что-то, что "прекрасно делает" всё, что нам заблагорассудится, а сложный код, имеющий свои нюансы и накладывающий свои ограничения.Если делать, как макаки - оно же "прекрасно всё делает" - на винде не сможем в ":". Столкнёмся с лимитами на длину имени файла или уровня вложенности пути в той же винде и не только. Где-то внезапно получим вместо "~" весёлое имя пользователя, под которым наш код запущен. Где-то на экзотике не сможем использовать пробелы или запятые. И т.д., и т.п.
Ну и да, если уж зашли на валидацию - даже самая простейшая (и не менее криворукая) валидация в виде проверки на /\?*: и \0 в именах файлов здесь нормально зайдёт. : потому, что иначе огребёте проблем под виндой.
А ты знаешь список всех функций где доступен этот API?
Считаем "с запасом", что везде, где идут обращения к файлам, сокетам, etc. Но дело не в этом.Понимаешь, я уже 100500 раз писал - мне не нужно знать этот список, у меня однозначно невалидированный пользовательский ввод в вызовы Stream API не может попасть никак, от слова "совсем".
Ну и дополню...ДА! Мы не можем 100% валидировать имена пользовательских файлов. Представляете? Никак! Сегодня это ://, вчера ? с *, завтра - ещё что-нибудь.
Золотое правило: не можешь валидировать и доверять - не используй в системных вызовах. Нельзя невалидируемый ввод использовать в таковых. Совсем. Не понимающие этого - обречены иметь дыры каждый день, что и наблюдаем.
https://github.com/nbs-system/snuffleupagus- Close to zero performance impact
- Powerful yet simple to write virtual-patching rules
- Killing several classes of vulnerabilities
* Unserialize-based code execution
* mail-based code execution
* Cookie-stealing XSS
* File-upload based code execution
* Weak PRNG
* XXE
- Several hardening features
* Automatic secure and samesite flag for cookies
* Bundled set of rules to detect post-compromissions behaviours
* Global strict mode and type-juggling prevention
* Whitelisting of stream wrappers
* Preventing writeable files execution
* Whitelist/blacklist for eval
* Enforcing TLS certificate validation when using curl
* Request dumping capability
- A relatively sane codebase:
* A comprehensive testsuite
* Every commit is tested on several distributions
* An clang-format-enfored code style
* A comprehensive documentation
* Usage of coverity
очередное "щас мы всем покажем как правильно кодить"и пофиг что половина списка ненужного ненужно ломает работающее к чертям, а где не ломает - там была не нужна.
особенно вот это прекрасно:
Enforcing TLS certificate validation when using curlдайте угадаю - еще и неотключаемая глупость.
Хосспаде, долбодятлы.Внезапно отсутствие валидации передаваемых имён и передача пользовательских данных в системные вызовы (в данном случае Stream API) без валидации. За эти два греха надо отлучать от доступа к коду навсегда.
Школота опять страдает - какой плохой пых, не защищает школоту от собственных кривых рук, палящих по ногам из ПТРД.
Они бы ещё на голых сях писать попробовали... =8O
> Они бы ещё на голых сях писать попробовали... =8Oя весь внимание - расскажите, как банальным вызовом stat() или _любым_ способом обработанным его значением или побочными эффектами (он целый errno побочно эффектит) выполнить чужой код?
Или балабол?
В glibc очень долго можно было это потенциально сделать вызовом glob() с необработанными данными.
Ну и да: чужой код не выполняет и PHP Stream API с phar://, представляешь себе?
Он выполняет только имеющийся на стороне сервера код. А все "побочные эффекты" - опять в коде у криворучек.
Придумают же костылей... pharы какие-то... хорошо что я ПХП уже лет 10 не трогал ) За всё это время, похоже, появилось много новых сущностей, а проблемы так и остались.
Держи в курсе, что ты там еще не трогал