====== Безопасность и PHP ======
===== Чек-лист =====
✅ Смотрим список активных модулей:
# php -m
Отключаем ненужные:
# mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable
✅ Отключаем отображение информации о версии PHP:
expose_php=Off
Это параметр для php.ini.
✅ Отключаем отображение ошибок PHP для посетителей:
display_errors=Off
Вместо этого логируем их отдельно:
log_errors=On
error_log=/var/log/httpd/php_scripts_error.log
✅ Если не нужна загрузка файлов на веб сервер, отключите эту возможность:
file_uploads=Off
Если загрузка нужна, то хотя бы ограничьте максимальный размер файла до необходимого предела:
file_uploads=On
upload_max_filesize=10M
✅ Отключаем функцию allow_url_fopen, если не используются сайтом. Она открывает широкие возможности для взлома, если разработчики забудут о фильтрации входящих данных.
allow_url_fopen=Off
✅ Настройка размера POST запросов. Этот параметр должен быть не меньше upload_max_filesize, если разрешена загрузка файлов. Если же она запрещена, то большой разрешённый размер post запросов не нужен. Вряд ли вам через формы потребуется заливать большой объём данных.
post_max_size=10M
или
post_max_size=10K
✅ Подобрать необходимые лимиты выполнения скриптов. Тут всё сильно зависит от самого сайта. В идеале, много ресурсов не выделять, но, к примеру, тот же Bitrix, требует очень много оперативной памяти и времени выполнения для своих скриптов.
max_execution_time = 30
max_input_time = 30
memory_limit = 64M
✅ Отключаем потенциально опасные функции PHP. Оставляем только то, что реально нужно.
disable_functions = exec,passthru,shell_exec,system,
proc_open,popen,curl_exec,curl_multi_exec,
parse_ini_file,show_source
✅ Убедиться, что параметр cgi.force_redirect не отключен принудительно. По дефолту, если его явно не указать, то он будет включен.
cgi.force_redirect=On
✅ Убедиться, что php работает от отдельного непривилегированного пользователя. Настройка будет зависеть от используемого менеджера процессов php. Проверяем примерно так:
# ps aux | grep php
✅ Ограничиваем доступ php к файловой системе:
open_basedir = "/var/www/html/"
✅ Настраиваем место хранения для сессий:
session.save_path = "/var/lib/php/session"
Важно убедиться, что туда нет доступа посторонним. Кроме веб сервера эта директория никому не нужна. Также туда не должно быть доступа с сайта.
===== Suhosin =====
Suhosin позволяет бороться с SQL-инъекциями (SQL injections), атаками на переполнение буфера, с отправкой спама через некачественно написанные скрипты, с воровством cookie и т.д. В некоторых случаях может вызывать проблемы, поэтому использовать осторожно. Возможно стоит сразу прописать в /etc/php5/apache2/conf.d/suhosin.ini значение suhosin.get.max_value_length = 4096
Если требуется передавать параметры suhosin через .htaccess то надо сделать следующее:
* Изменить в файле /etc/php5/conf.d/suhosin.ini параметр suhosin.perdir на suhosin.perdir = "p"
* Прописать в конфиге Апача для сайта или папки параметр AllowOverride All
* Добавить в .htaccess необходимые параметры, например suhosin.post.max_vars = 2048
suhosin.request.max_vars = 2048
===== Тюним php.ini =====
* Отключаем выполнение некоторых функций:
* disable_function="exec, system, passthru, shell_exec, proc_open"
* Те самые параметры о которых везде понаписано много буковок:
* magic_quotes_gpc = 1
* safe_mode = 0
* register_globals = 0
* Нет, ничего подключать не будем:
* allow_url_fopen = Off
* allow_url_include = Off
* Никому не надо знать что за ошибки возникают, а если нужно - посмотрим логи
* display_errors = Off
* display_startup_errors = Off
* log_errors = On
* error_log = php_error.log
* Запираем php в определенных папках:
* open_basedir=/var/www/you_mega_site.com:/tmp
* Можно спрятать информацию о версии PHP:
* expose_php = Off
===== Чистота - залог покоя =====
Проверяем все места со скриптами - нигде не должно валяться беспризорных php-файлов. В особенности всяких шеллов, приблуд типа phpmyadmin и т.д. Если что-то подобное используется - в отдельную папку с хитрым именем, на папку пароль и закрыть ей листинг из апача.
===== Разрешаем некоторые функции PHP для определенных виртуальных хостов =====
В некоторых случаях требуется запретить использование некоторых функций через disable_functions и сделать индивидуальные настройки для определенных виртуальных хостов. Ан нет, disable_functions работает только из php.ini. Пр попытке включить конструкцию php_admin_value в .htaccess получаем сообщение " php_admin_value not allowed here", а попытки сделать это через конфиги Apache так же не дают эффекта: получаем ошибку "PHP Warning: exec() has been disabled for security reasons in..."
Как оказалось, победить можно, но при условии использования на сервере suhosin. Сборка php5-suhosin 0.9.29-1ubuntu1 старая, я пересобрал руками 0.9.33.
Итак, делаем:
* В php.ini устанавливаем
disable_functions =
* В suhosin.ini (а если такого нет, то в php.ini) запрещаем требуемые функции, например:
suhosin.executor.func.blacklist = "exec,system,passthru,shell_exec,proc_open"
* В настройках виртуального хоста Apache добавляем конструкцию (например, разрешаем exec)
php_admin_value suhosin.executor.func.blacklist "system, passthru, shell_exec, proc_open"
===== Ищем взломанные файлы =====
Отсюда: http://habrahabr.ru/post/188878/
==== Измененные файлы за 7 дней ====
# find . -type f -name '*.php' -mtime -7
==== Подсчет хэш-сумм файлов и поиск измененных ====
#!/bin/sh
$files_path = "/root/bin/data"
$search_path = "/var/www/site/"
$mail_to = "your@mail.ru"
rm $files_path/before.txt
rm $files_path/diff.txt
mv $files_path/current.txt $files_path/before.txt
find $search_path -name "*.php" -type f -print0 | xargs -0 sha1sum > $files_path/current.txt
find $search_path -name "*.js" -type f -print0 | xargs -0 sha1sum >> $files_path/current.txt
find $search_path -name "*.html" -type f -print0 | xargs -0 sha1sum >> $files_path/current.txt
find $search_path -name "*.css" -type f -print0 | xargs -0 sha1sum >> $files_path/current.txt
diff -urN $files_path/before.txt $files_path/current.txt > $files_path/diff.txt
if [ `ls -la $files_path/diff.txt | awk '{print $5}'` -ne 0 ]; then
echo "Files changed!"
mail -s "Files changed!" $mail_to < $files_path/diff.txt
fi
==== Поиск вставок ====
# find . -type f -name '*.php' | xargs grep -l "eval *(" --color
# find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
# find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
# find . -type f -name '*.php' | xargs egrep -i "preg_replace *\((['|\"])(.).*\2[a-z]*e[^\1]*\1 *," --color
==== Сравнить две копии сайта ====
# diff -r copy-clean/ copy-compromised/ -x список_исключений
==== Поиск папок, открытых для записи ====
Ищет директории доступные для записи и php файлы в них. Результат будет сохранен в файл results.txt. Скрипт работает рекурсивно.
#!/bin/bash
search_dir=$(pwd)
writable_dirs=$(find $search_dir -type d -perm 0777)
for dir in $writable_dirs
do
#echo $dir
find $dir -type f -name '*.php'
done
{{tag>php suhosin security безопасность .htaccess expose_php}}