Цементирование сайта
Цементирование сайта — это комплекс технических мер, которые снижают риск взлома, загрузки вредоносных файлов, чтения конфигов, эксплуатации слабого кода и несанкционированного доступа к админке.
Важно понимать, что цементирование не делает сайт неуязвимым. Если в коде есть SQL-инъекция, уязвимый плагин или плохая логика авторизации, это всё равно нужно исправлять. Но hardening резко уменьшает последствия ошибки: злоумышленнику сложнее выполнить PHP-файл, скачать .env, получить дамп базы, прочитать логи или зайти в админку.
1. Базовый принцип: защищаем не только CMS, а весь контур
У сайта есть несколько слоёв:
- Домен и DNS
- SSL / HTTPS
- Хостинг или VPS
- Веб-сервер: Apache / Nginx
- PHP
- База данных
- CMS / фреймворк
- Плагины, модули, темы
- Формы, загрузки файлов, админка
- Бэкапы, логи, доступы
Ошибка многих владельцев сайтов — думать только про CMS. Например: “Я обновил WordPress, значит всё безопасно”. На практике сайт часто ломают не через ядро CMS, а через:
- старый плагин;
- открытую папку uploads;
- backup.zip в корне сайта;
- .env в public_html;
- chmod 777;
- старую версию PHP;
- слабый FTP-пароль;
- тестовый файл разработчика;
- открытую админку без защиты;
- форму загрузки файлов без фильтрации.
OWASP отдельно выделяет загрузку файлов как рискованную часть приложения и рекомендует использовать allowlist расширений, проверку типа файла, переименование, ограничение размера, безопасное хранение и запрет исполнения загруженных файлов как кода.
2. Разница между shared-хостингом и VPS
Shared-хостинг
На обычном шаред-хостинге ты чаще всего можешь управлять:
- файлами сайта;
- .htaccess;
- версией PHP;
- настройками PHP через панель или .user.ini;
- базами данных;
- SSL;
- cron;
- резервными копиями;
- FTP/SFTP-доступами.
Но обычно ты не можешь полноценно управлять:
- системным firewall;
- настройками Nginx/Apache на уровне сервера;
- ModSecurity;
- Fail2Ban;
- PHP-FPM pools;
- системными пользователями;
- глобальными логами;
- пакетами ОС.
Поэтому на shared-хостинге главный упор: .htaccess, права файлов, запрет PHP в uploads, закрытие служебных файлов, обновления CMS, бэкапы, пароли и контроль загруженных файлов.
VPS
На VPS ты уже отвечаешь за всё:
- ОС;
- SSH;
- firewall;
- веб-сервер;
- PHP-FPM;
- базу данных;
- SSL;
- логи;
- бэкапы;
- WAF;
- обновления пакетов;
- права пользователей.
Это даёт больше защиты, но и больше ответственности. Для VPS лучше ориентироваться на системные hardening-подходы: firewall, отдельные пользователи, SSH-ключи, отключение root-login, Fail2Ban, автоматические security updates, WAF и раздельные права на проекты. CIS Benchmarks описывает hardening как набор предписывающих конфигурационных рекомендаций для защиты систем и платформ.
3. Версия PHP — это первое, что нужно проверить
Старый PHP — один из главных рисков. На 6 июня 2026 года официально поддерживаются ветки PHP 8.2, 8.3, 8.4 и 8.5; PHP 8.2 получает security support до 31 декабря 2026, PHP 8.3 — до 31 декабря 2027, PHP 8.4 — до 31 декабря 2028, PHP 8.5 — до 31 декабря 2029.
Для новых проектов лучше целиться в:
PHP 8.3 / 8.4 / 8.5
Для старых CMS иногда приходится оставаться на более старой версии PHP из-за совместимости. Но это временное решение. Если сайт работает только на PHP 7.4 или 8.0, это сигнал: проект нужно обновлять, переписывать старые модули или планировать миграцию.
4. Универсальный чек-лист цементирования для любого сайта
4.1. Убрать всё лишнее из публичной папки
В публичной папке сайта не должно быть:
backup.zip
site.zip
old.zip
dump.sql
database.sql
db.sql
.env
.env.backup
config.php.bak
composer.json
composer.lock
package.json
node_modules/
.git/
.svn/
.idea/
.vscode/
logs/
Публичная папка — это то, что открывается из браузера. На shared-хостинге это обычно:
public_html/
www/
htdocs/
На VPS это может быть:
/var/www/site/public
/var/www/site/public_html
/home/site/web/domain.com/public_html
Бэкапы нужно хранить выше публичной папки:
/home/user/backups/
/var/backups/site/
4.2. Права на файлы и папки
Базовый стандарт:
Папки: 755
Файлы: 644
Конфиги: 600 или 640
Команды для SSH:
find public_html -type d -exec chmod 755 {} \;
find public_html -type f -exec chmod 644 {} \;
Для важных файлов:
chmod 600 .env
chmod 600 configuration.php
chmod 600 wp-config.php
chmod 600 config.php
Плохая практика:
chmod 777
777 можно использовать только в крайних случаях и временно. Если CMS требует 777, чаще всего проблема не в CMS, а в неправильном владельце файлов или настройках PHP/Apache.
4.3. Запрет просмотра директорий
Если в папке нет index.php, пользователь не должен видеть список файлов.
Для Apache в корневом .htaccess:
Options -Indexes
Для Nginx:
autoindex off;
4.4. Закрытие служебных файлов через .htaccess
Файл:
public_html/.htaccess
Базовый вариант:
Options -Indexes
<FilesMatch "^\.">
Require all denied
</FilesMatch>
<FilesMatch "(^#.*#|\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist|old|orig|save)|~)$">
Require all denied
</FilesMatch>
<FilesMatch "^(composer\.(json|lock)|package(-lock)?\.json|yarn\.lock|webpack\.mix\.js|vite\.config\.js|artisan|\.env)$">
Require all denied
</FilesMatch>
RedirectMatch 404 /\.git
RedirectMatch 404 /\.svn
RedirectMatch 404 /node_modules
RedirectMatch 404 /vendor
Этот блок не заменяет правильную структуру проекта, но закрывает типовые ошибки.
4.5. Запрет выполнения PHP в uploads
Это один из самых важных пунктов.
Папки загрузок:
/uploads/
/upload/
/files/
/media/
/images/
/wp-content/uploads/
/sites/default/files/
/assets/
/storage/app/public/
Внутри каждой такой папки для Apache нужно положить .htaccess:
Options -Indexes
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar|cgi|pl|py|sh|shtml)$">
Require all denied
</FilesMatch>
RemoveHandler .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
RemoveType .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
Смысл: даже если через слабую форму кто-то загрузит файл с опасным расширением, сервер не должен выполнить его как код.
Для Nginx на VPS аналогично:
location ~* ^/(uploads|upload|files|media|images|wp-content/uploads|assets)/.*\.(php|phtml|phar|cgi|pl|py|sh)$ {
deny all;
}
4.6. Безопасная загрузка файлов
Разрешай только то, что действительно нужно бизнесу.
Обычно можно разрешить:
jpg
jpeg
png
webp
pdf
doc
docx
xls
xlsx
Лучше запретить:
php
phtml
phar
js
html
htm
svg
sh
cgi
pl
py
exe
bat
cmd
SVG лучше не принимать от пользователей, если нет отдельной очистки, потому что SVG — это не просто картинка, а XML-формат, который может нести активное содержимое.
Файлы после загрузки лучше переименовывать:
Было:
document.php.jpg
Стало:
a83f9c1d7e2b.jpg
Нельзя доверять только расширению файла. Нужно проверять размер, MIME/type, реальное содержимое, путь сохранения и права доступа. OWASP рекомендует строить защиту загрузок по принципу нескольких слоёв: allowlist, проверка файла, безопасное имя, ограничение размера, хранение вне опасного контекста и защита от исполнения.
4.7. Настройки PHP
На shared-хостинге часто можно создать файл:
.user.ini
Пример:
display_errors = Off
log_errors = On
expose_php = Off
upload_max_filesize = 10M
post_max_size = 12M
max_execution_time = 60
memory_limit = 256M
Если сайт вообще не принимает загрузку файлов:
file_uploads = Off
На VPS настройки обычно лежат в:
/etc/php/8.3/fpm/php.ini
/etc/php/8.3/apache2/php.ini
/etc/php/8.3/fpm/pool.d/site.conf
После правок PHP-FPM:
sudo systemctl reload php8.3-fpm
4.8. Отключить вывод ошибок на экран
На боевом сайте нельзя показывать пользователям:
SQLSTATE...
/home/user/public_html/...
Stack trace...
DB_PASSWORD...
APP_KEY...
Правильно:
display_errors = Off
log_errors = On
Для Laravel:
APP_ENV=production
APP_DEBUG=false
Laravel прямо указывает, что APP_DEBUG в production должен быть false, иначе можно раскрыть чувствительные конфигурационные значения пользователям.
4.9. HTTPS и редирект
На Apache:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
HSTS включай только если уверен, что сайт и поддомены корректно работают по HTTPS:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>
Для Nginx:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
4.10. Security headers
Для Apache:
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
Для Nginx:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
OWASP Secure Headers Project описывает HTTP security headers как дополнительный слой защиты, который помогает браузеру ограничивать часть легко предотвращаемых рисков.
5. Цементирование на shared-хостинге
На shared-хостинге делай так:
Шаг 1. Проверить версию PHP
В панели хостинга:
- PHP Selector
- MultiPHP Manager
- Настройки PHP
- Версия PHP
Выбери актуальную совместимую версию. Для старых сайтов сначала тестируй на копии.
Шаг 2. Проверить публичные файлы
Открой в браузере:
site.kz/.env
site.kz/composer.json
site.kz/composer.lock
site.kz/backup.zip
site.kz/database.sql
site.kz/.git/config
site.kz/wp-config.php
site.kz/configuration.php
Нормальный результат:
403 Forbidden
404 Not Found
Плохой результат — если файл скачивается или открывается.
Шаг 3. Поставить .htaccess в корень
Используй универсальный блок из раздела выше.
Шаг 4. Поставить .htaccess в папки загрузок
Особенно:
/wp-content/uploads/
/upload/
/uploads/
/assets/
/media/
/files/
/images/
Шаг 5. Проверить права
В файловом менеджере хостинга:
Папки: 755
Файлы: 644
Конфиги: 600/640
Шаг 6. Отключить FTP, если есть SFTP
FTP передаёт данные менее безопасно. Лучше использовать SFTP/SSH, если хостинг позволяет.
Шаг 7. Сделать отдельные доступы
Нельзя давать всем один логин от хостинга. Для разработчика, SEO-специалиста, контент-менеджера и подрядчика — разные доступы, если панель позволяет.
Шаг 8. Бэкапы вне public_html
Если хостинг создаёт архив в корне сайта, сразу скачай и удали его из публичной папки.
6. Цементирование на VPS
На VPS схема жёстче.
6.1. Обновить систему
Ubuntu/Debian:
sudo apt update
sudo apt upgrade -y
6.2. Создать отдельного пользователя
adduser deploy
usermod -aG sudo deploy
Не работай постоянно под root.
6.3. SSH-защита
Файл:
/etc/ssh/sshd_config
Минимально:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
После правки:
sudo systemctl reload ssh
Важный момент: перед отключением паролей проверь, что вход по SSH-ключу точно работает.
6.4. Firewall через UFW
Ubuntu описывает ufw как пользовательский способ управлять firewall-правилами для IPv4/IPv6.
Базовый набор:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
6.5. Fail2Ban
Fail2Ban следит за логами и может блокировать IP-адреса при повторяющихся неудачных попытках входа; это полезно против перебора паролей и автоматических атак на SSH/админки.
Установка:
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Базовая проверка:
sudo fail2ban-client status
6.6. WAF / ModSecurity / OWASP CRS
На VPS можно поставить ModSecurity + OWASP Core Rule Set. OWASP CRS — это набор универсальных правил для WAF, предназначенный для обнаружения типовых атак на веб-приложения, включая категории вроде SQL Injection, XSS и Local File Inclusion.
Но включать WAF лучше поэтапно:
- Сначала detection/logging mode.
- Проверить ложные срабатывания.
- Настроить исключения под CMS.
- Потом включать blocking mode.
Иначе можно случайно сломать админку, оплату, фильтры каталога, формы или API.
7. WordPress цементирование
WordPress — самая популярная CMS, поэтому её постоянно сканируют боты. Официальный WordPress hardening guide подчёркивает, что безопасность требует базовых мер: обновлений, контроля доступа, правильной настройки файлов и снижения поверхности атаки.
7.1. Что обновить
- ядро WordPress;
- плагины;
- темы;
- переводы;
- PHP;
- серверные пакеты, если VPS.
Удаляй всё неиспользуемое:
- старые темы;
- отключённые плагины;
- тестовые плагины;
- nulled-темы;
- nulled-плагины.
Nulled-темы и плагины — один из частых источников заражения.
7.2. Защита wp-config.php
Права:
chmod 600 wp-config.php
В .htaccess:
<Files wp-config.php>
Require all denied
</Files>
7.3. Запрет редактирования файлов из админки
В wp-config.php:
define('DISALLOW_FILE_EDIT', true);
Более жёсткий вариант:
define('DISALLOW_FILE_MODS', true);
Но второй вариант отключит установку и обновление плагинов/тем через админку. Используй только если процесс обновлений идёт через Git/SSH.
7.4. Защита uploads
Файл:
wp-content/uploads/.htaccess
Содержимое:
Options -Indexes
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar|cgi|pl|py|sh|shtml)$">
Require all denied
</FilesMatch>
RemoveHandler .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
RemoveType .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
7.5. Админка
Минимум:
- не использовать логин admin;
- включить 2FA;
- ограничить попытки входа;
- поставить сложные пароли;
- отключить старых пользователей;
- не давать администратора контент-менеджеру;
- закрыть /wp-admin по IP или Basic Auth, если это корпоративный сайт.
Для Basic Auth на Apache:
7.6. XML-RPC
Если не используешь мобильное приложение, Jetpack или внешние интеграции, можно ограничить xmlrpc.php.
<Files xmlrpc.php>
Require all denied
</Files>
Но сначала проверь, не завязаны ли на него интеграции.
8. Bitrix / 1C-Bitrix: цементирование
У Bitrix часто проблема не только в CMS, а в тяжёлой инфраструктуре, старых модулях, кастомном коде, открытой админке и папке /upload/.
Для Bitrix-семейства важно использовать встроенные инструменты безопасности. Bitrix24 Helpdesk описывает proactive protection как встроенный WAF, который блокирует распространённые веб-атаки.
8.1. Что проверить в первую очередь
- версия ядра;
- обновления модулей;
- Marketplace-модули;
- кастомные компоненты;
- права на /upload/;
- открытость /bitrix/admin/;
- наличие старых backup-архивов;
- тестовые файлы разработчиков;
- дампы базы в корне сайта.
8.2. Папка upload
Для Apache:
/upload/.htaccess
Options -Indexes
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar|cgi|pl|py|sh|shtml)$">
Require all denied
</FilesMatch>
RemoveHandler .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
RemoveType .php .php3 .php4 .php5 .php7 .php8 .phtml .phar
На Bitrix это особенно важно, потому что /upload/ часто содержит пользовательские файлы, картинки, документы, временные выгрузки и импортированные материалы.
8.3. Админка
Админка /bitrix/admin/
Что сделать:
- сложный пароль;
- 2FA, если доступно;
- отдельные роли;
- не давать всем полный административный доступ;
- закрыть по IP, если админка нужна только офису;
- дополнительно закрыть Basic Auth.
8.4. Убрать опасные файлы
Проверить:
/bitrixsetup.php
/restore.php
/backup/
/upload/backup/
/local/backup/
/dump.sql
/site.zip
/old.zip
После установки и восстановления такие файлы не должны оставаться публично доступными.
8.5. На VPS
Для Bitrix на VPS лучше:
- отдельный пользователь под сайт;
- отдельный PHP-FPM pool;
- OPcache;
- HTTPS;
- firewall;
- Fail2Ban;
- WAF;
- регулярные бэкапы;
- мониторинг места на диске;
- мониторинг логов PHP и веб-сервера.
9. Joomla цементирование
Joomla в официальном Security Checklist рекомендует устанавливать официальные версии, менять стандартного администратора, защищать директории и файлы, а также корректно настраивать права.
9.1. Обновления
Проверить:
- Joomla core;
- расширения;
- шаблоны;
- языковые пакеты;
- сторонние компоненты;
- старые отключённые расширения.
Удалить всё, что не используется.
9.2. configuration.php
Файл:
configuration.php
Права:
chmod 600 configuration.php
В .htaccess:
<Files configuration.php>
Require all denied
</Files>
9.3. Админка
Админка Joomla: /administrator/
Защита:
- 2FA;
- сложные пароли;
- не использовать стандартные логины;
- ограничить попытки входа;
- закрыть /administrator/ по IP или Basic Auth.
Joomla в пользовательском security guide также рекомендует использовать security extensions, в том числе для ограничения попыток входа в административную часть.
9.4. Папки загрузок
Типовые папки:
/images/
/media/
/tmp/
/logs/
tmp и logs лучше выносить за пределы публичной директории, если хостинг позволяет. В папках с изображениями запретить PHP.
9.5. Права
Папки: 755
Файлы: 644
configuration.php: 600
10. Drupal: цементирование
Drupal официально ведёт раздел “Securing your site” и подчёркивает, что безопасность — это постоянный процесс: нужно обновлять код Drupal и инфраструктуру, а не один раз настроить сайт и забыть.
10.1. Обновления
Проверить:
- Drupal core;
- contributed modules;
- themes;
- composer dependencies;
- PHP;
- Drush;
- серверные пакеты.
Drupal рекомендует включить Update Manager и настроить уведомления о доступных обновлениях на реальный email.
10.2. settings.php
Файл:
sites/default/settings.php
Права:
chmod 440 sites/default/settings.php
Или, если хостинг не позволяет:
chmod 400 sites/default/settings.php
10.3. files directory
Публичные файлы обычно:
sites/default/files/
Там должен быть .htaccess, который Drupal обычно создаёт сам. Но нужно проверить, что PHP там не выполняется.
Дополнительно можно поставить:
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar)$">
Require all denied
</FilesMatch>
10.4. Private files
Для документов, которые не должны открываться напрямую, используй private files directory вне webroot:
/home/user/private_files
А не:
public_html/sites/default/files/private
10.5. Trusted host settings
В settings.php укажи разрешённые домены:
$settings['trusted_host_patterns'] = [
'^example\.kz$',
'^www\.example\.kz$',
];
Это снижает риски, связанные с неправильным Host header.
11. MODX Revolution: цементирование
MODX официально выделяет четыре главных направления hardening: защитить core, защитить manager, поставить firewall/WAF и обновлять сервер, MODX и Extras.
11.1. Защитить core
Папка /core/
Она не должна быть доступна из браузера.
Для Apache:
RewriteRule ^core/ - [F,L]
RewriteRule ^config.core.php - [F,L]
Более скрытый вариант — отдавать 404:
RewriteRule ^(core|config.core.php) /index.php?q=doesnotexist [L,R=404]
MODX в документации прямо указывает, что core нужно блокировать от публичного доступа.
11.2. Защитить manager
Стандартный путь: /manager/
Что сделать:
- закрыть по IP;
- добавить Basic Auth;
- переименовать/перенести manager, если проект позволяет;
- включить сложные пароли;
- убрать стандартные логины.
MODX рекомендует защищать Manager, в том числе ограничивать доступ по IP или ставить дополнительную .htaccess-авторизацию.
11.3. Обновления
Обновлять:
- MODX core;
- Extras;
- PHP;
- сервер;
- Composer-зависимости, если используются.
11.4. Assets
Папка /assets/
Там запретить выполнение PHP:
Options -Indexes
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar)$">
Require all denied
</FilesMatch>
12. Laravel цементирование
Laravel нужно деплоить так, чтобы публичной была только папка public. Официальная документация Laravel прямо предупреждает: веб-сервер должен направлять все запросы в public/index.php, а попытка обслуживать приложение из корня проекта может раскрыть чувствительные конфигурационные файлы в интернет.
12.1. Правильная структура
Правильно:
/home/user/project/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
│ └── index.php
├── resources/
├── routes/
├── storage/
├── vendor/
└── .env
Домен должен смотреть сюда:
/home/user/project/public
Неправильно:
/home/user/project
Если домен смотрит в корень Laravel-проекта, могут быть доступны .env, composer.json, storage, vendor и другие чувствительные файлы.
12.2. .env
APP_ENV=production
APP_DEBUG=false
Права:
chmod 600 .env
12.3. Установка зависимостей
На production:
composer install --no-dev --optimize-autoloader
12.4. Кэширование
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
Laravel описывает эти команды как часть production deployment/optimization.
12.5. Права
Писать должны только:
storage/
bootstrap/cache/
Пример:
chmod -R 775 storage bootstrap/cache
Остальной проект не должен быть writable для веб-сервера.
12.6. Защита storage
Если используется:
php artisan storage:link
то публичной становится:
public/storage
Туда нельзя позволять загружать PHP и исполняемые файлы. На Apache:
public/storage/.htaccess
Options -Indexes
<FilesMatch "\.(php|php3|php4|php5|php7|php8|phtml|phar|cgi|pl|py|sh|shtml)$">
Require all denied
</FilesMatch>
13. Готовый универсальный .htaccess для Apache
Можно использовать как базу и адаптировать под CMS:
Options -Indexes
RewriteEngine On
# HTTPS redirect
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Security headers
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
# Deny dotfiles
<FilesMatch "^\.">
Require all denied
</FilesMatch>
# Deny backups, dumps, logs, configs
<FilesMatch "(^#.*#|\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist|old|orig|save)|~)$">
Require all denied
</FilesMatch>
# Deny common project files
<FilesMatch "^(composer\.(json|lock)|package(-lock)?\.json|yarn\.lock|webpack\.mix\.js|vite\.config\.js|artisan|\.env)$">
Require all denied
</FilesMatch>
RedirectMatch 404 /\.git
RedirectMatch 404 /\.svn
RedirectMatch 404 /node_modules
14. Готовый Nginx-блок для VPS
Примерный фрагмент:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.php index.html;
autoindex off;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
location ~ /\.(?!well-known) {
deny all;
}
location ~* \.(bak|config|sql|ini|log|sh|inc|swp|dist|old|orig|save)$ {
deny all;
}
location ~* /(composer\.(json|lock)|package(-lock)?\.json|yarn\.lock|webpack\.mix\.js|vite\.config\.js|artisan|\.env)$ {
deny all;
}
location ~* ^/(uploads|upload|files|media|images|wp-content/uploads|assets|storage)/.*\.(php|phtml|phar|cgi|pl|py|sh)$ {
deny all;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}
Nginx поддерживает добавление произвольных заголовков через модуль ngx_http_headers_module и директиву add_header.
15. База данных
Для каждого сайта — отдельная база и отдельный пользователь.
Минимальные права для обычной работы:
SELECT
INSERT
UPDATE
DELETE
Для миграций и обновлений могут понадобиться:
CREATE
ALTER
DROP
INDEX
Но не нужно держать максимальные права постоянно, если проект этого не требует.
Пароль базы:
- длинный;
- уникальный;
- не совпадает с FTP;
- не совпадает с админкой;
- не отправляется в Telegram/WhatsApp открытым текстом.
16. Бэкапы
Правильная схема:
- Ежедневно: база данных
- Еженедельно: файлы сайта
- Перед обновлением: полный бэкап
- После крупных правок: контрольный бэкап
Хранить:
- вне public_html;
- на отдельном диске;
- в облаке;
- с ограниченным доступом.
Нельзя:
public_html/backup.zip public_html/site-old.zip public_html/db.sql public_html/dump.sql
17. Мониторинг подозрительных файлов
На VPS или shared с SSH:
Новые PHP-файлы за 7 дней
find public_html -type f -name "*.php" -mtime -7
PHP в uploads
find public_html -type f \( -path "*uploads*" -o -path "*upload*" -o -path "*files*" -o -path "*media*" \) \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \)
Архивы и дампы в public_html
find public_html -type f \( -name "*.zip" -o -name "*.rar" -o -name "*.tar" -o -name "*.gz" -o -name "*.sql" \)
Подозрительные недавно изменённые файлы
find public_html -type f -mtime -3
Это не антивирус, но для регулярного контроля очень полезно.
18. Чек-лист для агентства перед запуском сайта
- PHP актуальный и совместимый
- HTTPS включён
- HTTP редиректит на HTTPS
- Нет backup.zip / dump.sql / .env в public_html
- Папки 755
- Файлы 644
- Конфиги 600/640
- Нет chmod 777
- display_errors выключен
- log_errors включён
- uploads не выполняет PHP
- .git закрыт
- composer.json закрыт
- package.json закрыт
- админка защищена
- у всех пользователей свои доступы
- старые плагины удалены
- nulled-решений нет
- бэкап настроен
- восстановление бэкапа проверено
- WAF включён или запланирован
- логирование работает
- формы имеют валидацию и CSRF
- файлы загружаются только по allowlist
19. Главные ошибки, которые нельзя допускать
- Оставлять архив сайта в корне
- Оставлять дамп базы в public_html
- Делать chmod 777 на весь сайт
- Держать APP_DEBUG=true
- Оставлять старые плагины
- Использовать nulled-темы
- Давать всем один FTP
- Работать через обычный FTP вместо SFTP
- Не обновлять PHP
- Не проверять /uploads/
- Не закрывать .env
- Хранить бэкапы в публичной папке
- Давать контент-менеджеру права администратора
- Не делать бэкап перед обновлением
20. Короткая стратегия по каждому типу проекта
Shared-хостинг
- Обновить PHP.
- Закрыть служебные файлы через .htaccess.
- Запретить PHP в uploads.
- Проверить права файлов.
- Удалить бэкапы из public_html.
- Обновить CMS и плагины.
- Защитить админку.
- Настроить бэкапы.
VPS
- Обновить ОС.
- Настроить SSH-ключи.
- Отключить root-login.
- Включить firewall.
- Поставить Fail2Ban.
- Настроить Nginx/Apache.
- Настроить PHP-FPM.
- Разделить пользователей и проекты.
- Подключить WAF.
- Настроить логи и бэкапы.
WordPress
- Обновить ядро, плагины, темы.
- Удалить лишнее.
- Защитить wp-config.php.
- Запретить редактирование файлов.
- Защитить wp-content/uploads.
- Включить 2FA.
Bitrix
- Обновить ядро и модули.
- Проверить /upload/.
- Удалить restore.php, bitrixsetup.php и архивы.
- Защитить /bitrix/admin/.
- Включить встроенные механизмы безопасности.
- Проверить кастомные компоненты.
Joomla
- Обновить Joomla и расширения.
- Защитить configuration.php.
- Защитить /administrator/.
- Проверить /images/, /media/, /tmp/, /logs/.
- Удалить неиспользуемые расширения.
Drupal
- Обновить core/modules/themes.
- Настроить Update Manager.
- Защитить settings.php.
- Проверить sites/default/files.
- Настроить private files.
- Настроить trusted_host_patterns.
MODX Revo
- Закрыть /core/.
- Защитить /manager/.
- Обновить MODX и Extras.
- Защитить /assets/.
- Подключить WAF.
Laravel
- Домен должен смотреть только в /public.
- APP_DEBUG=false.
- .env вне public.
- composer install —no-dev.
- config/cache/route/view cache.
- storage и bootstrap/cache writable, остальное закрыто.
- public/storage не выполняет PHP.
Подведём итоги
Цементирование сайта — это не одна кнопка и не один плагин. Это система: обновления, права, запрет выполнения файлов, закрытые конфиги, защищённая админка, HTTPS, WAF, бэкапы и мониторинг.
Самые важные меры, которые дают максимальный эффект:
- Запретить PHP в uploads.
- Убрать .env, .sql, .zip из public_html.
- Отключить display_errors.
- Обновить PHP и CMS.
- Защитить админку.
- Убрать chmod 777.
- Настроить бэкапы вне сайта.
- На VPS включить firewall, Fail2Ban и WAF.
Если внедрить хотя бы эти пункты, сайт станет намного устойчивее к типовым автоматическим атакам, заражениям через загрузки, утечкам конфигов и ошибкам разработчиков.
