✅ Смотрим список активных модулей:
# 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 позволяет бороться с SQL-инъекциями (SQL injections), атаками на переполнение буфера, с отправкой спама через некачественно написанные скрипты, с воровством cookie и т.д. В некоторых случаях может вызывать проблемы, поэтому использовать осторожно. Возможно стоит сразу прописать в /etc/php5/apache2/conf.d/suhosin.ini значение suhosin.get.max_value_length = 4096
Если требуется передавать параметры suhosin через .htaccess то надо сделать следующее:
suhosin.perdir = "p"
AllowOverride All
suhosin.post.max_vars = 2048 suhosin.request.max_vars = 2048
Проверяем все места со скриптами - нигде не должно валяться беспризорных php-файлов. В особенности всяких шеллов, приблуд типа phpmyadmin и т.д. Если что-то подобное используется - в отдельную папку с хитрым именем, на папку пароль и закрыть ей листинг из апача.
В некоторых случаях требуется запретить использование некоторых функций через 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.
Итак, делаем:
disable_functions =
suhosin.executor.func.blacklist = "exec,system,passthru,shell_exec,proc_open"
php_admin_value suhosin.executor.func.blacklist "system, passthru, shell_exec, proc_open"
Отсюда: http://habrahabr.ru/post/188878/
# find . -type f -name '*.php' -mtime -7
#!/bin/sh $files_path = "/root/bin/data" $search_path = "/var/www/site/" $mail_to = "[email protected]" 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