Skip to content

Commit

Permalink
Security_best-practices translated into Russian (#203)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArduanovDanil authored Feb 3, 2024
1 parent f78f3f1 commit 812df2f
Showing 1 changed file with 216 additions and 0 deletions.
216 changes: 216 additions & 0 deletions guide/ru/security/best-practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Лучшие практики безопасности

Ниже мы рассмотрим общие принципы безопасности и опишем, как избежать угроз при разработке приложений с использованием Yii. Большинство из этих принципов не являются уникальными только для Yii, но применимы к разработке веб-сайтов или программного обеспечения в целом, так что вы также найдете ссылки для дальнейшего чтения об общих идеях, лежащих в их основе.

Check notice on line 3 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L3

[Microsoft.SentenceLength] Try to keep sentences short (< 30 words).
Raw output
{"message": "[Microsoft.SentenceLength] Try to keep sentences short (\u003c 30 words).", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 3, "column": 125}}}, "severity": "INFO"}

## Основные принципы

Независимо от того, какое приложение разрабатывается, существуют два основных принципа обеспечения безопасности:

1. Фильтрация ввода.
2. Экранирование вывода.

### Фильтрация ввода

Фильтрация ввода означает, что входные данные никогда не должны считаться безопасными и вы всегда должны проверять, являются ли полученные данные допустимыми.
Например, если мы знаем, что сортировка может быть осуществлена только по трём полям `title`, `created_at` и `status`, и поле может передаваться через ввод пользователем, лучше проверить значение там, где мы его получили.

Check notice on line 15 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L15

[Microsoft.SentenceLength] Try to keep sentences short (< 30 words).
Raw output
{"message": "[Microsoft.SentenceLength] Try to keep sentences short (\u003c 30 words).", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 15, "column": 1}}}, "severity": "INFO"}
С точки зрения чистого PHP, это будет выглядеть следующим образом:

```php
$sortBy = $_GET['sort'];
if (!in_array($sortBy, ['title', 'created_at', 'status'])) {
throw new \InvalidArgumentException('Invalid sort value.');
}
```

В Yii, вы, скорее всего, будете использовать [валидацию форм](../input/validation.md), чтобы делать такие проверки.

Дополнительная информация по теме:

- <https://owasp.org/www-community/vulnerabilities/Improper_Data_Validation>
- <https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html>

### Экранирование вывода

Экранирование вывода означает, что в зависимости от контекста, в котором вы используете данные, вам следует добавить к ними специальные символы, чтобы экранировать их значение.
В контексте HTML вы должны экранировать `<`, `>` и похожие специальные символы.
В контексте JavaScript или SQL это будет другой набор символов.
Так как ручное экранирование чревато ошибками, Yii предоставляет различные утилиты для экранирования в различных контекстах.

Дополнительная информация по теме:

- <https://owasp.org/www-community/attacks/Command_Injection>
- <https://owasp.org/www-community/attacks/Code_Injection>
- <https://owasp.org/www-community/attacks/xss/>

## Как избежать SQL-инъекций

Check notice on line 45 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L45

[Microsoft.Headings] 'Как избежать SQL-инъекций' should use sentence-style capitalization.
Raw output
{"message": "[Microsoft.Headings] 'Как избежать SQL-инъекций' should use sentence-style capitalization.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 45, "column": 4}}}, "severity": "INFO"}

Check warning on line 45 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L45

[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.
Raw output
{"message": "[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 45, "column": 17}}}, "severity": "WARNING"}

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. Скорее всего будет сломано приложение и будут потеряны данные (вы ведь делаете регулярное резервное копирование?).

Убедитесь, что либо вы напрямую используете подготовленные PDO запросы, либо это делает выбранная вами библиотека.

Check notice on line 62 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L62

[Microsoft.Acronyms] 'PDO' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'PDO' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 62, "column": 60}}}, "severity": "INFO"}
В случае подготовленных запросов невозможно манипулированть запросом, как было продемонстрировано выше.

