Может ли кто-нибудь объяснить модификатор /e regex? - программирование
Подтвердить что ты не робот

Может ли кто-нибудь объяснить модификатор /e regex?

В настоящее время я улучшаю свои знания о дырах в области безопасности в HTML, PHP, JavaScript и т.д. Несколько часов назад я наткнулся на модификатор /e в регулярных выражениях, и я до сих пор не понимаю, как это работает. Я взглянул на документацию, но это не помогло.

Я понял, что этот модификатор можно манипулировать, чтобы дать кому-то возможность выполнить PHP-код (например, preg_replace()). Я видел следующий пример, описывающий дыру в безопасности, но это не объяснялось, так что может кто-нибудь объяснить мне, как вызвать phpinfo() в следующем коде?

$input = htmlentities("");
if (strpos($input, 'bla'))
{
   echo preg_replace("/" .$input ."/", $input ."<img src='".$input.".png'>", "bla");
}
4b9b3361

Ответ 1

Модификатор e Regex в PHP с примером уязвимости и альтернатив

Что e делает с примером...

Модификатор e - это устаревший модификатор регулярных выражений, который позволяет использовать PHP-код в вашем регулярном выражении. Это означает, что все, что вы анализируете, будет оцениваться как часть вашей программы.

Например, мы можем использовать что-то вроде этого:

$input = "Bet you want a BMW.";
echo preg_replace("/([a-z]*)/e", "strtoupper('\\1')", $input);

Это приведет к выходу BET YOU WANT A BMW.

Без модификатора e мы получаем этот отличный результат:

strtoupper('')Bstrtoupper('et')strtoupper('') strtoupper('you')strtoupper('') strtoupper('want')strtoupper('') strtoupper('a')strtoupper('') strtoupper('')Bstrtoupper('')Mstrtoupper('')Wstrtoupper('').strtoupper('')

Потенциальные проблемы безопасности с e...

Модификатор e устарел из соображений безопасности. Вот пример проблемы, с которой вы можете легко справиться с e:

$password = 'secret';
...
$input = $_GET['input'];
echo preg_replace('|^(.*)$|e', '"\1"', $input);

Если я отправлю свой ввод как "$password", вывод этой функции будет secret (demo). Поэтому для меня очень легко получить доступ к переменным сеанса, причем все переменные используются на внутреннем сервере и даже принимают более глубокие уровни контроля над вашим приложением (eval('cat /etc/passwd');?) Через этот простой кусочек плохо написанного кода.

Подобно аналогично устаревшим библиотекам mysql, это не означает, что вы не можете писать код, который не подвержен уязвимости с помощью e, а это сложнее сделать.

Что вы должны использовать вместо этого...

Вы должны использовать preg_replace_callback почти во всех местах, которые вы рассмотрели бы с помощью модификатора e. В этом случае код не так краток, но не позволяйте этому дурачить вас - он в два раза быстрее:

$input = "Bet you want a BMW.";
echo preg_replace_callback(
    "/([a-z]*)/",
    function($matches){
        foreach($matches as $match){
            return strtoupper($match);
        }
    }, 
    $input
);

По производительности нет причин использовать e...

В отличие от библиотек mysql (которые также устарели для целей безопасности), e не быстрее, чем его альтернативы для большинства операций. В приведенном примере он в два раза медленнее: preg_replace_callback (0,14 с для 50 000 операций) vs e modifier ( 0,32 с для 50 000 операций)

Ответ 2

Модификатор e - это модификатор, специфичный для PHP, который запускает PHP для запуска результирующей строки в виде кода PHP. Это в основном eval(), завернутый в механизм регулярных выражений.

eval() сам по себе считается угрозой безопасности и проблемой производительности; обертывание его внутри регулярного выражения значительно усиливает обе эти проблемы.

Поэтому он считается плохой практикой и официально устарел от скоро появляющегося PHP v5.5.

PHP предоставил несколько версий теперь альтернативное решение в виде preg_replace_callback(), которое использует функции обратного вызова вместо использования eval(), Это рекомендуемый метод такого рода вещей.

С учетом кода, который вы указали:

Я не вижу модификатора e в примере кода, который вы указали в вопросе. Он имеет косую черту на каждом конце как разделитель регулярных выражений; e должен быть вне этого, и это не так. Поэтому я не думаю, что код, который вы цитировали, скорее всего будет уязвимым для того, чтобы в него был добавлен модификатор e.

Однако, если $input содержит любые символы /, он будет уязвим для того, чтобы быть полностью сломанным (то есть выбрасывать ошибку из-за недопустимого регулярного выражения). То же самое было бы применимо, если бы у него было что-то еще, что сделало его неправильным регулярным выражением.

Из-за этого неплохо использовать неиспользуемую строку ввода пользователя как часть шаблона регулярного выражения, даже если вы уверены, что его нельзя использовать с помощью модификатора e, есть много других которые могут быть достигнуты с ним.

Ответ 3

Это зло, все, что вам нужно знать: p

В частности, он генерирует заменяющую строку как обычно, но затем запускает ее через eval.

Вместо этого вы должны использовать preg_replace_callback.

Ответ 4

Как поясняется в руководстве, модификатор /e фактически оценивает текст, в котором регулярное выражение работает как PHP-код. Пример, приведенный в руководстве:

$html = preg_replace(
    '(<h([1-6])>(.*?)</h\1>)e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $html
);

Это соответствует любому тексту "<hX>XXXXX</hX>" (т.е. заголовкам HTML-тегов), заменяет этот текст на "<hX>" . strtoupper("XXXXXX") . "<hX>", а затем выполняет "<hX>" . strtoupper("XXXXXX") . "<hX>" как PHP-код, а затем возвращает результат в строка.

Если вы запускаете это при произвольном вводе пользователя, у любого пользователя есть шанс проскользнуть что-то, в котором фактически будет оцениваться как PHP-код. Если он делает это правильно, пользователь может использовать эту возможность для выполнения любого кода, который он хочет. В приведенном выше примере предположите, что на втором этапе текст будет "<hX>" . strtoupper("" . shell('rm -rf /') . "") . "<hX>".