Подготовленный оператор может представлять только полный литерал данных. Не является частью литерального, не сложного выражения или идентификатора. Но только строка или номер. Итак, очень распространенная ошибка - это такой запрос:
$sql = "SELECT * FROM t WHERE column LIKE '%?%'";
Если вы немного поразмышляете над этим вопросом, вы поймете, что, находясь внутри одинарных кавычек, вопросительный знак становится буквальным вопросительным знаком , без особого значения для подготовленных заявлений.
Итак, нужно отправить полный строковый литерал с помощью подготовленного оператора. Существует два возможных способа:
$name = "%$name%";
$stm = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stm->execute(array($name));
$data = $stm->fetchAll();
$sql = "SELECT * FROM t WHERE column LIKE concat('%',?,'%')";
, хотя последнее кажется слишком раздутым.
Самый легкий путь к универсальному "приложению PHP, работающему на сервере Apache, что Вы можете или не можете полностью управлять" ситуацией, состоит в том, чтобы поместить Ваш, включает в каталог, и запретите доступа к тому каталогу в Вашем .htaccess файле. Для избавления людей от необходимости Гуглить, если Вы используете Apache, помещает это в файл, названный ".htaccess" в каталоге, Вы не хотите быть доступными:
Deny from all
, Если Вы на самом деле имеете полный контроль над сервером (более характерный в эти дни даже для небольших приложений чем тогда, когда я сначала записал этот ответ), лучший подход должен засунуть файлы, которые Вы хотите защитить за пределами каталога, от которого служит Ваш веб-сервер. Таким образом, если Ваше приложение находится в /srv/YourApp/
, установите сервер, чтобы служить файлам от /srv/YourApp/app/
и поместить включать в /srv/YourApp/includes
, таким образом, буквально нет никакого URL, который может получить доступ к ним.
Помимо .htaccess пути, я видел полезный шаблон в различных платформах, например, в рубине на направляющих. У них есть отдельный паб / каталог в каталоге корневого каталога приложения, и каталоги библиотеки живут в каталогах в тот же уровень как паб/. Что-то вроде этого (не идеальный, но Вы получаете идею):
app/
|
+--pub/
|
+--lib/
|
+--conf/
|
+--models/
|
+--views/
|
+--controllers/
Вы настраиваете свой веб-сервер для использования паба / в качестве корня документа. Это предлагает лучшую защиту Вашим сценариям: в то время как они могут достигнуть из корня документа для загрузки необходимых компонентов, невозможно получить доступ к компонентам из Интернета. Другое преимущество помимо безопасности - то, что все находится в одном месте.
Эта установка лучше, чем просто создание регистраций каждого включенного файла, потому что "доступ, не разрешенный" сообщение, является ключом к разгадке взломщиков, и это лучше, чем .htaccess конфигурация, потому что это не базирующийся белый список: при завинчивании расширений файла, это не будет видимо в lib/, conf/и т.д. каталоги.
Самый легкий путь состоит в том, чтобы установить некоторую переменную в файле, который вызовы включают, такой как
$including = true;
Тогда в файле, это включается, проверьте на переменную
if (!$including) exit("direct access not permitted");
На самом деле мой совет состоит в том, чтобы сделать все эти лучшие практики.
if (!defined(INCL_FILE_FOO)) {
header('HTTP/1.0 403 Forbidden');
exit;
}
Таким образом, если файлы становятся неуместными так или иначе (ошибочная операция ftp) они все еще защищены.
Альтернатива (или дополнение) к решению Chuck's должна была бы запретить доступа к файлам, соответствующим определенному шаблону путем помещения чего-то вроде этого в .htaccess файл
<FilesMatch "\.(inc)$">
Order deny,allow
Deny from all
</FilesMatch>
Лучший способ предотвратить прямой доступ к файлам состоит в том, чтобы разместить их за пределами корня документа веб-сервера (обычно, один уровень выше). Можно все еще включать их, но нет никакой возможности кого-то получающего доступ к ним через запрос HTTP.
я обычно иду полностью и помещаю все свои файлы PHP за пределами корня документа кроме файл начальной загрузки - одинокий index.php в корне документа, который начинает направлять весь веб-сайт/приложение.
У меня есть файл, что я должен действовать по-другому, когда он включен по сравнению с тем, когда к нему получают доступ непосредственно (главным образом print()
по сравнению с return()
), Вот некоторый измененный код:
if(count(get_included_files()) ==1) exit("Direct access not permitted.");
получаемый доступ файл всегда является включенным файлом, следовательно == 1.
Добавьте это к странице, что Вы хотите только быть включенными
<?php
if(!defined('MyConst')) {
die('Direct access not permitted');
}
?>
тогда на страницах, которые включают ее, добавляют
<?php
define('MyConst', TRUE);
?>
Сделайте что-то как:
<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
header('HTTP/1.0 403 Forbidden');
exit('Forbidden');
}
?>
Однажды у меня была эта проблема, решенная с помощью:
if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...
, но идеальное решение - разместить файл вне корня документа веб-сервера, как упоминалось в другом ответе.
То, что делает Joomla! - это определение константы в корневом файле и проверка, определена ли она во включенных файлах.
defined('_JEXEC') or die('Restricted access');
или еще
можно держать все файлы вне досягаемости http запроса, размещая их вне каталога webroot, как рекомендует большинство фреймворков, таких как CodeIgniter.
или даже разместив файл .htaccess в папке include и написав правила, вы можете предотвратить прямой доступ.
<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>
поместите приведенный выше код в верхнюю часть вашего включенного php-файла.
ex:
<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
die("<h4>You don't have right permission to access this file directly.</h4>");
}
// do something
?>
Следующий код используется в Flatnux CMS ( http://flatnux.altervista.org ):
if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
header("Location: ../../index.php");
die("...");
}