Двухфакторная аутентификация в 1С-Битрикс

Настройка 2FA для администраторов и пользователей. OTP, приложения-аутентификаторы, резервные коды.

Дмитрий Мещеряков
Дмитрий Мещеряков
📅 23 сентября 2026 г.📖 8 мин чтения

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

Разберём настройку и, отдельно, границы того, что 2FA реально защищает: у неё есть слабые места, и знать их нужно до того, как вы решите, что вопрос закрыт.

Зачем 2FA

Пароль — единственный барьер между злоумышленником и вашей админкой. Если пароль утёк (фишинг, брутфорс, утечка базы другого сервиса), сайт скомпрометирован.

Двухфакторная аутентификация — это второй барьер помимо пароля: одноразовый код, который есть только у владельца телефона.

💡 Совет

По статистике Google, 2FA блокирует 100% автоматизированных атак, 96% фишинговых атак и 76% таргетированных атак.

Встроенная 2FA в Битрикс

Битрикс поддерживает OTP (One-Time Password) из коробки начиная с версии 14.5.

Включение для администраторов

Шаг 1: Включаем модуль

Админка → Настройки → Настройки продукта → Модули → Проактивная защита

Убедитесь, что модуль security установлен и активен.

Шаг 2: Настраиваем OTP

Админка → Настройки → Проактивная защита → Одноразовые пароли

text
☑ Включить одноразовые пароли
☑ Обязательное использование для группы: Администраторы [admin]
   Количество дней отсрочки: 3

Шаг 3: Пользователь настраивает свой OTP

При следующем входе администратор увидит форму настройки:

  1. Установить приложение-аутентификатор (Google Authenticator, Authy, 1Password)
  2. Отсканировать QR-код
  3. Ввести проверочный код
  4. Сохранить резервные коды

Приложения-аутентификаторы

ПриложениеПлатформыОсобенности
Google AuthenticatoriOS, AndroidПростое, без облака
AuthyiOS, Android, DesktopОблачный бэкап, мультидевайс
1PasswordВсеИнтеграция с менеджером паролей
Microsoft AuthenticatoriOS, AndroidИнтеграция с MS-аккаунтом
⚠️ Важно

Google Authenticator не делает бэкапов. При потере телефона — потеря доступа. Используйте Authy или сохраняйте резервные коды.

Настройка через код

Принудительное включение 2FA

php
// /local/php_interface/init.php
use Bitrix\Main\EventManager;

// Требуем 2FA для всех администраторов
EventManager::getInstance()->addEventHandler(
    'main',
    'OnAfterUserAuthorize',
    function ($arParams) {
        global $USER;
        
        if (!$USER->IsAuthorized()) {
            return;
        }
        
        // Проверяем, администратор ли это
        if (!$USER->IsAdmin()) {
            return;
        }
        
        // Проверяем, настроен ли OTP
        $otp = \Bitrix\Security\Mfa\Otp::getByUser($USER->GetID());
        
        if (!$otp || !$otp->isActivated()) {
            // Перенаправляем на настройку OTP
            LocalRedirect('/bitrix/admin/security_otp.php?init=Y');
        }
    }
);

Проверка статуса 2FA

php
use Bitrix\Security\Mfa\Otp;

function isOtpEnabled(int $userId): bool
{
    $otp = Otp::getByUser($userId);
    return $otp && $otp->isActivated();
}