Если вы используете данные для указания имен столбцов или таблиц, лучше всего разрешить только предопределенный набор значений:

```php
function actionList($orderBy = null)
{
if (!in_array($orderBy, ['name', 'status'])) {
throw new \InvalidArgumentException('Only name and status are allowed to order by.');
}

// ...
}
```

Дополнительная информация по теме:

- <https://owasp.org/www-community/attacks/SQL_Injection>

## Как избежать XSS

Check notice on line 82 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L82

[Microsoft.Headings] 'Как избежать XSS' should use sentence-style capitalization.
Raw output
{"message": "[Microsoft.Headings] 'Как избежать XSS' should use sentence-style capitalization.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 82, "column": 4}}}, "severity": "INFO"}

Check warning on line 82 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L82

[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.
Raw output
{"message": "[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 82, "column": 17}}}, "severity": "WARNING"}

XSS или кросс-сайтинговый скриптинг становится возможен, когда неэкранированный выходной HTML попадает в браузер.
Например, если пользователь должен ввести своё имя, но вместо `Alexander` он вводит `<script>alert('Hello!');</script>` то все страницы, которые его выводят без экранирования, будут выполнять JavaScript `alert('Hello!');`, и в результате будет выводиться окно сообщения в браузере.
В зависимости от сайта, вместо невинных скриптов с выводом всплывающего hello, злоумышленниками могут быть отправлены скрипты, похищающие личные данные пользователей сайта, либо выполняющие операции от их имени (например, банковские операции).

В Yii избежать XSS легко. Существует два варианта:

1. Вы хотите вывести данные в виде обычного текста.
2. Вы хотите вывести данные в виде HTML.

Если вам нужно вывести простой текст, то экранировать лучше следующим образом:

```php
<?= \Yiisoft\Html\Html::encode($username) ?>
```

Если нужно вывести HTML, вам лучше воспользоваться [HtmlPurifier](http://htmlpurifier.org/).
Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, поэтому рассмотрите возможность использования кеширования.

Дополнительная информация по теме:

- <https://owasp.org/www-community/attacks/xss/>

## Как избежать CSRF

Check notice on line 106 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L106

[Microsoft.Headings] 'Как избежать CSRF' should use sentence-style capitalization.
Raw output
{"message": "[Microsoft.Headings] 'Как избежать CSRF' should use sentence-style capitalization.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 106, "column": 4}}}, "severity": "INFO"}

Check warning on line 106 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L106

[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.
Raw output
{"message": "[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 106, "column": 17}}}, "severity": "WARNING"}

Check notice on line 106 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L106

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 106, "column": 17}}}, "severity": "INFO"}

CSRF - это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают, что запросы, приходящие от браузера, отправляются самим пользователем. Это может быть неправдой.

Check notice on line 108 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L108

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 108, "column": 1}}}, "severity": "INFO"}

Например, сайт `an.example.com` имеет URL `/logout`, который, используя простой GET, разлогинивает пользователя. Пока это запрос выполняется самим пользователем - всё в порядке, но в один прекрасный день злоумышленники размещают код '<img src="https://an.example.com/logout">' на форуме с большой посещаемостью. Браузер не делает никаких отличий между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом `<img>`, браузер отправит GET-запрос на указанный адрес, и пользователь будет разлогинен с `an.example.com`.

Check warning on line 110 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L110

[Microsoft.GeneralURL] For a general audience, use 'address' rather than 'URL'.
Raw output
{"message": "[Microsoft.GeneralURL] For a general audience, use 'address' rather than 'URL'.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 110, "column": 39}}}, "severity": "WARNING"}

Check notice on line 110 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L110

[Microsoft.SentenceLength] Try to keep sentences short (< 30 words).
Raw output
{"message": "[Microsoft.SentenceLength] Try to keep sentences short (\u003c 30 words).", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 110, "column": 313}}}, "severity": "INFO"}

