Китайские камеры Jovision и их OEM клоны. Мистификация безопасности

Так получилось, что для одного из проектов понадобилась управляемая система пространственного позиционирования целеуказателя. Серво-приводы различных производителей оказались довольно дорогими и было решено купить управляемую камеру и использовать встроенный сервопривод камеры для позиционирования. С PTZ камерами я дела никогда не имел, поэтому на пробу была приобретена камера J2000IP-CmPTZ-111v2.0, якобы российского производителя "3С-Групп" http://j2000.ru/.
Внимание! Публикация не является обзором камеры и скорее всего описывает разбор механизмов управления камерой предлагаемый производителем оборудования.

Итак камера J2000IP-CmPTZ-111v2.0, она же Jovision JVS-H411. Ничем не выдающаяся камера домашнего сегмента http://www.jovisioninc.com/index.php/ip-camera/wireless/jvs-h411.html
Как и большинство камер построена на чипе HiSilicon 3518E.
http://support.hkvstar.com/file/Hi3518E.pdf
image
Так как чип довольно распространён и к нему есть SDK, то производители поверх собранного ядра начинают "наворачивать" сверху свои специфические сервисы. Прошивки устройств обычно отличаются драйверами wifi модуля. Wifi модуль можно определить из названия прошивки взятой с адреса http://www.jovecloud.com/ipc/3518es/
jvs3518es-7601.bin — Ralink RT7601
jvs3518es-8188.bin — Realtek RTL8188
jvs3518es-9271.bin — Atheros AR9271

Прошивка в моём устройстве jvs3518es-7601.bin и валидна она для следующего списка устройств фирмы Jovision:

H411 J2000IP-CmPTZ-111-V2.0 H411V1_1 H411S-H1 H411V2 HC420S-H2 HC520D-H1 HC420-H2 H411-H1 H411KEDA AT-15H2 SW-H411V3 HZD-600DM AJL-H40610-S1 AJL-H40610-S2 JD-H40810

Итак. С моделью определились. Никакая это не российская разработка, как позиционирует её компания "3С-Групп", а просто OEM клон камеры большого китайского производителя.
Но если это клон и прошивка китайская, то значит и сервисы в ней зашиты китайские.
В принципе так и есть. Камера подразумевает регистрацию в облаке Jovision, подключения типа P2P, позволяет видеть изображение на своём телефоне и управлять камерой удалённо. Как любой сисадмин не доверяющий сторонним сервисам безопасности, тем более китайским, тем более видео, первое что я бы рекомендовал сделать — это поставить в камере шлюзом по умолчанию саму себя и использовать другие методы управления.

Для удалённого управления камерой производитель предоставляет OCX оснастку для IE(для контроля из локальной сети) и Android приложение(для контроля через сеть интернет).
Так как камеру планировалось использовать из-под Unix систем, то варианты с IE и Android отпали, как не подходящие под условия использования.

Никакого более менее доступного API в сети найдено не было, поэтому начали реверсить то, что имели в наличии.
OCX оснастка как оказалась использует 2 варианта управления:

  1. управление через закрытый ipc протокол.
  2. управление через встроенный thttpd сервер.

Первый вариант сначала исключили(потом вернулись к нему ради интереса), т.к. реверс проприетарного протокола мог бы затянуться надолго и начали копать второй вариант.
Оказалось, что все запросы к камере идут на один единственный URL

http://<camip>/cgi-bin/jvsweb.cgi

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

http://<camip>/cgi-bin/jvsweb.cgi?username=admin&password=password

И после этого должна следовать команда управления.
Но после того, как я добрался до внутренностей прошивки, я был сильно удивлён содержимому файла jvsweb.cgi

#!/bin/sh eval `./proccgi` echo Content-type: application/json #echo #echo $FORM_cmd #echo $FORM_action #echo $FORM_param #echo $FORM_username #echo $FORM_password #echo ./wagent $FORM_cmd $FORM_action "$FORM_param" $FORM_username $FORM_password

