forked from yiisoft/yii2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request yiisoft#8345 from miramir/ru_translate_security_be…
…st_practice Translate security best practice to russian [skip ci]
- Loading branch information
Showing
2 changed files
with
181 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
Лучшие практики безопасности | ||
============================ | ||
|
||
Ниже мы рассмотрим основные принципы безопасности и опишем, как избежать угроз при разработке на 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` он вводит `<script>alert('Hello!');</script>`, то | ||
все страницы, которые его выводят без экранирования, будут выполнять JavaScript `alert('Hello!');`, и в результате | ||
будет выводится окно сообщения в браузере. В зависимости от сайта, вместо невинных скриптов с выводом всплывающего | ||
hello, злоумышленниками могут быть отправлены скрипты, похищающие личные данные пользователей сайта, | ||
либо выполняющие операции от их имени. | ||
|
||
В Yii избежать XSS легко. На месте вывода текста необходими выбрать один из двух вариантов: | ||
|
||
1. Вы хотите вывести данные в виде обычного текста. | ||
2. Вы хотите вывести данные в виде HTML. | ||
|
||
Если вам нужно вывести простой текст, то экранировать лучше следующим образом: | ||
|
||
```php | ||
<?= \yii\helpers\Html::encode($username) ?> | ||
``` | ||
|
||
Если нужно вывести HTML, вам лучше воспользоваться HtmlPurifier: | ||
|
||
```php | ||
<?= \yii\helpers\HtmlPurifier::process($description) ?> | ||
``` | ||
|
||
Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, так что неплохо бы задуматься о кешировании. | ||
|
||
Как избежать CSRF | ||
----------------- | ||
|
||
CSRF - это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают, | ||
что запросы, приходящие от браузера, отправляются самим пользователем. Это может быть неправдой. | ||
|
||
Например, сайт `an.example.com` имеет URL `/logout`, который, используя простой GET, разлогинивает пользователя. Пока | ||
это запрос выполняется самим пользователем - всё в порядке, но в один прекрасный день злоумышленники размещают код | ||
`<img src="http://an.example.com/logout">` на форуме с большой посещаемостью. Браузер не делает никаких отличий | ||
между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом `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-адресами. |