From 1cddeb0c03cfae2688bd0560c9ce8b81ea085cc1 Mon Sep 17 00:00:00 2001 From: miramir Date: Sun, 10 May 2015 21:39:24 +0500 Subject: [PATCH] Translate security best practice to russian --- docs/guide-ru/README.md | 2 +- docs/guide-ru/security-best-practices.md | 178 +++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 docs/guide-ru/security-best-practices.md diff --git a/docs/guide-ru/README.md b/docs/guide-ru/README.md index 3a9e94eda2..78b8afe485 100644 --- a/docs/guide-ru/README.md +++ b/docs/guide-ru/README.md @@ -111,7 +111,7 @@ All Rights Reserved. * **TBD** [Авторизация](security-authorization.md) * **TBD** [Работа с паролями](security-passwords.md) * **TBD** [Клиенты авторизации](security-auth-clients.md) -* **TBD** [Лучшие практики](security-best-practices.md) +* [Лучшие практики](security-best-practices.md) Кеширование diff --git a/docs/guide-ru/security-best-practices.md b/docs/guide-ru/security-best-practices.md new file mode 100644 index 0000000000..0f95ab6bec --- /dev/null +++ b/docs/guide-ru/security-best-practices.md @@ -0,0 +1,178 @@ +Лучшие практики безопасности +============================ + +Ниже мы рассмотрим основные принципы безопасности и опишем, как избежать угроз при разработке на Yii. + +Основные принципы +----------------- + +Есть два основных принципа безопасности, независимо от того какое приложение разрабатывается: + +1. Фильтрация ввода. +2. Экранирование вывода. + + +### Фильтрация ввода + +Фильтрация ввода означает, что входные данные никогда не должны считаться безопасными и вы всегда должны проверять +являются ли полученные данные допустимыми. Например, если мы знаем, что сортировка может быть осуществлена только +по трём полям `title`, `created_at` и `status`, и поле может передаваться через ввод пользователем, лучше проверить +значение там где мы его получили: + +```php +$sortBy = $_GET['sort']; +if (!in_array($sortBy, ['title', 'created_at', 'status'])) { + throw new Exception('Invalid sort value.'); +} +``` + +В Yii, вы скорее всего будете использовать [валидацию форм](input-validation.md), чтоб делать такие проверки. + + +### Экранирование вывода + +Экранирование вывода означает, что данные в зависимости от контекста должны экранироваться, например в контексте +HTML вы должны экранировать `<`, `>` и похожие специальные символы. В контексте JavaScript или SQL будет другой набор +символов. Так как ручное экранирование черевато ошибками Yii предоставляет различные утилиты для экранирования в +различных контекстах. + +Как избежать SQL-иньекций +------------------------- + +SQL-иньекции происходят когда текст запроса формируется склеивание неэкранированных строк, как показано ниже: + +```php +$username = $_GET['username']; +$sql = "SELECT * FROM user WHERE username = '$username'"; +``` + +Вместо того, чтобы подставлять корректное имя пользователя злоумышленик может передать вам в приложение что-то вроде +`'; DROP TABLE user; --`. +В результате SQL будет следующий: + +```sql +SELECT * FROM user WHERE username = ''; DROP TABLE user; --' +``` + +Это валидный запрос, который будет искать пользователей с пустым именем, а затем удалит таблицу `user`, скорее всего +сломается приложение и будут потеряны данные (вы ведь делаете регулярное резервное копирование?). + +Большинство запросов к базе данных в Yii происходит через [Active Record](db-active-record.md), который правильно +использует подготовленные запросы PDO внутри. При использовании подготовленных запросов невозможно манипулировать +запросом как это показано ниже. + +Тем не менее, иногда нужны [сырые запросы](db-dao.md) или [построитель запросов](db-query-builder.md). В этом случае +вы должны использовать безопасные способы передачи данных. Если данные используются значения столбцов предпочтительнее +использовать подготовленные запросы: + +```php +// query builder +$userIDs = (new Query()) + ->select('id') + ->from('user') + ->where('status=:status', [':status' => $status]) + ->all(); + +// DAO +$userIDs = $connection + ->createCommand('SELECT id FROM user where status=:status') + ->bindValues([':status' => $status]) + ->queryColumn(); +``` + +Если данные используются в качестве имён столбцов или таблиц, то лучший путь это разрешить только предопределённый набор +значений: + +```php +function actionList($orderBy = null) +{ + if (!in_array($orderBy, ['name', 'status'])) { + throw new BadRequestHttpException('Only name and status are allowed to order by.') + } + + // ... +} +``` + +Если это невозможно, то имена столбцов и таблиц должны экранироваться. Yii использует специальный синтаксис +для экранирования для всех поддерживаемых баз данных: + +```php +$sql = "SELECT COUNT([[$column]]) FROM {{table}}"; +$rowCount = $connection->createCommand($sql)->queryScalar(); +``` + +Вы можете получить подробную информацию о синтаксисе в [Экранирование имён таблиц и столбцов](db-dao.md#quoting-table-and-column-names). + + +Как избежать XSS +---------------- + +XSS или крос-сайтинговый скриптинг становится возможен когда не экранированный выходной HTML попадает в браузер. +Например, если пользователь может ввести свой имя и вместо `Alexander` он вводит ``, то +все страницы которые его выводят без экранирования будут выполнять JavaScript `alert('Hello!');` и в результате +будет выводится окно сообщения в браузере. В зависимости от вебсайта вместо невинных скриптов с сообщениями могут быть +отправлены сообщения используя ваше имя или даже выполнять банковские операции. + +В Yii избежать XSS легко. В основном есть два варианта: + +1. Вы хотите вывести данные в виде обычного текста. +2. Вы хотите вывести данные в виде HTML. + +Если вам нужно вывести простой текст, то екранировать лучше следующим образом: + +```php + +``` + +Если нужно вывести HTML вам лучше воспользоваться HtmlPurifier: + +```php + +``` + +Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, так что неплохо бы задуматься о кешировании. + +Как избежать CSRF +----------------- + +CSRF это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают +что запросы приходящие от браузера отправляются самим пользователем. Это может быть неправдой. + +Например, сайт `an.example.com` имеет URL `/logout`, который используя простой GET, разлогинивает пользователя. Пока +это запрос выполняется самим пользователем всё в порядке, но в один прекрасный день злоумышленники размещают код +`` на форуме с большой посещаемостью. Браузер не делает никаких отличий +между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом `img`, он +разлогинится с сайта `an.example.com`. + +Вот основная идея. Можно сказать, что в разлогировании пользователя нет ничего серъёзного, но отправить POST не намного +сложнее. + +Для того чтоб избежать CSRF вы должны всегда: + +1. Следуйте спецификациям HTTP, например запрос GET не должен менять состояние приложения. +2. Держите защиту CSRF в Yii включонной. + + +Как избежать нежелательного доступа к файлам +-------------------------------------------- + +По умолчанию webroot сервера указывает на каталог `web` где лежит `index.php`. В случае виртуального хостинга +это может быть недостижимо, в конечном итоге весь код, конфиги и логи могут оказаться в webroot сервера. + +Если это так, то нужно запретить доступ ко всему кроме директории `web`. Если на вашем хостинге такое невозможно, +рассмотрите возможность смены хостинга. + +Как избежать отладочной информации и утилит в продуктиве +-------------------------------------------------------- + +В режиме отладки Yii отображает довольно подробные ошибки, которые полезны во время разработки. Дело в том, что +подробные ошибки удобны для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части +вашего кода. Никогда не запускайте продуктивное приложение с `YII_DEBUG` установленным в `true` в вашем `index.php`. + +Вы никогда не должны включать Gii на продуктиве. Он может быть использован для получения информации о структуре +базы данных, кода и может быть просто переписан код с помощью генератора Gii. + +Также следует избегат включения на продуктиве панели отладки, если только это деийствительно не необходимо. +Она раскрывает всё приложение и детали конфигурации. Если вам это абсолютно необходимо, проверьте дважды что доступ +ограничен только вашими IP-адресами.