# Базы данных

CIS Benchmarks (CIS - Center for Internet Security) — это набор рекомендаций и стандартов безопасности информационных систем, разработанный организацией Center for Internet Security. Каждый мануал представляет собой набор наилучших практик и конфигураций для различных операционных систем, устройств и ПО.

Рекомендации по настройке могут различаться в зависимости от типа базы данных (например, PostgreSQL, MySQL, Microsoft SQL Server и т. д.) и версии базы данных. Но общие принципы и рекомендации по настройке обязательно включают в себя:

- Аутентификация и авторизация: права доступа к базе данных должны быть ограничены для каждого пользователя на минимально необходимый уровень, а учетные записи пользователей должны иметь сильные пароли, также по возможности стоит использовать двухфакторную аутентификацию.
- Шифрование: в большинстве СУБД (систем управления базами данных) существуют механизмы встроенного шифрования, которые следует активировать. Помимо этого, необходимо шифровать соединений с базой данных с помощью SSL/TLS.
- Аудит и мониторинг: в базах данных должны быть установлены механизмы мониторинга для отслеживания активности пользователей и обнаружения подозрительных действий, например: создание учетной записи с широкими правами, выполнение очень большого запроса, и т.д. Также рекомендуется проводить регулярный аудит учетных записей на предмет превышения прав.
- Обновления и патчи: регулярно обновляйте базу данных и устанавливайте патчи для закрытия известных уязвимостей.
- Защита от инъекций: применяйте методы предотвращения инъекций, такие как параметризованные запросы и санитаризация входных данных, чтобы предотвратить SQL-инъекции и другие виды атак.
- Реагирование на инциденты безопасности: разработайте план реагирования на инциденты и обучите свой персонал его исполнению в случае возникновения инцидентов.

# Логирование и мониторинг запросов в базах данных

Большинство современных СУБД предоставляют возможность вести журнал запросов, записывая все запросы, поступающие к базе данных. Помимо такого "внутреннего" логирования существуют системы мониторинга баз данных. Они могут непрерывно отслеживать активность баз данных, включая выполняемые запросы, количество обращений и нагрузку на систему. Примеры таких систем — Dynatrace, Datadog.

В данном курсе мы рассмотрим прежде всего возможности логирования внутри баз данных. На основании этих логов можно самостоятельно создавать правила SIEM для выявления несанкционированных или подозрительных операций.

### Мониторинг запросов в PostgreSQL

Для мониторинга запросов в базах данных PostgreSQL можно использовать различные инструменты и методы. Ниже представлено несколько способов:

1. **Журналы PostgreSQL:** PostgreSQL записывает информацию о выполненных запросах в журналы ошибок (`log_error_verbosity`) и журналы запросов (`log_statement`). Вы можете настроить эти параметры в конфигурационном файле PostgreSQL (например, *postgresql.conf*) и перезапустить сервер:
    
    ```
    ```ini
    log_statement = 'all' log_destination = 'stderr' logging_collector = on
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
    
    После настройки PostgreSQL будет записывать все SQL запросы в указанный в log\_destination журнал.
2. **Утилита pg\_stat\_statements:** это встроенный модуль PostgreSQL, который отслеживает статистику выполнения SQL запросов. Вы можете включить его в конфигурационном файле PostgreSQL и перезапустить сервер:
    
    ```
    ```ini
    shared_preload_libraries = 'pg_stat_statements' pg_stat_statements.max = 10000 pg_stat_statements.track = all
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
    
    Затем можно выполнить запросы к представлению `pg_stat_statements` для получения информации о наиболее часто выполняемых запросах, их времени выполнения и других метриках.

Пример SQL запроса для просмотра наиболее часто выполняемых запросов и их времени выполнения с использованием `pg_stat_statements`:

```
```sql
SELECT query, total_time, calls, rows FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Этот запрос покажет 10 наиболее ресурсоемких запросов по времени выполнения, их количество вызовов и количество обработанных строк.

### Настройка логирования в PostgreSQL

Настройки логирования возможно изменить в файле `postgresql.conf`, который обычно располагается в каталоге `postgresql`.

Как это сделать:

1. **Настройте параметры логирования**:
    
    В файле `postgresql.conf` найдите и отредактируйте следующие параметры:
    
    
    - `log_statement = 'all'`: параметр определяет, какие SQL-запросы будут записываться в журнал. Установите его значение на `all`, чтобы записывать все SQL-запросы.
    - `log_connections = on`: параметр указывает, нужно ли записывать информацию о подключениях к базе данных в журнал. Установите его значение на `on`, чтобы записывать информацию о подключениях.
    - `log_disconnections = on`: параметр указывает, нужно ли записывать информацию о отключениях от базы данных в журнал. Установите его значение на `on`, чтобы записывать информацию об отключениях.
    - `log_duration = on`: параметр указывает, нужно ли записывать информацию о продолжительности выполнения SQL-запросов в журнал. Установите его значение на `on`, чтобы записывать информацию о продолжительности выполнения запросов.
2. **Перезапустите PostgreSQL**:
    
    После внесения изменений в файл `postgresql.conf` перезапустите PostgreSQL для применения новых настроек:
    
    `sudo service postgresql restart`

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

<details id="bkmrk-%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-postgre"><summary>Пример файла postgresql.conf</summary>

```
```ini
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------

data_directory = '/var/lib/postgresql/12/main'

#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

listen_addresses = 'localhost'
port = 5432

#------------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#------------------------------------------------------------------------------

shared_buffers = 128MB

#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------

wal_level = replica
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/12/main/archive/%f'

#------------------------------------------------------------------------------
# QUERY TUNING
#------------------------------------------------------------------------------

max_connections = 100
effective_cache_size = 4GB
work_mem = 64MB

#------------------------------------------------------------------------------
# ERROR REPORTING AND LOGGING
#------------------------------------------------------------------------------

log_destination = 'stderr'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d.log'
log_statement = 'all'
log_connections = on
log_disconnections = on
log_duration = on

#------------------------------------------------------------------------------
# SECURITY AND AUTHORIZATION
#------------------------------------------------------------------------------

password_encryption = 'scram-sha-256'

#------------------------------------------------------------------------------
# OTHERS
#------------------------------------------------------------------------------

max_wal_size = 2GB

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

</details>### Типы событий в журнале postgresql.log

Сообщения сервера — информационные сообщения о состоянии сервера, его настройках, запущенных процессах и т. д.:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A00%3A00."><table><tbody><tr><td>2024-03-28 10:00:00.123 UTC \[23345\] LOG: database system is ready to accept connections</td></tr></tbody></table>

</div>Сообщения об ошибках, возникающих во время выполнения запросов, операций и т. д.:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A05%3A00."><table><tbody><tr><td>2024-03-28 10:05:00.456 UTC \[23345\] ERROR: syntax error at or near "SELECT"</td></tr></tbody></table>