Вот основная идея того, как работает CSRF-атака.

Check notice on line 112 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L112

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 112, "column": 38}}}, "severity": "INFO"}
Можно сказать, что в разлогинивании пользователя нет ничего серьёзного.
Однако, это был всего лишь пример.

С помощью этого подхода можно сделать гораздо больше опасных вещей.
Например, оплату или изменение данных.
Представьте, что существует страница `http://an.example.com/purse/transfer?to=anotherUser&amount=2000`, обращение к которой с помощью GET-запроса, приводит к перечислению 2000 единиц валюты со счета авторизованного пользователя на счет пользователя с логином `anotherUser`.
Учитывая, что браузер для загрузки контента отправляет GET-запросы, можно подумать, что разрешение на выполнение такой операции только POST-запросом на 100% обезопасит от проблем.
К сожалению, это не спасет вас, так как вместо тега `<img>`, злоумышленник может внедрить JavaScript код, который будет отправлять нужные POST-запросы на этот URL.

Check warning on line 120 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L120

[Microsoft.GeneralURL] For a general audience, use 'address' rather than 'URL'.
Raw output
{"message": "[Microsoft.GeneralURL] For a general audience, use 'address' rather than 'URL'.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 120, "column": 160}}}, "severity": "WARNING"}

По этой причине Yii применяет дополнительные механизмы защиты от CSRF-атак.

Check notice on line 122 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L122

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 122, "column": 66}}}, "severity": "INFO"}

Для того, чтоб избежать CSRF вы должны всегда:

Check notice on line 124 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L124

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 124, "column": 25}}}, "severity": "INFO"}

1. Следовать спецификации HTTP. Например, GET-запрос не должен менять состояние приложения.
Дополнительные сведения см. в [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html)
2. Держите защиту CSRF в Yii включенной.

Check notice on line 128 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L128

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 128, "column": 19}}}, "severity": "INFO"}

Yii имеет защиту от CSRF в middleware `Yiisoft\Yii\Web\Middleware\Csrf`.

Check notice on line 130 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L130

[Microsoft.Acronyms] 'CSRF' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'CSRF' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 130, "column": 21}}}, "severity": "INFO"}
Убедитесь, что он используется в вашем приложении.

Дополнительная информация по теме:

- <https://owasp.org/www-community/attacks/csrf>
- <https://owasp.org/www-community/SameSite>

## Как избежать нежелательного доступа к файлам

По умолчанию, webroot сервера указывает на каталог `public`, где лежит `index.php`.
В случае использования виртуального хостинга, это может быть недостижимо, в конечном итоге весь код, конфиги и логи могут оказаться в webroot сервера.

Если это так, то нужно запретить доступ ко всему, кроме директории `web`.
Если на вашем хостинге такое невозможно, рассмотрите возможность смены хостинга.

## Как избежать вывода отладочной информации и инструментов в боевом окружении

В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Однако, подробные ошибки удобны и для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части вашего кода.

Вы никогда не должны оставлять Debug панель или Gii доступной для всех в боевом окружении. Это может быть использовано для получения информации о структуре базы данных или коде, может позволить заменить файлы, генерируемые Gii автоматически.

Следует избегать включения в боевом окружении панели отладки, если только в этом нет острой необходимости. Она раскрывает всё приложение и детали конфигурации. Если вам всё-таки нужно запустить панель отладки, проверьте дважды, что доступ ограничен только вашими IP-адресами.

Дополнительная информация по теме:

- <https://owasp.org/www-project-.net/articles/Exception_Handling.md>
- <https://owasp.org/www-pdf-archive/OWASP_Top_10_2007.pdf>

## Использование безопасного подключения через TLS

Check warning on line 159 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L159

[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.
Raw output
{"message": "[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 159, "column": 48}}}, "severity": "WARNING"}

Check notice on line 159 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L159

[Microsoft.Acronyms] 'TLS' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'TLS' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 159, "column": 48}}}, "severity": "INFO"}

Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP.
Они могут быть уязвимыми, если ваше соединение скомпрометировано.