Маленькая программка proccgi парсит web запрос к серверу и конвертит его в переменные, которые далее "скармливаются" программе агенту, передающему эти данные в управляющую программу.
Как показало исследование поля username и password не влияют ни на что от слова СОВСЕМ. Важны только первые три параметра.
Главное, что из этого я хочу донести до всех читателей: КАМЕРА НЕБЕЗОПАСНА! и управлять ей может кто угодно находясь с ней в одной сети.
Продолжаем исследования.
Подключение к камере по telnet(адрес по умолчанию 192.8.8.8) осуществляется по фиксированному логину и паролю root/jvbzd, который нельзя поменять обычными методами!!!
Опять же подключиться может кто угодно. Именно по данной причине я первым делом убрал доступ камеры в облако. Если базовые политики безопасности сразу являются скомпрометированы, то нет смысла доверять чему-то более высокоуровневому.

Попробуем залезть еще поглубже.
Процесс загрузки камеры состоит из загрузки ядра, чтения базовых настроек системы, запуску проверялки-перехватчика портов и запуска самой программы управления.
Если с первыми двумя пунктами всё понятно, то с третьим пунктом возникает вопрос.
Перехватчик портов основываясь на списке жёстко зарезервированных под сервисы портов, проверяет из занятость и резервирует за собой. Программа управления представляет собой статически скомпилёный бинарник весом в 5 мегабайт, в котором "зашита" вся логика управления камерой.
Ядро камеры имеет встроенный watchdog и если от программы управления в нужный момент не пришёл alive сигнал, то камера автоматически перезагружается.
Для того чтобы запустить камеру в отладочном режиме необходимо сделать 3 шага:

  1. Перезагрузить камеру и в течении 5 секунд после начала перезагрузки зайти на камеру телнетом
  2. Запустить ps w и через kill "пристрелить" процессы startup.sh и /tmp/sctrl. startup.sh необходимо "стрелять первым", т.к. в строке следующей за запуском /tmp/sctrl стоит команда reboot
  3. Запустить /tmp/sctrl с ключами:
    • cmd=0/1 — включение командного интерфейса системы контроля
    • debug=0/1 — включение расширенного дебага

Все указанные действия необходимо выполнить в 10-15 секундный срок, до отработки watchdog. После запуска программы управления вы увидите лог работы, а также лог обработки входящих команд.
Программа управления делится на несколько частей:

  1. модуль управления по ipc
  2. модуль управления по http
  3. модуль подключения к облаку
  4. модуль обнаружения совместимых сетевых устройств
  5. модуль управления по интерфейсу onvif

Модуль управления по ipc работает постоянно и ожидает команд на порту 9101
Модуль управления по http реализован на свободном сервере thttpd, работает постоянно и ожидает команд на порту 80
Модуль подключения к облаку проверяет соединение каждые 10 секунд.
Модуль обнаружения сетевых устройств пытается найти рекордер
Модуль управления по интерфейсу onvif работает совместно с thttpd и предоставляет очень кривую и бедную поддержку управления.

Да! забыл написать. Камера предоставляет шифрование трафика между клиентом и камерой, но!!! ключ шифрования един на все прошивки и лежит в файле /tmp/encrypt!!!

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

http://<camip>/cgi-bin/jvsweb.cgi?cmd=webhelp

Вот список всех блоков управления камерой

cmd list and help information    mptz         mptz zoom [X] [Y] [ZOOM]   timer         display all timer list   stream         for stream test   account         account operation cmd   webalarm         alarm operation command   webmdetect         motion detect operation command   webprivacy         privacy operation command   webrecord         record operation command   webstorage         storage operation command   webstream         stream operation command   webifconfig         ifconfig operation command   webwifi         wifi operation command   webosd         osd operation command   websnapshot         Have a snapshot of the channel   webhelp         Display help info   webipcinfo         ipcinfo operation command   webdevinfo         webdevinfo operation command   webimage         image operation command   yst         yst operation command   system         websystem operation command   multimedia         multimedia operation command   ptz         ptz operation command   webaudio         webaudio operation command   redirect         redirect stdout stderror   webled         led control command   webad         audio detect   wdtoff         Manual close watchdog