</div>Записи о выполняемых SQL-запросах, включая их текст, время выполнения, идентификаторы процессов и т. д.:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A10%3A00."><table><tbody><tr><td>2024-03-28 10:10:00.789 UTC \[23345\] LOG: statement: SELECT \* FROM users;  
2024-03-28 10:00:01.234 UTC \[23345\] LOG: statement: INSERT INTO products (name, price) VALUES ('Product A', 99.99);  
2024-03-28 10:00:02.345 UTC \[23345\] LOG: statement: UPDATE customers SET email = 'new@example.com' WHERE id = 123;</td></tr></tbody></table>

</div>Сообщения о подключениях и отключениях к серверу PostgreSQL:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A15%3A00."><table><tbody><tr><td>2024-03-28 10:15:00.012 UTC \[23345\] LOG: connection received: host=127.0.0.1 port=5432  
2024-03-28 10:20:00.345 UTC \[23345\] LOG: disconnection: session time: 0:05:00</td></tr></tbody></table>

</div>Информация о процессах репликации, восстановлении, синхронизации и т. д., если сервер работает в режиме репликации.

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A25%3A00."><table><tbody><tr><td>2024-03-28 10:25:00.678 UTC \[23345\] LOG: starting streaming replication</td></tr></tbody></table>

</div>Сообщения о сбоях и восстановлении:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A30%3A00."><table><tbody><tr><td>2024-03-28 10:30:00.901 UTC \[23345\] LOG: server process (PID 23345) was terminated by signal 9: Killed  
2024-03-28 10:35:00.234 UTC \[23345\] LOG: database system was interrupted; last known up at 2024-03-28 10:00:00 UTC</td></tr></tbody></table>

</div>Сообщения о процессах архивации и восстановления:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A40%3A00."><table><tbody><tr><td>2024-03-28 10:40:00.567 UTC \[23345\] LOG: starting online backup of database "mydb"  
2024-03-28 10:45:00.890 UTC \[23345\] LOG: restore of database "mydb" from archive completed</td></tr></tbody></table>

</div>Сообщения о настройках и изменениях конфигурации:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A50%3A00."><table><tbody><tr><td>2024-03-28 10:50:00.123 UTC \[23345\] LOG: configuration file "/etc/postgresql.conf" contains changes</td></tr></tbody></table>

</div>Рассмотрим подробнее пример файла журнала `postgresql.log` с включенной опцией `log_statement`, который записывает в лог все SQL-запросы:

<div class="table-scroll" id="bkmrk-2024-03-28-10%3A00%3A00.-1"><table><tbody><tr><td>2024-03-28 10:00:00.123 UTC \[23345\] LOG: statement: SELECT \* FROM users;  
2024-03-28 10:00:01.234 UTC \[23345\] LOG: statement: INSERT INTO products (name, price) VALUES ('Product A', 99.99);  
2024-03-28 10:00:02.345 UTC \[23345\] LOG: statement: UPDATE customers SET email = 'new@example.com' WHERE id = 123;</td></tr></tbody></table>

</div>В этом примере каждая строка в файле журнала представляет собой SQL-запрос, который был выполнен в базе данных. Каждая запись начинается с даты и времени события, за которыми следует идентификатор процесса PostgreSQL (`23345` в данном случае), уровень журналирования (`LOG`), и непосредственно сам SQL-запрос.

- **Дата и время (`2024-03-28 10:00:00.123 UTC`):** метка времени, когда был выполнен SQL-запрос.
- **Идентификатор процесса (`[23345]`):** это уникальный идентификатор процесса PostgreSQL, который выполнял SQL-запрос.
- **Уровень журналирования (`LOG`):** указывает на уровень важности сообщения. В данном случае, это просто информационное сообщение.
- **SQL-запрос (`statement: ...`):** это сам SQL-запрос, который был выполнен. В примере показаны три различных SQL-запроса: выборка (`SELECT`), вставка (`INSERT`) и обновление (`UPDATE`).

### Мониторинг запросов в MongoDB

1. **Профилирование MongoDB:** MongoDB позволяет включить профилирование, чтобы записывать информацию о выполненных запросах. Это делается с помощью команды `db.setProfilingLevel()`.
    
    Пример установки уровня профилирования в MongoDB:
    
    ```
    ```css
    db.setProfilingLevel(1, { slowms: 100 });
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
    
    Значение **1** указывает на включение профилирования. Это означает, что MongoDB будет записывать информацию о каждом выполненном запросе.  
    **{ slowms: 100 }**: это опциональный параметр, который определяет пороговое значение времени выполнения запроса в миллисекундах, после которого запрос считается "медленным". В данном случае запросы, выполняющиеся дольше 100 миллисекунд, будут считаться медленными и будут записываться в профилировочный журнал.
2. **Использование инструментов мониторинга:** для мониторинга MongoDB можно использовать различные инструменты, такие как MongoDB Compass, MongoDB Cloud Manager, MongoDB Ops Manager и другие. Они предоставляют дашборды и отчеты о выполненных запросах и производительности сервера MongoDB.
3. **db.currentOp():** этот метод позволяет просматривать текущие операции в MongoDB, включая выполняемые запросы.

### Просмотр текущих операций в MongoDB

В MongoDB метод `db.currentOp()` используется для получения списка текущих операций, выполняющихся в базе данных. Этот метод полезен для мониторинга текущей активности и идентификации долго выполняющихся операций или блокировок. Пример вывода после использования `db.currentOp()`:

<details id="bkmrk-%D0%A0%D0%B0%D1%81%D0%BA%D1%80%D1%8B%D1%82%D1%8C-%7B-%22inprog%22-"><summary>Раскрыть</summary>