Риск снижается, если приложение использует безопасное соединение через TLS (часто называемое как [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security)).

Check notice on line 164 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L164

[Microsoft.Acronyms] 'TLS' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'TLS' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 164, "column": 72}}}, "severity": "INFO"}

Сегодня любой желающий может бесплатно получить SSL-сертификат и автоматически обновлять его благодаря [Let's Encrypt](https://letsencrypt.org/).

Check warning on line 166 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L166

[Microsoft.We] Try to avoid using first-person plural like 'Let's'.
Raw output
{"message": "[Microsoft.We] Try to avoid using first-person plural like 'Let's'.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 166, "column": 105}}}, "severity": "WARNING"}

## Безопасная конфигурация сервера

Цель этого раздела - выявить риски, которые необходимо учитывать при создании конфигурации сервера для обслуживания веб-сайта на основе Yii.
Помимо перечисленных здесь пунктов есть и другие параметры, связанные с безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот раздел как завершенный.

### Как избежать атаки типа `Host`-header

Если веб-сервер настроен на обслуживание одного и того же сайта независимо от значения заголовка `Host`, эта информация может быть ненадежной и [может быть подделана пользователем, отправляющим HTTP-запрос](https://www.acunetix.com/vulnerabilities/web/host-header-attack).
В таких ситуациях вам следует исправить конфигурацию вашего веб-сервера, чтобы он обслуживал сайт только для указанных имен хостов.

Дополнительные сведения о конфигурации сервера смотрите в документации вашего веб-сервера:

- Apache 2: <https://httpd.apache.org/docs/trunk/vhosts/examples.html#defaultallports>
- Nginx: <https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/>

### Настройка проверки SSL-сертификата

Check notice on line 183 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L183

[Microsoft.Headings] 'Настройка проверки SSL-сертификата' should use sentence-style capitalization.
Raw output
{"message": "[Microsoft.Headings] 'Настройка проверки SSL-сертификата' should use sentence-style capitalization.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 183, "column": 5}}}, "severity": "INFO"}

Check warning on line 183 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L183

[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.
Raw output
{"message": "[Microsoft.HeadingAcronyms] Avoid using acronyms in a title or heading.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 183, "column": 24}}}, "severity": "WARNING"}

Существует типичное заблуждение о том, как решить проблемы с проверкой сертификата SSL, например:

```
cURL error 60: SSL certificate problem: unable to get local issuer certificate
```

или

```
stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
```

Многие источники ошибочно предлагают отключить проверку одноранговых соединений SSL.
Этого никогда не следует делать, поскольку это допускает атаки типа «man-in-the-middle».
Вместо этого, PHP должен быть правильно настроен:

1. Скачайте файл [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert.pem).
2. Добавьте в свой php.ini следующее:
```
openssl.cafile="/path/to/cacert.pem"
curl.cainfo="/path/to/cacert.pem".
```

Обратите внимание, что вам следует поддерживать файл в актуальном состоянии.

## Ссылки

- [OWASP top 10](https://owasp.org/Top10/)

Check notice on line 212 in guide/ru/security/best-practices.md

View workflow job for this annotation

GitHub Actions / vale

[vale] guide/ru/security/best-practices.md#L212

[Microsoft.Acronyms] 'OWASP' has no definition.
Raw output
{"message": "[Microsoft.Acronyms] 'OWASP' has no definition.", "location": {"path": "guide/ru/security/best-practices.md", "range": {"start": {"line": 212, "column": 4}}}, "severity": "INFO"}
- [The Basics of Web Application Security](https://martinfowler.com/articles/web-security-basics.html) Мартина Фаулера
- [Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)
- [Раздел "Информационная безопасность" на STackExchange](https://security.stackexchange.com/)

0 comments on commit 812df2f

Please sign in to comment.