Моей основной задачей было обеспечить чёткое позиционирование камеры, но к сожалению из-за программной реализации продукта оказалось, что сделать это невозможно. Почему ?

Интерфейс управления кинематикой PTZ работает по RS485 и не имеет каких-либо внешних датчиков и счётчиков для определения текущего положения камеры. Интерфейс передающий команды в PTZ передаёт в модуль ядра шаг на который необходимо повернуть двигатель в нужную сторону. Для определения сектора работы, при первичной инициализации, камера поворачивается в нулевое положение по обоим осям и начинает вращение в сторону увеличения координат. Определив конец сектора вращения горизонтальной координаты камера делит полученный сектор на 65536. То же самое происходит с вертикальной координатой. Таким образом получается внутренняя координатная сетка на основании которой происходит позиционирование камеры. Когда мы при помощи интерфейса управления передаём в камеру команды поворота, в камере считается и сохраняется только внутренний счётчик недоступный пользователю. Когда мы сохраняем Preset, то программа управления сохраняет текущие координаты в которых на данный момент находится камера и потом использует их для позиционирования. Чёткое точечное позиционирование пользователю недоступно.

Но не время сдаваться 🙂
Продолжаем копать возможности камеры.
За разбор входных данных в интерфейс управления отвечает библиотека cJSON https://github.com/DaveGamble/cJSON, таким образом в переменной param должна быть валидная JSON структура.

Строка запроса всегда выглядит так:

http://<camip>/cgi-bin/jvsweb.cgi?cmd=<cmd>&action=<action>&param={"key1":"value1","key2":"value2"}

На данный запрос камера обычно возвращает несколько строк в зависимости от результата

{"status":"ok","data":""} {"status":"param error","data":""} param error либо результат выполнения запроса

Распишу все найденные мной команды управления и их поля/параметры
Данные указанные в фигурных скобках содержат данные, которые необходимо поместить в поле param запроса.
Большинство команд поддерживают action=list для вывода текущих настроек.
Начнём с команды account

  • account
    Управление пользователями веб интерфейса системы

    list    # List all account with passwords add:    # add account     {"acID": "aborche","acPW": "123","acDescript":"test","Power":17} check:  # check password     {"acID":"aborche","acPW":"123"} modify: # modify account     {"acID":"aborche","acOldPW":"123","acNewPW":"1234"} del:    # delete account     {"acID":"aborche1"} count   # count accounts

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

    http://<camip>/cgi-bin/jvsweb.cgi?cmd=account&action=list

    а добавление пользователя

    http://<camip>/cgi-bin/jvsweb.cgi?cmd=account&action=add&param={"acID": "aborche","acPW": "123","acDescript":"test","Power":17}

  • webalarm
    Оповещения о срабатывании детекторов движения
    list    # List all alarms set:    # Set alarm     {"delay":10,"sender":"ipcmail@163.com","server":"smtp.163.com","username":"ipcmail","passwd":"ipcam71a",     "receiver0":"lfx@jovision.com","receiver1":"(null)","receiver2":"(null)","receiver3":"(null)"}