```
```json
{
   "inprog" : [
      {
         "opid" : 6146937,
         "active" : true,
         "secs_running" : 5,
         "op" : "query",
         "ns" : "test.collection",
         "command" : {
            "find" : "collection",
            "filter" : {
               "status" : "active"
            },
            "lsid" : {
               "id" : UUID("50cb6696-739b-4db3-806d-31a4365a4e38")
            },
            "$clusterTime" : {
               "clusterTime" : Timestamp(1632785477, 1),
               "signature" : {
                  "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                  "keyId" : NumberLong(0)
               }
            },
            "originatingCommand" : {
               "find" : "collection",
               "filter" : {
                  "status" : "active"
               },
               "lsid" : {
                  "id" : UUID("50cb6696-739b-4db3-806d-31a4365a4e38")
               },
               "$clusterTime" : {
                  "clusterTime" : Timestamp(1632785477, 1),
                  "signature" : {
                     "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                     "keyId" : NumberLong(0)
                  }
               },
               "...
         },
         "planSummary" : "COLLSCAN",
         "numYields" : 0,
         "locks" : {
            "ReplicationStateTransition" : {
               "acquireCount" : {
                  "w" : NumberLong(1)
               }
            },
            "Global" : {
               "acquireCount" : {
                  "r" : NumberLong(1)
               }
            },
            "Database" : {
               "acquireCount" : {
                  "r" : NumberLong(1)
               }
            },
            "Collection" : {
               "acquireCount" : {
                  "r" : NumberLong(1)
               }
            }
         },
         "responseLength" : 15825718,
         "protocol" : "op_msg",
         "millis" : 5,
         "execStats" : {

         },
         "ts" : ISODate("2021-09-28T14:11:17.631Z"),
         "client" : "127.0.0.1",
         "appName" : "MongoDB Shell",
         "clientMetadata" : {
            "application" : {
               "name" : "MongoDB Shell"
            },
            "driver" : {
               "name" : "MongoDB Internal Client",
               "version" : "4.4.8"
            },
            "os" : {
               "type" : "Linux",
               "name" : "Ubuntu",
               "architecture" : "x86_64",
               "version" : "20.04"
            }
         },
         "numYields" : 0,
         "locks" : {

         },
         "waitingForLock" : false,
         "awaiting_historical_lock" : false,
         "lockStats" : {
            "ReplicationStateTransition" : {
               "timeLockedMicros" : {
                  "r" : NumberLong(0),
                  "w" : NumberLong(87)
               }
            },
            "Global" : {
               "timeLockedMicros" : {
                  "r" : NumberLong(0),
                  "w" : NumberLong(87)
               }
            },
            "Database" : {
               "timeLockedMicros" : {
                  "r" : NumberLong(0),
                  "w" : NumberLong(87)
               }
            },
            "Collection" : {
               "timeLockedMicros" : {
                  "r" : NumberLong(0),
                  "w" : NumberLong(87)
               }
            }
         }
      }
   ],
   "ok" : 1
}
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

</details>В примере приведена информация о текущей операции, выполняющейся в MongoDB. Поля в этом логе:

1. **opid**: Уникальный идентификатор операции (Operation ID).
2. **active**: Показывает, активна ли операция в данный момент.
3. **secs\_running**: Время, в течение которого операция выполняется, в секундах.
4. **op**: Тип операции. В данном случае это `query`, что означает выполнение запроса к базе данных.
5. **ns**: Пространство имен, в котором выполняется операция. В данном случае запрос выполняется в коллекции `test.collection`.
6. **command**: Команда запроса. Здесь показана конкретная команда `find` для поиска документов в коллекции `collection`, которые соответствуют фильтру `{ "status" : "active" }`.
7. **planSummary**: Краткое описание плана выполнения запроса. В данном случае используется коллекционный скан (`COLLSCAN`), что может указывать на то, что индекс не используется для выполнения запроса.
8. **locks**: Информация о блокировках, которые удерживает операция. Здесь показаны различные типы блокировок, включая блокировки на уровне глобального объекта, базы данных и коллекции.
9. **responseLength**: Длина ответа на запрос, в байтах.
10. **client**: IP-адрес или хост, откуда был отправлен запрос.
11. **appName**: Имя приложения, которое инициировало запрос. В данном случае это MongoDB Shell.
12. **clientMetadata**: Дополнительная метаданные о клиенте, включая информацию о драйвере и операционной системе.
13. **waitingForLock**: Показывает, ожидает ли операция блокировку.
14. **awaiting\_historical\_lock**: Показывает, ожидает ли операция историческую блокировку.
15. **lockStats**: Статистика блокировок для операции, включая время, в течение которого различные типы блокировок были удерживаемыми.

### Настройка логирования в MongoDB

В MongoDB настройка логирования осуществляется через файл конфигурации `mongod.conf`.

1. **Настройка параметров логирования**:
    
    В файле `mongod.conf` найдите и отредактируйте параметры, связанные с логированием:
    
    
    - `systemLog.destination`: Укажите тип журнала, который вы хотите использовать. Например, `file` для записи в файл или `syslog` для записи в системный журнал.
    - `systemLog.path`: Укажите путь к файлу журнала, если вы выбрали тип `file`.
    - `systemLog.logAppend`: Если установлено в `true`, новые записи будут добавляться в конец существующего файла журнала. Если установлено в `false`, файл будет перезаписываться при каждом запуске.
    - `systemLog.verbosity`: Укажите уровень журналирования. Например, `0` для минимального уровня (только критические сообщения), `1` для информационных сообщений, `2` для отладочных сообщений и т. д.
2. **Перезапустите MongoDB**:
    
    После внесения изменений в файл `mongod.conf` перезапустите MongoDB для применения новых настроек.
    
    `sudo service mongod restart`

<details id="bkmrk-%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-mongod."><summary>Пример файла mongod.conf</summary>

```
```yaml
# mongod.conf

# Установка каталога данных и журнала
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true

# Установка параметров системного журнала
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
  verbosity: 1

# Установка параметров сети
net:
  port: 27017
  bindIp: 127.0.0.1

# Настройка параметров безопасности
security:
  authorization: enabled

# Другие параметры конфигурации (необязательно)

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

</details>### Логи MongoDB

В логе mongod.log MongoDB записывает различные типы событий, связанных с работой сервера и его окружения.

Основные типы событий, которые могут присутствовать в журнале mongod.log:

**Сообщения о запуске и остановке сервера:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A00%3A00."><table><tbody><tr><td>2024-03-28T12:00:00.000+0000 I CONTROL \[main\] \*\*\*\*\* SERVER RESTARTED \*\*\*\*\*  
2024-03-28T12:00:05.000+0000 I CONTROL \[initandlisten\] MongoDB starting : pid=123 port=27017 ...</td></tr></tbody></table>

</div>- Сообщения об успешном запуске сервера MongoDB.
- Сообщения о завершении работы сервера при выключении.

**Сообщения о подключении и отключении клиентов:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A05%3A23."><table><tbody><tr><td>2024-03-28T12:05:23.000+0000 I NETWORK \[listener\] connection accepted from 192.168.1.100:54321 #1 (1 connection now open)  
2024-03-28T12:05:30.000+0000 I NETWORK \[conn1\] end connection 192.168.1.100:54321 (0 connections now open)</td></tr></tbody></table>

</div>- Информация о новых клиентских подключениях к серверу MongoDB.
- Уведомления об отключении клиентов от сервера.

**Сообщения об аутентификации и авторизации:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A10%3A12."><table><tbody><tr><td>2024-03-28T12:10:12.000+0000 I ACCESS \[conn123\] Successfully authenticated as user1  
2024-03-28T12:10:20.000+0000 I ACCESS \[conn123\] Authentication failed for user2 from IP 192.168.1.101</td></tr></tbody></table>

</div>- Логирование попыток аутентификации пользователей и ролей.
- Уведомления о результате аутентификации (успех или неудача).

**Сообщения о выполнении операций:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A15%3A45."><table><tbody><tr><td>2024-03-28T12:15:45.000+0000 I COMMAND \[conn123\] command mydatabase.collection command: find { find: "collection", filter: {}, ...  
2024-03-28T12:15:50.000+0000 I WRITE \[conn123\] update mydatabase.collection query: { \_id: ObjectId("123") } update: ...</td></tr></tbody></table>

</div>- Логирование различных операций с данными, таких как запросы на чтение и запись, обновление и удаление документов.
- Информация о долго выполняющихся запросах и запросах, требующих индексов.

**Сообщения об ошибках и предупреждениях:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A20%3A00."><table><tbody><tr><td>2024-03-28T12:20:00.000+0000 W STORAGE \[conn123\] Detected unclean shutdown - /data/db/mongod.lock is not empty.  
2024-03-28T12:20:10.000+0000 E STORAGE \[conn123\] WiredTiger error (0) \[111111111\] at &lt;path/to/file&gt;:123, terminating</td></tr></tbody></table>

</div>- Логирование различных видов ошибок, возникающих во время работы сервера MongoDB.
- Предупреждения о потенциальных проблемах и нежелательных событиях.

**Сообщения о репликации и кластеризации:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A25%3A00."><table><tbody><tr><td>2024-03-28T12:25:00.000+0000 I REPL \[rsSync\] Starting initial sync with primary  
2024-03-28T12:25:10.000+0000 I REPL \[rsSync\] Initial sync attempt failed, retrying in 10 seconds</td></tr></tbody></table>

</div>- Информация о состоянии репликации и синхронизации данных между узлами кластера.
- Логирование операций репликации, таких как выборы лидера, перенос данных и т. д.

**Сообщения о резервном копировании и восстановлении:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A30%3A00."><table><tbody><tr><td>2024-03-28T12:30:00.000+0000 I COMMAND \[conn123\] command admin.backup command: backup { backup: "mydatabase" }  
2024-03-28T12:30:05.000+0000 I COMMAND \[conn123\] command admin.restore command: restore { restore: "mydatabase" }</td></tr></tbody></table>

</div>- Информация о процессах резервного копирования и восстановления данных.
- Логирование успешных и неудачных операций резервного копирования и восстановления.

**Сообщения о настройках и изменениях конфигурации:**

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A35%3A00."><table><tbody><tr><td>2024-03-28T12:35:00.000+0000 I CONTROL \[main\] Setting featureCompatibilityVersion to "4.0"  
2024-03-28T12:35:10.000+0000 I STORAGE \[initandlisten\] Detected data files in /data/db created by the 'wiredTiger' storage engine, ...</td></tr></tbody></table>

</div>- Уведомления о изменениях в конфигурационных файлах сервера MongoDB.
- Информация о перезагрузке сервера в связи с изменениями в конфигурации.

# Роли и права пользователей

## В реляционных базах данных

### **Роли пользователей**

**Суперпользователь (Superuser)** — особая роль, которая обладает полными правами на управление базой данных и ее объектами. Суперпользователь может выполнять любые операции с данными, включая создание, изменение и удаление объектов базы данных, а также управление пользователями и их правами.

**Пользователь (User)** — обычный пользователь базы данных, который имеет ограниченные права на выполнение операций с данными. Пользователи могут иметь доступ только к определенным объектам базы данных и выполнять только определенные операции, в зависимости от их назначенных прав доступа.

**Роли безопасности (Security Roles)** — являются наборами прав доступа, которые можно назначить одному или нескольким пользователям. Использование ролей позволяет упростить управление правами доступа и обеспечить согласованность безопасности в системе.

### **Права доступа**

**Права на объекты** — определяют, какие операции разрешены для выполнения с определенными объектами базы данных, такими как таблицы, представления, процедуры и т.д. Типичные права включают SELECT (чтение), INSERT (добавление), UPDATE (обновление), DELETE (удаление) и другие.

**Глобальные права** — определяют операции, разрешенные для выполнения на уровне базы данных или даже на уровне сервера баз данных в целом. Например, глобальные права могут включать права на создание баз данных, создание пользователей, управление ролями и т.д.

**Права на системные объекты** — определяют доступ к системным объектам базы данных, таким как системные таблицы и представления, а также каталоги базы данных.

**Права на схемы (Schema Privileges)** — некоторые СУБД предоставляют возможность управления правами доступа на уровне схем, что позволяет более гибко управлять доступом к группам объектов.

### Примеры создания пользователей в PostgreSQL

В PostgreSQL для создания пользователя используется команда `<samp>CREATE ROLE</samp>`. Создавать новых пользователей могут пользователями с такими правами:

- **CREATE ROLE**: эта привилегия дает пользователю возможность создавать новые роли (включая пользователей) в базе данных PostgreSQL. Пользователи, обладающие этой привилегией, могут выполнять команду CREATE ROLE для создания новых пользователей.
- **SUPERUSER**: пользователь с правами суперпользователя (SUPERUSER) имеет все привилегии в базе данных, включая возможность создавать новых пользователей и назначать им любые права доступа.

Рассмотрим примеры создания пользователей с различными уровнями привилегий:

#### **Создание суперпользователя**

<div class="table-scroll" id="bkmrk-create-role-superuse"><table><tbody><tr><td>CREATE ROLE superuser LOGIN SUPERUSER PASSWORD 'password';</td></tr></tbody></table>

</div>Этот запрос создает нового суперпользователя с именем superuser и устанавливает пароль password. Суперпользователь имеет полный доступ ко всем объектам базы данных и может выполнять любые операции.

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-%3Ctimestamp%3E-log%3A-%C2%A0ne"><table><tbody><tr><td>&lt;timestamp&gt; LOG: new superuser superuser created  
&lt;timestamp&gt; LOG: granting SUPERUSER privileges to user "superuser"</td></tr></tbody></table>

</div>#### **Создание пользователя с ограниченными привилегиями**

<div class="table-scroll" id="bkmrk-create-role-limited_"><table><tbody><tr><td>CREATE ROLE limited\_user LOGIN PASSWORD 'password' VALID UNTIL '2025-12-31';  
GRANT SELECT ON ALL TABLES IN SCHEMA public TO limited\_user;

</td></tr></tbody></table>

</div>Этот запрос создает нового пользователя с именем limited\_user, устанавливает ему пароль password и устанавливает срок его действия до 31 декабря 2025 года. Затем с помощью команды <samp>`GRANT`</samp> предоставляются ограниченные привилегии на чтение (SELECT) для всех таблиц в схеме public.

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-%3Ctimestamp%3E-log%3A-%C2%A0ne-1"><table><tbody><tr><td>&lt;timestamp&gt; LOG: new user limited\_user with password created  
&lt;timestamp&gt; LOG: granting LOGIN privileges to user "limited\_user"  
&lt;timestamp&gt; LOG: granting SELECT privileges on all tables in schema public to user "limited\_user"</td></tr></tbody></table>

</div>#### **Создание роли с административными привилегиями**

<div class="table-scroll" id="bkmrk-create-role-admin_ro"><table><tbody><tr><td>CREATE ROLE admin\_role;  
GRANT CREATE ROLE TO admin\_role;  
GRANT CREATE DATABASE TO admin\_role;</td></tr></tbody></table>

</div>Этот запрос создает новую роль admin\_role, которая имеет право создавать другие роли и базы данных. Роль с административными привилегиями может быть использована для управления пользователями и базами данных в системе.

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-%3Ctimestamp%3E-log%3A-%C2%A0ne-2"><table><tbody><tr><td>&lt;timestamp&gt; LOG: new role admin\_role created  
&lt;timestamp&gt; LOG: granting CREATE ROLE privileges to role "admin\_role"  
&lt;timestamp&gt; LOG: granting CREATE DATABASE privileges to role "admin\_role"</td></tr></tbody></table>

</div>## Аудит учетных записей

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

- DDL (Data definition language - создание таблиц, создание представлений, создание индексов и т. д.);
- DML (Data Manipulation Language - select, insert, update, delete).

Также считается хорошей практикой создавать отдельные роли для DDL и DML. Для приложения с названием "payroll" были бы созданы следующие пользователи:

- payroll\_owner;
- payroll\_user.

Любые привилегии DDL предоставляются только учетной записи payroll\_owner, в то время как привилегии DML предоставляются только учетной записи payroll\_user. Это предотвращает случайное создание/изменение/удаление объектов базы данных кодом приложения, который выполняется от имени учетной записи payroll\_user.

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

В процессе аудита сначала необходимо проверить привилегии, предоставленные суперпользователю базы данных (определенному здесь как postgres), используя команду отображения `<samp>psql -c "\du postgres"</samp>`, чтобы установить базовую линию для предоставленных административных привилегий. На основе примера ниже, суперпользователь postgres может создавать роли, создавать базы данных, управлять репликацией и обходить уровни безопасности строк (RLS - Row Level Security):

<div class="table-scroll" id="bkmrk-%23-whoamipostgres%23-ps"><table><tbody><tr><td>\# whoami  
postgres  
\# psql -c "\\du postgres"

 List of roles  
Role name | Attributes | Member of  
\-----------------+--------------------------------------------------------------------------+--------------------  
postgres | Superuser, Create role, Create DB, Replication, | {}  
 | Bypass RLS |

</td></tr></tbody></table>

</div>Теперь проверим ту же информацию для обычного пользователя с именем appuser с помощью команды отображения `psql -c "\du appuser"`. Вывод подтверждает, что обычный пользователь appuser имеет те же повышенные привилегии, что и системный администратор пользователь postgres, так быть не должно:

<div class="table-scroll" id="bkmrk-%23-whoamipostgres%23-ps-1"><table><tbody><tr><td>\# whoami  
postgres  
\# psql -c "\\du appuser"

 List of roles  
Role name | Attributes | Member of  
\-----------------+---------------------------------------------------------------------------+--------------------  
appuser | Superuser, Create role, Create DB, Replication, | {}  
 | Bypass RLS |

</td></tr></tbody></table>

</div>Этот пример показывает, что одному пользователю были присвоены излишние административные права, однако в процессе аудита нужно провести полный анализ всех пользователей базы данных, чтобы убедиться, что у них нет избыточных прав. Это можно сделать с помощью следующих команд:

<div class="table-scroll" id="bkmrk-%23-whoamipostgres%23-ps-2"><table><tbody><tr><td>\# whoami  
postgres  
\# psql -c "\\du \*"  
\# psql -c "select \* from pg\_user order by usename"</td></tr></tbody></table>

</div>Если каким-либо обычным пользователям были предоставлены избыточные права, их следует немедленно отозвать с помощью команды SQL `ALTER ROLE`. Используя тот же пример выше, следующие команды отзывают все ненужные повышенные права у обычного пользователя appuser:

<div class="table-scroll" id="bkmrk-%23-whoamipostgres%23-ps-3"><table><tbody><tr><td>\# whoami  
postgres  
\# psql -c "ALTER ROLE appuser NOSUPERUSER;"  
ALTER ROLE  
\# psql -c "ALTER ROLE appuser NOCREATEROLE;"  
ALTER ROLE  
\# psql -c "ALTER ROLE appuser NOCREATEDB;"  
ALTER ROLE  
\# psql -c "ALTER ROLE appuser NOREPLICATION;"  
ALTER ROLE  
\# psql -c "ALTER ROLE appuser NOBYPASSRLS;"  
ALTER ROLE  
\# psql -c "ALTER ROLE appuser NOINHERIT;"  
ALTER ROLE</td></tr></tbody></table>

</div>После выполненных действий нужно проверить новые права у пользователя appuser:

<div class="table-scroll" id="bkmrk-%23-whoamipostgres%23-ps-4"><table><tbody><tr><td>\# whoami  
postgres  
\# psql -c "\\du appuser"

 List of roles  
Role name | Attributes | Member of  
\-----------------+-----------------+--------------------  
appuser | | {}

</td></tr></tbody></table>

</div>## Роли и права пользователей в NoSQL базах

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

**Аутентификация и авторизация** — пользователи могут аутентифицироваться с помощью учетных данных (например, имя пользователя и пароль) или с использованием механизмов аутентификации на основе ключей. После успешной аутентификации пользователь авторизуется для доступа к данным в соответствии с их правами доступа.

**Роли** — в NoSQL базах данных также существуют концепции ролей, которые могут группировать пользователей и предоставлять им схожие права доступа. Роли могут использоваться для упрощения управления правами доступа и обеспечения согласованности безопасности в системе.

**Права доступа** — пользователи или роли могут быть наделены различными правами доступа к данным.  
Эти права могут включать операции чтения, записи, обновления, удаления и т. д. В зависимости от конкретной NoSQL базы данных, могут также поддерживаться различные уровни гранулярности прав доступа к отдельным объектам данных.

### Основные права доступа в MongoDB

- **read**: позволяет пользователю выполнять операции чтения данных из коллекции.
- **readWrite**: предоставляет пользователю права на выполнение операций чтения и записи данных в коллекцию.
- **dbAdmin**: позволяет пользователю управлять базой данных, включая создание и удаление коллекций, просмотр статистики базы данных и т. д.
- **dbOwner**: предоставляет пользователю полные права доступа ко всем объектам базы данных, включая управление пользователями и ролями.
- **userAdmin**: позволяет пользователю управлять пользователями и ролями в базе данных, включая создание и удаление пользователей и ролей.
- **clusterAdmin**: предоставляет пользователю права на управление кластером MongoDB, включая управление репликацией, шардингом и администрирование кластера.
- **backup**: позволяет пользователю выполнять резервное копирование базы данных MongoDB.
- **restore**: предоставляет пользователю права на восстановление данных из резервной копии базы данных MongoDB.
- **backupAdmin**: позволяет пользователю управлять процессом резервного копирования базы данных MongoDB, включая управление точками сохранения и другими аспектами резервного копирования.

Управление доступом на уровне коллекций/таблиц - во многих NoSQL базах данных можно настраивать права доступа на уровне отдельных коллекций (в MongoDB) или таблиц (в Cassandra). Это позволяет точечно контролировать доступ к конкретным наборам данных в базе данных.

Управление доступом на уровне полей - некоторые NoSQL базы данных также поддерживают гранулярное управление доступом на уровне отдельных полей в документах (например, в MongoDB).

### **Пример создания пользователя в MongoDB**

```
```javascript
use mydatabase;

// Создание пользователя с правами чтения и записи для определенной коллекции
db.createUser({
  user: "user1",
  pwd: "password1",
  roles: [
    { role: "readWrite", db: "mydatabase" }
  ]
});

// Создание пользователя с административными правами для базы данных
db.createUser({
  user: "adminUser",
  pwd: "adminPassword",
  roles: [
    { role: "dbAdmin", db: "mydatabase" },
    { role: "userAdmin", db: "mydatabase" }
  ]
});

// Создание пользователя с правами на выполнение резервного копирования и восстановления
db.createUser({
  user: "backupUser",
  pwd: "backupPassword",
  roles: [
    { role: "backup", db: "mydatabase" },
    { role: "restore", db: "mydatabase" }
  ]
});

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

События создания пользователей в журнале MongoDB mongod.log могут выглядеть следующим образом:

<div class="table-scroll" id="bkmrk-2024-03-28t12%3A34%3A56."><table><tbody><tr><td>2024-03-28T12:34:56.789+0000 I ACCESS \[conn123\] Successfully added user: { "user" : "user1", "roles" : \[ { "role" : "readWrite", "db" : "mydatabase" } \] }  
2024-03-28T12:34:56.790+0000 I ACCESS \[conn123\] Successfully added user: { "user" : "adminUser", "roles" : \[ { "role" : "dbAdmin", "db" : "mydatabase" }, { "role" : "userAdmin", "db" : "mydatabase" } \] }  
2024-03-28T12:34:56.791+0000 I ACCESS \[conn123\] Successfully added user: { "user" : "backupUser", "roles" : \[ { "role" : "backup", "db" : "mydatabase" }, { "role" : "restore", "db" : "mydatabase" } \] }</td></tr></tbody></table>

</div>Поля в логе:

- Дата и время (2024-03-28T12:34:56.789+0000): Метка времени события.
- Уровень журналирования (I ACCESS): Уровень важности сообщения.
- Идентификатор соединения (\[conn123\]): Идентификатор соединения, в рамках которого была создана запись.
- Сообщение (Successfully added user): Описание события.
- Детали ({ "user" : "user1", "roles" : \[...\] }): Дополнительная информация о созданном пользователе, включая его имя пользователя (user) и назначенные ему роли (roles).
- Эти записи в журнале сообщают об успешном создании пользователей и предоставлении им соответствующих прав доступа.

# Использование шифрования

## Настройка шифрования в PostgreSQL

В PostgreSQL шифрование данных можно настроить с использованием различных методов, таких как шифрование на уровне приложения, шифрование на уровне столбцов и шифрование на уровне хранения данных. Ниже представлен обзор этих методов:

1. **Шифрование на уровне приложения**: этот метод предполагает, что данные шифруются на стороне приложения перед тем, как они попадут в базу данных. Приложение самостоятельно обрабатывает шифрование и дешифрование данных перед сохранением их в базе данных или после извлечения из базы данных. Это обеспечивает контроль над процессом шифрования, но требует изменений в коде приложения.
2. **Шифрование на уровне столбцов**: PostgreSQL поддерживает шифрование данных на уровне столбцов с помощью модуля расширения pgcrypto. С использованием этого метода вы можете шифровать конкретные столбцы таблицы, оставляя остальные данные в открытом виде. Преимущество этого метода в том, что шифрование и дешифрование данных происходят автоматически на уровне базы данных, что делает его более удобным для применения.
3. **Шифрование на уровне хранения данных**: этот метод предполагает использование шифрования на уровне хранения данных, когда все данные в базе данных шифруются целиком. PostgreSQL поддерживает шифрование на уровне хранения данных с помощью различных инструментов, таких как Transparent Data Encryption (TDE), который может быть реализован с помощью сторонних расширений или управляемых служб.

Для конфигурации шифрования на уровне столбцов в PostgreSQL с помощью pgcrypto можно использовать следующие шаги:

1\. Установите расширение pgcrypto:

```
```SQL
CREATE EXTENSION pgcrypto;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

2\. Создайте таблицу с зашифрованными столбцами:

```
```SQL
CREATE TABLE my_table ( id SERIAL PRIMARY KEY, sensitive_data BYTEA ); -- Шифруйте данные перед вставкой в таблицу
INSERT INTO my_table (sensitive_data) VALUES (pgp_sym_encrypt('my sensitive data', 'secret_key'));
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

3\. Дешифруйте данные при их извлечении из таблицы:

```
```SQL
-- Извлеките зашифрованные данные и дешифруйте их
SELECT pgp_sym_decrypt(sensitive_data, 'secret_key') AS sensitive_data FROM my_table;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Для работы с зашифрованными данными в базе данных пользователю обычно требуются следующие права доступа:

**Доступ к зашифрованным данным**: пользователь должен иметь права на выполнение операций чтения, записи, обновления и удаления данных в зашифрованных таблицах или столбцах. Это обеспечивает пользователю возможность взаимодействовать с данными в базе данных, независимо от их шифрования

```
```sql
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE encrypted_table TO user_name;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

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

```
```sql
GRANT EXECUTE ON FUNCTION encrypt_function(text) TO user_name;
GRANT EXECUTE ON FUNCTION decrypt_function(text) TO user_name;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

**Доступ к функциям и процедурам**: если в базе данных используются функции или процедуры для работы с зашифрованными данными (например, для шифрования или расшифровки), пользователю может потребоваться доступ к этим функциям или процедурам.

```
```sql
GRANT EXECUTE ON FUNCTION encryption_function(parameters) TO user_name;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

**Доступ к управлению ключами шифрования (необязательно)**: в некоторых случаях пользователь может быть уполномочен на управление ключами шифрования или их генерацию. Это может потребоваться, например, при создании новых зашифрованных столбцов или при установке новых ключей шифрования.

```
```sql
GRANT CREATE ON SCHEMA encryption_schema TO user_name;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

## Настройка шифрования в MongoDB

Для настройки шифрования данных в MongoDB вам необходимо выполнить ряд шагов, включая создание ключей шифрования, настройку ключевого провайдера, включение шифрования данных и настройку транспортного шифрования.

1. **Создание ключей шифрования**:
    
    Пример создания ключей шифрования с использованием `mongocryptd`:
    
    ```
    ```css
    mongocryptd --fork --dbpath /var/lib/mongocryptd
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
2. **Настройка ключевого провайдера**:
    
    ```
    ```x86asm
    mongosh use admin db.createCollection("keys") db.keys.insertOne({ "key": "<master_key>" })
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
3. **Включение шифрования данных**:
    
    Включение шифрования данных при запуске сервера MongoDB:
    
    ```
    ```css
    mongod --enableEncryption --encryptionKeyFile /path/to/encryption.key
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
4. **Включение транспортного шифрования**:
    
    Пример настройки SSL/TLS для транспортного шифрования:
    
    ```objectivec
    net: ssl: mode: "requireSSL" PEMKeyFile: "/path/to/server.pem" CAFile: "/path/to/ca.pem"
    ```

# Резервное копирование

## Резервное копирование в PostgreSQL

Для настройки резервного копирования в PostgreSQL вы можете использовать инструменты резервного копирования, такие как `pg_dump` и `pg_dumpall`, а также встроенную функциональность PostgreSQL для создания резервных копий и восстановления данных. Ниже шаги, которые обычно выполняются для настройки резервного копирования:

1. **Использование pg\_dump для создания резервной копии базы данных:**
    
    
    - Используйте команду `pg_dump` для создания текстовых файлов SQL, содержащих структуру базы данных и данные.
    - Пример команды для создания резервной копии базы данных: ```
        ```nginx
        pg_dump -U username dbname > backup.sql
        ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                              3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                              20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                          </button>
        ```
2. **Использование pg\_dumpall для создания резервной копии всех баз данных:**
    
    
    - Команда `pg_dumpall` позволяет создавать резервные копии всех баз данных, доступных для указанного пользователя.
    - Пример команды для создания резервной копии всех баз данных: ```
        ```nginx
        pg_dumpall -U username > backup.sql
        ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                              3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                              20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                          </button>
        ```

## Резервное копирование в MongoDB

Для настройки резервного копирования в MongoDB можно использовать инструменты резервного копирования, такие как `mongodump`, а также сторонние инструменты управления резервными копиями, например, MongoDB Atlas Backup или другие инструменты для автоматизации и управления резервным копированием. Ниже настройка резервного копирования в MongoDB с использованием `mongodump`:

1. **Использование mongodump для создания резервных копий:**
    
    
    - Пример команды для создания резервной копии всех баз данных MongoDB: ```
        ```css
        mongodump --host <hostname> --port <port> --username <username> --password <password> --out <backup_directory>
        ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                              3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                              20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                          </button>
        ```
        
        Эта команда использует подключение к MongoDB с указанными параметрами (хост, порт, имя пользователя, пароль) и сохраняет резервную копию в указанном каталоге.

Общие рекомендации:

1. **Автоматизация резервного копирования:**
    
    
    - Для регулярного создания резервных копий вы можете использовать утилиты планировщика задач, такие как cron в UNIX-подобных системах или Task Scheduler в Windows.
    - Создайте скрипт, который будет выполнять команду резервного копирования с необходимыми параметрами, а затем настройте его выполнение по расписанию с помощью утилиты планировщика задач.
2. **Хранение резервных копий:**
    
    
    - Убедитесь, что резервные копии хранятся в безопасном месте, доступном только авторизованным пользователям.
    - Рассмотрите возможность хранения резервных копий в облачном хранилище или на отдельном сервере с репликацией данных для обеспечения долгосрочного хранения и защиты от потери данных.
3. **Тестирование восстановления:**
    
    
    - Регулярно проверяйте процесс восстановления данных из резервной копии, чтобы убедиться, что он работает правильно, и данные могут быть восстановлены в случае чрезвычайной ситуации.

# Сценарий атаки

## На примере PostgreSQL

Рассмотрим сценарий, при котором злоумышленник уже имеет доступ к учетной записи с правом `CREATE ROLE` . Пользователь с правом `CREATE ROLE` в PostgreSQL может создать другого пользователя и назначить ему права на редактирование/удаление/просмотр всех таблиц в базе данных.

1. **Создание нового пользователя:** Пользователь с правом `CREATE ROLE` может создать нового пользователя с помощью команды `CREATE ROLE` и назначить ему необходимые права доступа.
    
    ```
    ```sql
    CREATE ROLE coolhecker LOGIN PASSWORD 'password';
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
2. **Назначение прав доступа:** чтобы дать новой учетной записи права на редактирование таблиц в БД, ему можно дать роль `SUPERUSER`
    
    ```
    ```sql
    ALTER ROLE coolhecker WITH SUPERUSER;
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
    
    Или можно назначить отдельные привилегии для пользователя, указав необходимые права доступа, например:
    
    ```
    ```sql
    GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO coolhecker;
    ```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                          3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                          20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                      </button>
    ```
    
    Этот запрос предоставит пользователю `coolhecker` права на просмотр, вставку, обновление и удаление данных из всех таблиц в схеме `public`.

Как это будет видно в логе:

<div class="table-scroll" id="bkmrk-2024-03-29-12%3A00%3A00."><table><tbody><tr><td>2024-03-29 12:00:00.123 UTC \[23345\] LOG: statement: CREATE ROLE coolhecker LOGIN PASSWORD 'ehehehehe';  
2024-03-29 12:00:01.234 UTC \[23345\] LOG: statement: ALTER ROLE coolhecker WITH SUPERUSER;</td></tr></tbody></table>

</div>В первой записи выполняется команда `<samp>CREATE ROLE</samp>`, создающая нового пользователя с именем coolhecker и паролем ehehehehe. Во второй записи выполняется команда `<samp>ALTER ROLE</samp>`, назначающая пользователю coolhecker права SUPERUSER.

Важно! Для того чтобы увидеть эти записи в логе, необходимо настроить журналирование в соответствии с требуемым уровнем детализации и включить запись административных действий в лог.

Уже на этом этапе злоумышленника можно остановить, если вовремя среагировать на событие создания пользователя с ролью superuser. Как может выглядеть правило sigma для обнаружения такого события:

```
```yaml

title: Обнаружение создания суперпользователя в PostgreSQL
id: postgresql_create_superuser
status: experimental
description: Обнаружение операции создания пользователя с ролью суперпользователя в PostgreSQL.
author: [Your Name]
date: 2024-03-31
logsource:
  product: postgresql
detection:
  selection:
    crosstheme1.username: ["!~^(?:postgres)$"]  # Исключаем создание роли "postgres"
    crosstheme1.statement: ["CREATE ROLE%", "%SUPERUSER%"]
  condition: selection
fields:
  - username
  - statement
falsepositives:
  - Легитимные операции создания пользователей с правами суперпользователя, произведенные администраторами.
level: high

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Предположим, что злоумышленника никто не остановил и он идет дальше. Какие операции он может выполнить:

**Зайти в БД под созданной учетной записью**

В логе такое событие будет выглядеть так:

<div class="table-scroll" id="bkmrk-2024-03-31-10%3A15%3A00."><table><tbody><tr><td>2024-03-31 10:15:00.123 UTC \[23345\] LOG: connection authorized: user=coolhecker database=my\_database</td></tr></tbody></table>

</div>**Вывод перечня таблиц в базе данных**

```
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Этот запрос выбирает все имена таблиц из схемы `public` в базе данных.

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-2024-03-31-10%3A15%3A00.-1"><table><tbody><tr><td>2024-03-31 10:15:00.123 UTC \[23345\] LOG: statement: SELECT table\_name FROM information\_schema.tables WHERE table\_schema = 'public';</td></tr></tbody></table>

</div>**Вывод названий столбцов для одной из таблиц**

Допустим, у нас есть таблица `users`, и злоумышленник хочет увидеть названия ее столбцов.

```
```sql
SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'users';
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Этот запрос выбирает все имена столбцов для таблицы `users` из схемы `public` в базе данных.

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-2024-03-31-10%3A16%3A00."><table><tbody><tr><td>2024-03-31 10:16:00.234 UTC \[23346\] LOG: statement: SELECT column\_name FROM information\_schema.columns WHERE table\_schema = 'public' AND table\_name = 'users';</td></tr></tbody></table>

</div>**Выполнить очень широкий запрос**

```
```css
SELECT * FROM users;
```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Как это будет выглядеть в логе:

<div class="table-scroll" id="bkmrk-2024-03-31-10%3A16%3A00.-1"><table><tbody><tr><td>2024-03-31 10:16:00.234 UTC \[23346\] LOG: statement: SELECT \* FROM my\_table;</td></tr></tbody></table>

</div>Пример правила Sigma, которое обнаруживает 2 последовательных события: авторизацию пользователя в базе и выполнение широкого запроса:

```
```yaml

title: Обнаружение последовательности аутентификации и выполнения запроса SELECT * FROM в PostgreSQL
id: postgresql_login_followed_by_select
status: experimental
description: Обнаружение события, когда пользователь авторизуется в базе данных, а затем выполняет запрос SELECT * FROM.
author: [Your Name]
date: 2024-04-01
references:
  - https://example.com/postgresql-logging-docs
logsource:
  product: postgresql
detection:
  selection1:
    crosstheme1.event: "connection authorized"
  selection2:
    crosstheme1.statement: "SELECT * FROM"
  timeframe: 1m # Временное окно для обнаружения двух последовательных событий (1 минута)
  condition: selection1 and selection2
fields:
  - user
  - event
  - statement
falsepositives:
  - Легитимные операции, произведенные аутентифицированными пользователями.
level: high


```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

## Пример в MongoDB 

Рассмотрим аналогичный пример для MongoDB.

Злоумышленник создает учетную запись с широкими правами:

```
```javascript

use admin

db.createUser({
    user: "adminUser",
    pwd: "adminPassword",
    roles: [
        { role: "root", db: "admin" },
        { role: "readWriteAnyDatabase", db: "admin" },
        { role: "dbAdminAnyDatabase", db: "admin" },
        { role: "userAdminAnyDatabase", db: "admin" }
    ]
})

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

- root: Дает полный административный доступ ко всей системе MongoDB.
- readWriteAnyDatabase: Позволяет читать и записывать данные в любую базу данных.
- dbAdminAnyDatabase: Позволяет управлять базами данных на уровне администратора.
- userAdminAnyDatabase: Позволяет управлять пользователями и их правами на уровне администратора.

Пример правила Sigma, которое будет обнаруживать такое событие:

```
```yaml

title: Обнаружение создания пользователя с широкими правами в MongoDB
id: mongodb_create_user_with_wide_privileges
status: experimental
description: Обнаружение события, когда создается пользователь с широкими правами в MongoDB.
author: [Your Name]
date: 2024-04-02
logsource:
  product: mongodb
detection:
  selection:
    crosstheme1.operation: CREATE_USER
    crosstheme1.roles: ["root", "readWriteAnyDatabase", "dbAdminAnyDatabase", "userAdminAnyDatabase"]
  condition: selection
fields:
  - user
  - roles
falsepositives:
  - Легитимные операции создания пользователей с широкими правами, произведенные администраторами.
level: high


```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

Допустим, злоумышленник решил выбрать все возможные данные из БД. В логе это будет выглядеть так:

<div class="table-scroll" id="bkmrk-2024-04-02t12%3A34%3A56."><table><tbody><tr><td>2024-04-02T12:34:56.789+0000 I COMMAND \[conn1234\] command my\_database.my\_collection command: find { find: "my\_collection", filter: {}, $db: "my\_database" } planSummary: COLLSCAN keysExamined:0 docsExamined:10000 cursorExhausted:1 numYields:78 nreturned:10000 reslen:2687313 locks:{ Global: { acquireCount: { r: 158 } }, Database: { acquireCount: { r: 79 } }, Collection: { acquireCount: { r: 79 } } } protocol:op\_msg 33ms</td></tr></tbody></table>

</div>- `2024-04-02T12:34:56.789+0000` - дата и время события.
- `I COMMAND` - тип команды (в данном случае, команда).
- `[conn1234]` - идентификатор соединения.
- `command my_database.my_collection` - команда, которая была выполнена (в данном случае, поиск документов в коллекции `my_collection` базы данных `my_database`).
- `keysExamined:0` - количество ключей, проанализированных при выполнении запроса (в данном случае, 0).
- `docsExamined:10000` - количество документов, просмотренных при выполнении запроса (в данном случае, 10000).
- `cursorExhausted:1` - флаг, указывающий, что курсор исчерпан.
- `numYields:78` - количество раз, когда сервер передал управление другим операциям (yielded).
- `nreturned:10000` - количество документов, возвращенных в результате запроса (в данном случае, 10000).
- `reslen:2687313` - размер ответа в байтах.
- `locks` - информация о блокировках, используемых запросом.
- `protocol:op_msg` - протокол, используемый для передачи сообщений (в данном случае, op\_msg).
- `33ms` - время выполнения запроса (в данном случае, 33 миллисекунды).

Пример правила Sigma, которое будет обнаруживать такое событие:

```
```yaml

title: Обнаружение выбора всех данных из базы данных MongoDB
id: mongodb_select_all_data
status: experimental
description: Обнаружение события, когда пользователь выбирает все данные из базы данных MongoDB.
author: [Your Name]
date: 2024-04-03
logsource:
  product: mongodb
detection:
  selection:
    crosstheme1.command: "find"
    crosstheme1.docsExamined: { ">": 0 }
    crosstheme1.nreturned: { ">": 0 }
    crosstheme1.keysExamined: 0
    crosstheme1.cursorExhausted: 1
  condition: selection
fields:
  - user
  - database
  - collection
  - command
falsepositives:
  - Легитимные запросы, которые выбирают все данные из базы данных MongoDB.
level: high

```<button class="copy-code-btn st-button_style_none copy-code-btn__code-block" title="Скопировать код" type="button"><svg fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.2 3H10.2C9.2073 3 8.4 3.8073 8.4 4.8V8.4H4.8C3.8073 8.4 3 9.2073 3 10.2V19.2C3 20.1927 
                      3.8073 21 4.8 21H13.8C14.7927 21 15.6 20.1927 15.6 19.2V15.6H19.2C20.1927 15.6 21 14.7927 21 13.8V4.8C21 3.8073 
                      20.1927 3 19.2 3ZM4.8 19.2V10.2H13.8L13.8018 19.2H4.8ZM19.2 13.8H15.6V10.2C15.6 9.2073 14.7927 8.4 13.8 8.4H10.2V4.8H19.2V13.8Z" fill="#777777"></path></svg>
                  </button>
```

- `title`: Название правила.
- `id`: Уникальный идентификатор правила.
- `status`: Статус правила (например, "экспериментальный").
- `description`: Описание того, что делает правило.
- `author`: Ваше имя или имя автора правила.
- `date`: Дата создания правила.
- `logsource`: Источник журналов, в данном случае - продукт `mongodb`.
- `detection`: Определение, которое указывает, как обнаружить событие. Мы используем выборку по нескольким полям, таким как `command` (команда), `docsExamined` (количество документов, просмотренных при выполнении запроса), `nreturned` (количество возвращенных документов), `keysExamined` (количество ключей, проанализированных при выполнении запроса) и `cursorExhausted` (флаг, указывающий, что курсор исчерпан).
- `condition`: Условие, которое определяет, что событие соответствует правилу.
- `fields`: Поля, которые будут отображены в результате обнаружения.
- `falsepositives`: Возможные ситуации, которые могут быть ложноположительными.
- `level`: Уровень серьезности обнаружения (например, "высокий").