function requireOtpForAdmins(): void
{
    global $DB;
    
    // Получаем всех администраторов без 2FA
    $admins = $DB->Query("
        SELECT u.ID, u.LOGIN, u.EMAIL
        FROM b_user u
        JOIN b_user_group ug ON u.ID = ug.USER_ID
        WHERE ug.GROUP_ID = 1
          AND u.ACTIVE = 'Y'
          AND u.ID NOT IN (
              SELECT USER_ID FROM b_security_otp WHERE ACTIVE = 'Y'
          )
    ");
    
    $withoutOtp = [];
    while ($admin = $admins->Fetch()) {
        $withoutOtp[] = $admin;
    }
    
    if (!empty($withoutOtp)) {
        // Отправляем уведомление или логируем
        \CEventLog::Add([
            'SEVERITY' => 'WARNING',
            'AUDIT_TYPE_ID' => 'SECURITY_OTP',
            'MODULE_ID' => 'security',
            'DESCRIPTION' => 'Администраторы без 2FA: ' . json_encode($withoutOtp),
        ]);
    }
}

API для работы с OTP

php
use Bitrix\Security\Mfa\Otp;
use Bitrix\Security\Mfa\OtpAlgorithm;

// Создание нового OTP для пользователя
function setupOtpForUser(int $userId): array
{
    // Генерируем секретный ключ
    $secret = Otp::generateSecret();
    
    // Создаём объект OTP
    $otp = new Otp();
    $otp->setUserId($userId);
    $otp->setSecret($secret);
    $otp->setType(OtpAlgorithm::TOTP); // Time-based OTP
    
    // Сохраняем (но не активируем)
    $otp->save();
    
    // Генерируем QR-код
    $qrCodeUrl = $otp->getProvisioningUri(
        'Битрикс Админка', // Название сервиса
        $userId            // Идентификатор аккаунта
    );
    
    // Генерируем резервные коды
    $backupCodes = [];
    for ($i = 0; $i < 10; $i++) {
        $backupCodes[] = Otp::generateRecoveryCode();
    }
    
    return [
        'secret' => $secret,
        'qr_url' => $qrCodeUrl,
        'backup_codes' => $backupCodes,
    ];
}

// Проверка OTP-кода
function verifyOtpCode(int $userId, string $code): bool
{
    $otp = Otp::getByUser($userId);
    
    if (!$otp) {
        return false;
    }
    
    return $otp->verify($code);
}

// Активация OTP после первой успешной проверки
function activateOtp(int $userId, string $code): bool
{
    $otp = Otp::getByUser($userId);
    
    if (!$otp || $otp->isActivated()) {
        return false;
    }
    
    if ($otp->verify($code)) {
        $otp->activate();
        $otp->save();
        return true;
    }
    
    return false;
}

Резервные коды

Резервные коды — страховка на случай потери телефона. Каждый код одноразовый.

Генерация резервных кодов

php
use Bitrix\Security\Mfa\Otp;

function generateBackupCodes(int $userId, int $count = 10): array
{
    $codes = [];
    
    for ($i = 0; $i < $count; $i++) {
        $codes[] = Otp::generateRecoveryCode();
    }
    
    // Сохраняем хэши кодов в БД
    $otp = Otp::getByUser($userId);
    if ($otp) {
        $otp->setRecoveryCodes($codes);
        $otp->save();
    }
    
    return $codes; // Показываем пользователю один раз
}

Хранение резервных кодов

php
// Структура таблицы b_security_otp_recovery
// USER_ID | CODE_HASH | USED | DATE_USED

function useBackupCode(int $userId, string $code): bool
{
    global $DB;
    
    $codeHash = hash('sha256', $code);
    
    $result = $DB->Query("
        UPDATE b_security_otp_recovery
        SET USED = 'Y', DATE_USED = NOW()
        WHERE USER_ID = {$userId}
          AND CODE_HASH = '{$DB->ForSql($codeHash)}'
          AND USED = 'N'
    ");
    
    return $DB->AffectedRowsCount() > 0;
}
💡 Совет

Рекомендация: храните резервные коды в менеджере паролей (1Password, Bitwarden) или в защищённом облачном хранилище.

Кастомная форма входа с 2FA

php
// /local/templates/main/components/bitrix/system.auth.form/.default/template.php
<?php if ($arResult['NEED_OTP']): ?>
    <div class="auth-otp-form">
        <h3>Введите код из приложения</h3>
        <p>Откройте Google Authenticator или другое приложение и введите 6-значный код.</p>
        
        <form method="POST" action="<?= POST_FORM_ACTION_URI ?>">
            <?= bitrix_sessid_post() ?>
            <input type="hidden" name="AUTH_FORM" value="Y" />
            <input type="hidden" name="TYPE" value="OTP" />
            
            <div class="form-group">
                <input 
                    type="text" 
                    name="USER_OTP" 
                    placeholder="000 000"
                    maxlength="6"
                    pattern="[0-9]{6}"
                    autocomplete="one-time-code"
                    inputmode="numeric"
                    autofocus
                    required
                />
            </div>
            
            <div class="form-group">
                <label>
                    <input type="checkbox" name="OTP_REMEMBER" value="Y" />
                    Запомнить это устройство на 30 дней
                </label>
            </div>
            
            <button type="submit" class="btn btn-primary">
                Подтвердить
            </button>
            
            <a href="?backup_code=Y" class="link-secondary">
                Использовать резервный код
            </a>
        </form>
    </div>
<?php else: ?>
    <!-- Обычная форма входа -->
<?php endif; ?>

Доверенные устройства

Битрикс позволяет «запомнить» устройство на определённый срок.

php
// Настройка в админке
// Проактивная защита → Одноразовые пароли → Доверенные устройства

// Параметры:
// - Срок действия: 30 дней (по умолчанию)
// - Привязка к IP: да/нет
// - Привязка к User-Agent: да/нет

Программное управление доверенными устройствами

php
use Bitrix\Security\Mfa\TrustedDevice;

// Добавить текущее устройство как доверенное
function trustCurrentDevice(int $userId, int $days = 30): void
{
    $device = new TrustedDevice();
    $device->setUserId($userId);
    $device->setDeviceHash(TrustedDevice::generateDeviceHash());
    $device->setIp($_SERVER['REMOTE_ADDR']);
    $device->setUserAgent($_SERVER['HTTP_USER_AGENT']);
    $device->setExpiresAt(new \DateTime("+{$days} days"));
    $device->save();
}

// Проверить, доверенное ли устройство
function isDeviceTrusted(int $userId): bool
{
    $deviceHash = TrustedDevice::generateDeviceHash();
    return TrustedDevice::isTrusted($userId, $deviceHash);
}

// Отозвать все доверенные устройства
function revokeAllTrustedDevices(int $userId): void
{
    TrustedDevice::deleteByUser($userId);
}

Мониторинг и алерты

Логирование событий 2FA

php
// /local/php_interface/init.php
use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandler(
    'security',
    'OnOtpVerifySuccess',
    function ($userId) {
        \CEventLog::Add([
            'SEVERITY' => 'INFO',
            'AUDIT_TYPE_ID' => 'OTP_SUCCESS',
            'MODULE_ID' => 'security',
            'ITEM_ID' => $userId,
            'DESCRIPTION' => 'Успешная проверка OTP',
        ]);
    }
);

EventManager::getInstance()->addEventHandler(
    'security',
    'OnOtpVerifyFail',
    function ($userId) {
        \CEventLog::Add([
            'SEVERITY' => 'WARNING',
            'AUDIT_TYPE_ID' => 'OTP_FAIL',
            'MODULE_ID' => 'security',
            'ITEM_ID' => $userId,
            'DESCRIPTION' => 'Неудачная проверка OTP',
        ]);
        
        // Алерт при множественных неудачах
        $failCount = getRecentOtpFailures($userId, 10); // за 10 минут
        if ($failCount >= 5) {
            sendSecurityAlert("Множественные неудачные OTP для пользователя {$userId}");
        }
    }
);

Итоги

Чеклист внедрения 2FA

  • Модуль security установлен и активен
  • 2FA обязательна для группы «Администраторы»
  • Все админы настроили свои аутентификаторы
  • Резервные коды сгенерированы и сохранены
  • Логирование событий 2FA включено
  • Есть процедура восстановления доступа

Что реально даёт 2FA

Таблицы вида «с 2FA фишинг бесполезен» встречаются часто, но они неточны, а неточность в вопросах безопасности приводит к ложному чувству защищённости. Разберём честно.

СценарийБез 2FAС 2FA (TOTP)
Пароль утёк из другой базыПолная компрометацияНе сработает
Подбор пароляВозможенПрактически бесполезен
Пароль подсмотрен или записанКомпрометацияНе сработает
Классический фишинг (сбор пароля)РаботаетНе сработает
Фишинг в реальном времениРаботаетРаботает
Перехват сессии после входаРаботаетРаботает
Вредоносный код на устройстве админаРаботаетРаботает
⚠️ Важно

Три сценария, от которых TOTP не защищает, и их стоит знать.

Фишинг в реальном времени. Поддельная страница входа, которая передаёт введённые логин, пароль и одноразовый код на настоящий сайт немедленно. Код действует около минуты — этого более чем достаточно. Такие наборы инструментов существуют и доступны; TOTP их не останавливает. Останавливают аппаратные ключи (WebAuthn/FIDO2), где подпись привязана к домену и на поддельном сайте не сработает.

Перехват уже установленной сессии. 2FA проверяется при входе; после него работает кука сессии. Украденная кука даёт доступ без всякого второго фактора — отсюда важность HttpOnly, Secure, привязки сессии и разумного времени её жизни.

Скомпрометированное устройство администратора. Если на машине работает вредоносный код, он дождётся легитимного входа и воспользуется готовой сессией.

Это не аргументы против 2FA — она закрывает самый частый сценарий и включать её нужно. Это аргументы против того, чтобы считать вопрос безопасности админки решённым после её включения.

💡 Совет

Самое слабое место внедрения — процедура восстановления доступа. Администратор потерял телефон, и дальше есть два плохих варианта: либо восстановление настолько простое, что им может воспользоваться злоумышленник (и тогда 2FA обходится через поддержку), либо настолько сложное, что доступ теряется вместе с телефоном.

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

Проверьте процедуру заранее, на тестовой учётной записи. Обнаруживать, что восстановление не работает, в момент, когда никто не может войти в админку, — плохой опыт.

Частые вопросы

Как включить двухфакторную аутентификацию в Битриксе?

Через модуль проактивной защиты: убедитесь, что модуль security установлен и активен, откройте раздел одноразовых паролей в настройках проактивной защиты и включите OTP для нужных групп. Битрикс поддерживает эту возможность из коробки начиная с версии 14.5. При следующем входе пользователь увидит форму настройки: установить приложение-аутентификатор, отсканировать QR-код, ввести проверочный код и сохранить резервные коды.

Какое приложение-аутентификатор выбрать?

Google Authenticator — простое и без облака, но при потере телефона коды не восстановить. Authy даёт облачный бэкап и работу на нескольких устройствах. Менеджеры паролей вроде 1Password держат коды рядом с паролями, что удобно, но кладёт оба фактора в одно место. Microsoft Authenticator удобен там, где уже используется учётная запись Microsoft.

Что делать при потере телефона с аутентификатором?

Использовать резервные коды — их выдают при настройке, и сохранить их нужно сразу, отдельно от телефона. Без них восстановление доступа означает отключение OTP администратором через админку или напрямую в базе, то есть требует другого администратора или доступа к серверу. Это тот случай, когда подготовка занимает минуту, а её отсутствие стоит рабочего дня.

От чего 2FA не защищает?

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

Нужны ли доверенные устройства?

Это компромисс между удобством и безопасностью. Запоминание устройства избавляет от ввода кода при каждом входе, что снижает соблазн отключить 2FA вовсе, но одновременно означает, что украденный ноутбук даёт доступ без второго фактора. Разумный вариант — ограниченный срок доверия и возможность отозвать все устройства одной кнопкой.

Кому включать 2FA в первую очередь?

Администраторам и всем, у кого есть доступ к разделам с персональными данными или деньгами. Массовое включение для всех пользователей сайта обычно приносит больше обращений в поддержку, чем безопасности, а вот учётные записи с правами на изменение кода, настроек и заказов — это ровно те, ради которых мера и вводится. И обязательно настройте уведомления о входах: 2FA снижает вероятность компрометации, но не отменяет необходимости знать о ней.