Остановимся на минуту на этих двух командах. Все получаемые с камеры данные являются открытыми и доступ происходит без логина и пароля!!!!
Поэтому если вы не хотите лишиться доступа к своему почтовому ящику(как пример), будьте осторожны и заведите второй ящик.

  • webmdetect
    Определение движения

    <ch> list   # List motion detects         # cmd=webmdetect&action=1 list         # cmd=webmdetect 1&action=list <ch> set:     {"bEnable":0,"nSensitivity":50,"nThreshold":15,"nRectNum":0,     "stRect":[{"x":0,"y":0","w":0,"h":0},         {"x":0,"y":0,"w":0,"h":0},         {"x":0,"y":0,"w":0,"h":0},         {"x":0,"y":0,"w":0,"h":0}],     "nDelay":10,"nStart":0,"bOutClient":0,"bOutEMail":0}

    Обратите внимание, что из-за кривизны разбора входных параметров можно беспрепятственно передавать любую длину команд с любыми параметрами. Так как камера имеет несколько каналов(видеопотоков), то часть команд может идти с номером канала.

  • webprivacy
    Определение приватной зоны на изображении, которую не нужно транслировать

    <ch> list   # List privacy zones         # cmd=webprivacy&action=1 list         # cmd=webprivacy 1&action=list <ch> set:   # Set privacy zone     {"bEnable":0,"stRect":[{"x":0,"y":0,"w":0,"h":0},     {"x":0,"y":0,"w":0,"h":0},     {"x":0,"y":0,"w":0,"h":0},     {"x":0,"y":0,"w":0,"h":0}]}

  • webrecord
    Настройки записи

            # cmd=webrecord&action=1 list         # cmd=webrecord 1&action=list <ch> list   # List settings <ch> set:   #     {"bEnable":1,"file_length":600,"timing_enable":0,"discon_enable":0,     "alarm_enable":0,"timing_start":0,"timing_stop":0,"disconnected":0,     "detecting":0,"alarming":0,"alarm_pre_record":6,"alarm_duration":10}

  • webstorage
    содержимое внешней карты памяти

    list    # List settings format  # Format storage

  • webstream
    Настройки потоков

            # cmd=webstream&action=1%20list         # cmd=webstream 1&action=list         # cmd=webstream -c<chid> <streamid>&action=ability         # cmd=webstream -c1 1&action=ability <ch> list   # List streams <ch> set:   # Set stream settings     {"bEnable":1,   "bAudioEn":1,   "viWidth":1280, "viHeight":720,     "width":1280,   "height":720,   "framerate":20, "bitrate":1024,     "ngop_s":4, "rcMode":1, "encLevel":1,   "quality":40,     "minQP":24, "maxQP":46} <ch> resolution # Get stream possible resolution <ch> ability    # Get stream settings requestidr  # ?????

  • webifconfig
    Настройки сетевого интерфейса

    list    # Get interfaces configuration set:    # Set interfaces configuration     {"inet":"dhcp",     "eth":         {"name":"eth0","bDHCP":1,"addr":"","mask":"","gateway":"0.0.0.0",         "mac":"02:00:01:01:01:12","dns":"8.8.8.8"},     "pppoe":         {"name":"ppp0","username":"x","passwd":"1"},     "wifiap":         {"name":"","passwd":"","quality":0,"keystat":0,"iestat":""}     } scan    # ReScan wifi networks

  • webwifi
    Управление wifi подключением
    list    # List wifi networks connect:    # Connect to network     {"name":"ZyXEL53",  "passwd":"",    "quality":2,     "keystat":1,    "iestat":"\u0004\u0002"} changemode:     ????

