Как безопасно использовать file_get_contents?

Я создаю базовый PHP-источник для папки кода примера моего блога.

<?php if (isset($_GET['file'])) { header('Content-type: text/plain'); $filename = realpath($_GET['file']); if (startsWith($filename, dirname(__FILE__))) { echo file_get_contents($filename); } } function startsWith($haystack, $needle) { $length = strlen($needle); return (substr($haystack, 0, $length) === $needle); } ?> 

Есть ли у меня здесь достаточно, чтобы он никогда не позволял просматривать файл за пределами каталога, в котором находится этот скрипт, или подкаталогов каталога этого скрипта? Я предполагаю, что есть лучшее решение, чем startsWith, для проверки того, является ли путь потомком определенного каталога?

Да, это будет безопасно. Часть realpath – это то, что вам нужно делать, и вы это делаете. Этот код делает то, что он должен просто отлично.

Возможно, вы уменьшите ввод до имени файла (см. Finfo ) и укажите каталог для поиска, если он является одним и тем же каталогом каждый раз, поэтому вам не нужно проверять через startsWith() .

Если вы хотите показать только PHP-исходный код, попробуйте включить * .phps-file-handling в своем веб-сервере. См. https://serverfault.com/questions/62410/apache-htaccess-phps.

В стороне, посмотрите на использование strncmp вместо вашей пользовательской функции startWith.

Если бы я подошел к подобному проекту, я бы:

Используйте комбинацию вашего решения & htaccess, чтобы замаскировать исходное имя файла как имеющее:

http://example.com/viewsource.php?file=./project1/index.php

было бы слишком очевидным и соблазнительным, чтобы с ним связать, используя htaccess, который у вас может быть:

http://example.com/source/project1/index.php

это тоже указывает

h1ddEnfIlEs / ViewSource / index.php? Файл = $ 1 и папка = $ 2

 RewriteRule ^source/([a-z0-9]+)/([a-z0-9]+).php$ h1ddEnfIlEs/viewSourceScript/index.php?file=$2&project=$1 

Затем с помощью средства просмотра источника h1ddEnfIlEs / viewSourceScript / index.php

 <?php if( is_dir('./h1ddEnfIlEs/'.$_GET['project'].'/')===true && is_file('./h1ddEnfIlEs/'.$_GET['project'].'/'.basename($_GET['file'])) ){ highlight_file('./h1ddEnfIlEs/'.$_GET['project'].'/'.basename($_GET['file'])); } ?>