Fixing RTSP in a Vivotek camera

Arseni Mourzenko
Founder and lead developer
176
articles
July 1, 2020
Tags: hardware 11

I own a Viv­otek cam­era. It ap­pears that I haven't been to se­ri­ous up­dat­ing the firmware—but nei­ther is the man­u­fac­tur­er—since the cam­era was bought in 2015, but didn't have the lat­est firmware re­leased in... 2014.

Al­though the de­scrip­tion of the “new” firmware fea­tured no bug­fix­es, I still de­cid­ed to in­stall it. I'm not sure if it made some­thing bet­ter, but what's for sure is that it broke RTSP. It just went down, port 554 un­reach­able.

Al­though I con­tact­ed Viv­otek's sup­port, I thought that fig­ur­ing out the prob­lem my­self could prob­a­bly be a faster al­ter­na­tive. With­out much sur­prise, I found that a pop­u­lar vul­ner­a­bil­i­ty af­fect­ed my mod­el of the cam­era as well, and know­ing the pass­word of an ad­min­is­tra­tor—that is my own pass­word—I got my­self telnet ac­cess to the de­vice. This was easy:

  1. Go to the web in­ter­face and walk through the pages un­til an HTTP call is made to a CGI script.
  2. From the net­work pan­el, copy the net­work re­quest as a CURL com­mand.
  3. Mod­i­fy it ac­cord­ing­ly by chang­ing the URI to /cgi-bin/admin/mod_inetd.cgi?telnet=on. It looks like this is the only change I had to do.

In­deed, nmap hap­pi­ly dis­played that tel­net's port 23 was now open, and I was able to con­nect with my ad­min­is­tra­tor cre­den­tials. The next thing was to fig­ure out what hap­pened.

My first thought was that the firmware hard­ened the iptables rules, but it ap­peared that it wasn't the case. The files in­side /var/log weren't par­tic­u­lar­ly in­ter­est­ing. Af­ter a bit of search­ing and thanks to netstat -tulpn, I found that noth­ing was lis­ten­ing on port 554.

Run­ning /etc/init.d/rtsps start was show­ing a bunch of er­rors, but not what I want­ed. It took a few min­utes to un­der­stand that, un­der the hood, it was run­ning the fol­low­ing script:

/usr/sbin/rtsps \
    -a 10.0.0.92 \
    -c /etc/conf.d/config_streamserver.xml \
    -q \
    /etc/conf.d/config_qos.xml \
    -d

Run­ning the script man­u­al­ly and re­mov­ing the -q (stand­ing for qui­et) and -d (stand­ing for dae­mon), I got the fol­low­ing out­put:

[StreamingServer_Initial]ChannelNumber 1, PerChannelStreamNumber 2
Addon Caching 0x40137100
Addon Caching 0x40137100
Addon Caching fail!
Addon Caching fail!
Addon Caching 0x4120f080
Addon Caching fail!
Addon Caching fail!
Parse video media info failed for config file /etc/conf.d/config_streamserver.xml!
config file /etc/conf.d/config_streamserver.xml parse failed
initial rtsp server fail

In­spect­ing the XML file, there was a sus­pi­cious thing. There is a block /root/network/rtsp with a lot of op­tions (in­clud­ing the port and the au­then­ti­ca­tion), and among oth­ers, it con­tains four blocks: <s0>, <s1>, <s2>, and <s3>. The first two spec­i­fy the streams live.sdp and live2.sdp like this:

<s0>
    <enable>1</enable>
    <accessname>live.sdp</accessname>
    <videotrack>0</videotrack>
    <audiotrack>-1</audiotrack>
    <metadatatrack>0</metadatatrack>
    <multicast>
        <alwaysmulticast>0</alwaysmulticast>
        <videoport>5560</videoport>
        <audioport>5562</audioport>
        <ipaddress>239.128.1.99</ipaddress>
        <metadataport>6560</metadataport>
        <audioextraipaddress>239.128.1.99</audioextraipaddress>
        <ttl>15</ttl>
        <vvtkextension>1</vvtkextension>
    </multicast>
</s0>

but the next two blocks look like this:

<s2>
    <enable>1</enable>
    <accessname></accessname>
    <videotrack>2</videotrack>
    <audiotrack></audiotrack>
</s2>

Wait? An en­abled stream with ab­solute­ly no in­for­ma­tion in­side? That's weird!

Set­ting <enable> to zero didn't help: /usr/sbin/rtsps con­tin­ued to claim that it can­not parse the file. How­ev­er, adding dum­my con­tent to the emp­ty nodes helped:

<s2>
    <enable>0</enable>
    <accessname>abc</accessname>
    <videotrack>2</videotrack>
    <audiotrack>abc</audiotrack>
</s2>

Es­sen­tial­ly, the pars­er is un­able to parse an XML block which doesn't have any con­tent. That's sad. Any­way, I got rid of <s2> and <s3>, and it seems to be work­ing now.


Viv­otek's sup­port ap­peared to be as great as one would ex­pect. I con­tact­ed them on the 1st of June, case num­ber 00078251. A month lat­er, there is still no re­sponse. Good job, guys.

On 24th of June, I sent them the fol­low­ing mes­sage:

Hi,
Is this ex­pect­ed that you don't even both­er an­swer­ing your cus­tomers' ques­tions? I thought the sup­port was just need­ing some time to an­swer, but three weeks with ab­solute­ly no up­dates is plain­ly im­po­lite.

Let's see if men­tion­ing the fact that some­one is im­po­lite makes this per­son less im­po­lite.