Обратите внимание, что при помощи команд webwifi и webifconfig можно спокойно просканировать рядом находящиеся WIFI сети и подключиться к ним. Таким образом подконтрольная камера может спокойно шпионить за окружающей обстановкой

  • webosd
    Управление идентификатором камеры на видео

    <ch> list   # Get channel info <ch> set:     {"bShowOSD":1,  "timeFormat":"MM/DD/YYYY hh:mm:ss", "position":1,     "timePos":2,    "channelName":"HD IPC", "osdbInvColEn":1,"bLargeOSD":1}

  • webipcinfo
    Информация о устройстве

    list    # Get device info set:     {   "type": "J2000IP-CmPTZ-111-V2.0",         "product":  "JVS-HI3518ES-7601",         "version":  "V2.2.4402",         "acDevName":    "HD IPC",         "nickName": "",         "sn":   36430,         "ystID":    xxxxxxxxxx,         "nDeviceInfo":  [],         "nLanguage":    1,         "date": "2016-10-22 14:31:43",         "bSntp":    1,         "sntpInterval": 24,         "ntpServer":    "192.168.205.1",         "enableStreamWatchDog": 1,         "tz":   3,         "bDST": 0,         "bIPSelfAdapt": 1,         "rebootDay":    0,         "rebootHour":   1,         "bRestriction": 1,         "portUsed": "8099,554,23,8127,51994,55434,6666,8732,58434,3702,9100,9104,9106,57241,4001,6072,8899,1998,17",         "osdText":  ["", "", "", "", "", ""],         "osdX": 0,         "osdY": 0,         "osdSize":  32,         "lcmsServer":   ""} settime <datetime>   system <reboot/reset/softreset>

    Функция позволяет ребутить или сбрасывать устройство

    http://<camip>/cgi-bin/jvsweb.cgi?cmd=webipcinfo&action=system reboot

  • webdevinfo

    list    # get device info set     {   "type": "ipc",         "hardware": "JVS-HI3518ES-7601",         "firmware": "V2.2.4402",         "manufacture":  "JVS-HI3518ES-7601",         "sn":   "XXXXXXXXXX",         "model":    "ipc-module",         "channelCnt":   1,         "streamCnt":    3,         "ystChannelNo": [1, 2, 3, ..... 0],         "name": "HD IPC",         "date": "2016-12-26 20:55:23",         "bSntp":    1,         "sntpInterval": 24,         "ntpServer":    "ntp.fudan.edu.cn",         "tz":   3,         "bDST": 0     } settime <datetime> settime 2012-06-07 13:58:00 system <reboot/reset/softreset>

  • webimage
    Настройка параметров изображения

    list set:     {"contrast":    135,     "brightness":   135,     "saturation":   135,     "sharpen":  255,     "exposureMax":  3,     "exposureMin":  100000,     "scene":    0,     "daynightMode": 0,     "dayStart": [{         "hour": 6,         "minute":   0     }],     "dayEnd":   [{         "hour": 18,         "minute":   0     }],     "bEnableAWB":   1,     "bEnableMI":    0,     "bEnableST":    0,     "bEnableNoC":   0,     "bEnableWDynamic":  0,     "bNightOptimization":   1,     "bAutoLowFrameEn":  0}

  • yst
    Информация о потоках для удалённого управления

    list set:     {"strGroup":    "B",     "nID":  XXXXXXXXX,     "nPort":    9101,     "nStatus":  2,     "bActiving":    1,     "nYSTPeriod":   10,     "bTransmit":    "\u0001",     "eLANModel":    0,     "bWebServer":   1,     "nWebPort": 80,     "nPictureType": 3,     "nPictureTypeOld":  1} get_port    # get control port get_video   # get video streams

    Остановимся на данной команде. Эта команда описывает настройки видеопотоков для удалённого управления через OCX или телефон.
    Врядли что-то из этих данных вам будет полезно кроме двух команд

    http://<camip>/cgi-bin/jvsweb.cgi?cmd=yst&action=get_port http://<camip>/cgi-bin/jvsweb.cgi?cmd=yst&action=get_video

    Первая покажет порт управления системой и параметры порта
    Вторая покажет текущие видеопотоки имеющиеся в системе.
    Вывод второй команды обычно такой

    rtsp://<camip>/live0.264 rtsp://<camip>/live1.264

  • ptz
    Управление камерой

    move:   # range = step(255*x(y)), sign +/- = direction     {"chnid":0,"x":[0.01..1],"y":[0.01..1]}     x,y - moving speed     0 - stop move move_auto: # set move speed     {"chnid":1,"s":0.5} preset: #preset control     {"chnid":0,"type":n,"presetid":p,"name":name}     type:   0="list"         1="Save Preset"         2="Delete Preset"         3="Apply Preset"     param={"chnid":1,"type":1,"presetid":1,"name":"preset 1"} - Save Preset 1 with name "preset 1" lens: # lens and picture control     {"type":n,"value":v}     type:   0="aperture"         1="focus"         2="magnify"     value:  0.01..1 patrol:     {"status":"ok","data":[{"id":0,"presetid": 1,"name":"1111","staytime":10},{"id":1,"presetid": 2,"name":"2222","staytime":10}]}     type:   0="list"         1="Save Patrol"         2="Delete Patrol"         3="Start Patrol"         4="Stop Patrol"

  • mptz
    left right up down stop preset locatePreset aux # param=auxnum/-auxnum turn aux on/off dropon dropoff sensor zoom # Not working

