Intereting Posts
Развертывание приложения Symfony2 с Capifony – загрузчик APC по-прежнему использует предыдущий выпуск Zend Framework генерирует уникальную строку Разбивка ссылок на страницы Pagination Как сохранить сеанс Twitter API после регистрации через API Facebook? PHP: перевести POST в простые переменные? Есть ли идиоматический способ получить потенциально неопределенный ключ из массива в PHP? 404 Не найдена ошибка при вызове web-сервисов clickbank Как найти все дочерние строки в MySQL? Как использовать путь $ _GET с файлами-файлами и сохранять их в безопасности? Не удается подключиться к FTP с PHP ftp_connect из localhost Access-Control-Allow-Origin для расширения хрома заменить любой URL-адрес в строке текста, на интерактивные ссылки с php Как использовать «Простой доступ API для доступа к Google» для доступа к информации Календаря Google (PHP)? Почему xdebug не устанавливает соединение с NetBeans? PHP Regex Help для синтаксического анализа строки

Избегайте использования include ($ _ GET )

В основном, я работаю над сайтом уже несколько месяцев, и я собираюсь его открыть. Перед открытием я перехожу к потенциальным проблемам безопасности, и я провел некоторое исследование в Интернете, чтобы узнать, что такое проблемы безопасности cummon в php, я уже знал, как исправить большинство из них, хотя у меня действительно есть проблема с один из них: я хочу избежать использования include($_GET['page']) , я провел некоторое исследование, но не нашел ничего действительно удобного в использовании, хотя есть ли способ, которым я могу просто «защитить» мой код как это?
Вот что я закодировал для предотвращения проблем безопасности:

 if (!isset($_GET['page'])) { echo redirect_tempo(500, 'index.php?page=home'); } elseif ($_GET['page']=="index") { echo redirect_tempo(500, 'index.php?page=home'); } elseif (file_exists($_GET['page'].".php")) { require $_GET['page'].'.php'; } else { echo redirect_tempo(500, 'index.php?page=404'); } 

Обратите внимание, что redirect_temp() – это просто header() .

Достаточно ли этого, могу ли я улучшить его, или мне просто нужно полностью его изменить?

Эта часть опасна:

 elseif (file_exists($_GET['page'].".php")) 

Я могу дать путь "../../../../etc/passwd" (я знаю, это уже старый, но это может быть что угодно), и он будет читать файл (при наличии достаточных разрешений).

Простое исправление может быть:

 elseif (file_exists(basename($_GET['page']) . ".php")) 

Не забудьте также применить одно и то же к реальному require :

 require basename($_GET['page']) . '.php'; 

Вы также можете применить basename() дальше, так что вам не нужно дважды применять функцию

См. Также: basename

Идя с моим комментарием, я бы сделал что-то вроде этого.

 switch($_GET['page']) { case 'index' : redirect_tempo(500, 'index.php?page=home'); break; ........ default : die('NO!'); break; } 

Однако это не лучший способ этого.

Ваш код выглядит хорошо. Но было бы лучше, если бы вы также подтвердили свое значение GET перед использованием. Вы можете проверить, является ли это только числовым или алфавитным или буквенно-цифровым. Это может быть одно слово или несколько слов. Проверьте это согласно вашему требованию.

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

Я бы рекомендовал проверить, что косые черты и точки не находятся в строке (из-за путей, например ../ или / или \ в Windows). И, возможно, даже жесткий код .PHP в конце, чтобы предотвратить доступ к другим типам файлов.

 if (strstr($_GET['page'], ".") || strstr($_GET['page'], "/") || strstr($_GET['page'], "\\") { echo "error"; exit; } include($_GET['page'] .".php"); 

Это будет включать все разрешенные страницы, поэтому $ _GET ['page'] == поиск будет включать search.php, но $ _GET ['page'] == что-то будет включать home.php:]

 $allowed_pages = array('home', 'search', 'signup', 'signin', 'loggedin'); if(in_array($_GET["page"], $allowed_pages)) { $page = $_GET["page"]; } else { $page = "home"; } $page = str_replace('/', '', $page); if(file_exists("page_includes/$page.php")) { include("page_includes/$page.php"); } else { include("page_includes/home.php"); } в $allowed_pages = array('home', 'search', 'signup', 'signin', 'loggedin'); if(in_array($_GET["page"], $allowed_pages)) { $page = $_GET["page"]; } else { $page = "home"; } $page = str_replace('/', '', $page); if(file_exists("page_includes/$page.php")) { include("page_includes/$page.php"); } else { include("page_includes/home.php"); } в $allowed_pages = array('home', 'search', 'signup', 'signin', 'loggedin'); if(in_array($_GET["page"], $allowed_pages)) { $page = $_GET["page"]; } else { $page = "home"; } $page = str_replace('/', '', $page); if(file_exists("page_includes/$page.php")) { include("page_includes/$page.php"); } else { include("page_includes/home.php"); } 

Я бы использовал белый список:

 $all_pages = array( 'index' => 'index.php', 'about' => 'misc/about.php', '404' => '404.php', ... ); function reverse($filename) { /* maps filenames to page names */ return preg_replace('#/pages/(.*).php#', '$1', $filename); } /* add all php files in pages/ directory to $all_pages */ foreach (glob("pages/*.php") as $filename) { $all_pages[reverse($filename)] = $filename; } /* for debugging: make sure this only prints stuffs you want to include */ /* var_dump($all_pages); */ /* the actual check is simple */ $page_name = isset($_GET['page']) ? $_GET['page'] : "index"; $include_name = isset($all_pages[$page_name]) ? $all_pages[$page_name] : "404"; require $include_name; 

Многие из этих ответов забывают об атаках с нулевым байтом . Добавление «.php» для предотвращения таких вещей, как ../../../../../etc/passwd, не будет работать во многих развертываниях. Эта проблема была исправлена ​​только в PHP 5.3.4 .