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

Так вийшло, що для одного з проектів знадобилася керована система просторового позиціонування целеуказателя. Сервоприводи різних виробників виявилися досить дорогими і було вирішено купити керовану камеру і використовувати вбудований сервопривід камери для позиціонування. З PTZ камерами я справи ніколи не мав, тому на пробу була придбана камера J2000IP-CmPTZ-111v2.0, нібито російського виробника "3С-Груп".
Увага! Публікація не є оглядом камери і швидше за все описує розбір механізмів управління камерою пропонований виробником обладнання.
Отже камера J2000IP-CmPTZ-111v2.0, вона ж Jovision JVS-H411. Нічим не видатна камера домашнього сегмента. Як і більшість камер побудована на чіпі HiSilicon 3518E.
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 command operation
webmdetect
motion detect command operation
webprivacy
privacy command operation
webrecord
record command operation
webstorage
storage command operation
webstream
stream command operation
webifconfig
ifconfig command operation
webwifi
wifi command operation
webosd
osd command operation
websnapshot
Have a snapshot of the channel
webhelp
Display help info
webipcinfo
ipcinfo command operation
webdevinfo
webdevinfo command operation
webimage
image command operation
yst
yst command operation
system
 websystem command operation
multimedia
multimedia command operation
ptz
ptz command operation
webaudio
webaudio command operation
redirect
redirect stdout stderror
webled
led control command
webad
audio detect
wdtoff
Manual close watchdog

Моїм основним завданням було забезпечити чітке позиціонування камери, але нажаль за програмної реалізації продукту виявилося, що зробити це неможливо. Чому ?
Інтерфейс управління кінематикою PTZ працює по RS485 і не має яких-небудь зовнішніх датчиків і лічильників для визначення поточного положення камери. Інтерфейс передає команди в PTZ передає в модуль ядра крок на який необхідно повернути двигун в потрібну сторону. Для визначення сектору роботи, при первинній ініціалізації, камера повертається в нульове положення по обом осях і починає обертання в бік збільшення координат. Визначивши кінець сектора обертання горизонтальної координати камера ділить отриманий сектор на 65536. Те ж саме відбувається з вертикальною координатою. Таким чином виходить внутрішня координатна сітка на підставі якої відбувається позиціонування камери. Коли ми за допомогою інтерфейсу управління передаємо в камеру команди повороту, в камері вважається і зберігається тільки внутрішній лічильник користувачу недоступний. Коли ми зберігаємо Preset, то програма управління зберігає поточні координати в яких на даний момент знаходиться камера і потім використовує їх для позиціонування. Чітке точкове позиціонування користувачу недоступний.
Але не час здаватися :) Продовжуємо копати можливості камери. За розбір вхідних даних в інтерфейс управління відповідає бібліотека 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 # privacy List 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 # storage Format

  • 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 configuration interfaces
{"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 info channel
<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=reboot system

  • 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 port control
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 speed move
{"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 VALUE TYPE
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 received the 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
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.