Команды ptz и mptz были основной причиной начала расковыривания прошивки.

http://<camip>/cgi-bin/jvsweb.cgi?cmd=ptz&action=move&param=["chnid":1,"x":0,"y":-0.5] http://<camip>/cgi-bin/jvsweb.cgi?cmd=mptz&action=down

Обе команды дают камере команду повернуться вниз. В первом случае мы указываем скорость с которой будет опускаться камера. Скорость рассчитывается как 255 умноженное на значение скорости. Таким образом при значении скорости равной 0.01 камера будет опускаться вниз со скоростью 2 точки на 1 тик. Во втором случае камера будет опускаться со скоростью 100 точек на 1 тик. Значение тика я пока не выяснил. Нужно замерить.
Камера будет опускаться до тех пор пока не достигнет нулевой точки, либо пока не будет получена следующая команда

http://<camip>/cgi-bin/jvsweb.cgi?cmd=ptz&action=move&param=["chnid":1,"x":0,"y":0] http://<camip>/cgi-bin/jvsweb.cgi?cmd=mptz&action=stop

preset и locatePreset служат для быстрого добавления и вызова точек позиционирования

http://<camip>/cgi-bin/jvsweb.cgi?cmd=mptz&action=preset 1 http://<camip>/cgi-bin/jvsweb.cgi?cmd=mptz&action=locatePreset 1

  • stream
    Управление энкодером видеопотоков

    stream CMD CHANNELID stream set CHANNELID TYPE VALUE CMD:     start   start the stream     stop    stop the stream     flush   flush the stream     restart restart the stream     set     set param     debug   if be 1, print the received stream package TYPE:     width - resolution width     height - resolution height     framerate - framerate such as 30,25,20,15,10...     nGOP - I frame between     bitrate - bitrate with unit of Kbit Per Second

  • multimedia
    Управление изображением

    imageget:     {"chnid":1,"type":0}     type:          0   contrast         1   brightness         2   saturation         3   sharpness imageset:     {"chnid":1,"type":0}     type:          0   contrast         1   brightness         2   saturation         3   sharpness

    Перед началом изменения параметров, рекомендуется сделать imageget для каждой настройки, после этого сделать изменения и сделать imageset

  • webaudio
    Управление звуком

    list set:     {         "sampleRate":   8000,         "bitWidth":     1,         "encType":      0,         "level":        2,         "muted":        1,         "micGain":      69     }

  • webad
    Определение звука
    list set:    {     "bEnable":      1,     "bEnableRecord":        1,     "nStart":       0,     "bOutClient":   1,     "bOutEMail":    1,     "bOutVMS":      1,     "bBuzzing":     1,     "ADThreshold":  80,     "ADTimeInterval":       60,     "ADPercentage": 30     }
  • webled
    Управление светодиодами
    list set:     0 - turn off     1 - turn on

В принципе это почти весь набор команд обеспечивающих взаимодействие с камерой.
Остальные команды описывать смысла нет, т.к. они обеспечивают вывод отладочной информации в консоль.

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

На очереди у меня стоит камера TENVIS JPT3815W, посмотрим что есть у неё.
Спасибо за уделенное время на чтение статьи, надеюсь она была для вас полезной.

PS: если нужна информация о дешифровке прошивок Jovision, то могу выложить.

© Aborche 2016

Aborche
ссылка на оригинал статьи https://habrahabr.ru/post/318572/

Один комментарий к “Китайские камеры Jovision и их OEM клоны. Мистификация безопасности

  1. Ну не даром эти камеры так дешево стоят, по сравнению с тем же hikvision, хотя у HV тоже был косяк с дырой в прошивке, но там хотя бы техподдержка есть.

Добавить комментарий для Кузьмич Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *