Saturday, July 1, 2017

Getting still image URL/URI of an ipcam OR just how to query onvif ip cameras

The net is full of to much TLDR info about ipcams...
Here is a short tutorial on running ONVIF queries to your ipcam to check which URLs do what.

ONVIF is a universal spec that tries to unify function calls to all supported ip cameras.
The problem is ONVIF organization is really the type of "we like to document a lot but not give short examples on how to use" type of org (maybe they should start thinking in the direction of open sourcing and supporting sites that try to explain their specs instead of hunting them down for posting a spec that is hidden in their own "membership" areas on their site)

So here is the short "Hello World" on ONVIF and ipcams:

Lets go through a learning experience - i have a cheap ali express ip cam and i want to figure out which cam URLs are used for streaming video and which cam URLs can give me a still image.

I want this because i want to port forward these specific ports and be able to access them directly and not via some P2P Chinese service app that wants all permissions on my android...(RTSP streaming video can be opened on many standard android apps and on vlc)

STEPS:

1. Connect

Physically connect the cam to the router on your home LAN using an ethernet cable - fairly easy
Note that there are wifi ipcams and ethernet ipcams - both have an option to connect an ethernet cable
The good ones will be pre-configured to get an IP from DHCP
The bad ones will have some preconfigured ip address, but they can be changed to DHCP, you just need to connect to their http address and change it (wait but i don't know their IP ....?! - try changing your router to 10.0.0.X subnet or 192.168.1.X subnet and connecting just a computer and your cam, then see next section on how to find them)

2. Discover ip/port 

Lets find the ip and port of the ONVIF service on the cam -
First, how to check i found the correct ip and port-
just enter in your browser and see a SOAP response like this:
for example enter: http://192.168.14.41:8899/

and get:

SOAP-ENV:ClientHTTP GET method not implemented

that means we found it (never mind about the error - we will see about that later)

So how to find the ip/port:
option A: if you know how to enter your router's http and check connected clients you can do that to find the IP, then you will have to scan that ip or try some well known ONVIF ports (e.g. 8899/1018)

option B: install "Fing" on your android cellphone - it will scan your local net and find it. again you will need to find the correct port

option C: install "Onvif device manager" or "iSpy" on your windows machine - they will scan your net and ports and find the ipcams and their onvif ports for you

3. Lets talk Onvif language with our cam-

Onvif speaks SOAP protocol - we will need a browser add-on to make life easier for us because we are too lazy to program stuff (or write long command lines with 'curl') -

In firefox, go to add-ons and click extensions, and add "RESTClient" extension +restart firefox.
Lets start by telling the device we want some general information -
lets assume my ip/port are 192.168.14.51:8899

Click on the RESTClient red rectangular button on the top of the browser and you will get this screen:


When you enter a URL in the browser address bar it uses http GET protocol. SOAP uses http POST protocol, which besides the URL has a "BODY" part too - so  we will use the add-on to sent the POST commands (this can be done in linux/windows command line using "curl" too).

change the "Method" to POST
in the URL put http://192.168.14.51:8899
in the BODY put:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
 xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<SOAP-ENV:Body>
    <tds:GetDeviceInformation/>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


 


click "SEND"

on the bottom part in "Response" change the tab to "Response Body (highlight)"
skip all the bloated SOAP-ENV xml shit, and in the bottom you will see something like:

<SOAP-ENV:Body>
 <tds:GetDeviceInformationResponse>
   <tds:Manufacturer>H264</tds:Manufacturer>
   <tds:Model>50H20L_S39</tds:Model>
   <tds:FirmwareVersion>V4.02.R11.00002520.10010.242900.ONVIF 2.4</tds:FirmwareVersion>
   <tds:SerialNumber>1b011f97f22424de</tds:SerialNumber>
   <tds:HardwareId>00001</tds:HardwareId>
 </tds:GetDeviceInformationResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>



Great ! it works ! (if not, then your ip/port are not correct or your ip camera 
does not support onvif)

4. Check video stream URLs

everything same as before just change the body:


<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl">
   <soap:Body>
      <trt:GetProfiles/>
   </soap:Body>
</soap:Envelope>

  
    

click SEND

as usual, skip all the soap shit and got to the bottom of the response (in the response body tab not response headers tab!)

you will get a list a profiles with their tokens and resolutions etc...:

<SOAP-ENV:Body>
 <trt:GetProfilesResponse>
   <trt:Profiles fixed="true" token="000">
     <tt:Name>Profile_000</tt:Name>
     <tt:VideoSourceConfiguration token="000">
       <tt:Name>VideoS_000</tt:Name>
       <tt:UseCount>3</tt:UseCount>
       <tt:SourceToken>000</tt:SourceToken>
       <tt:Bounds height="1080" width="1920" y="0" x="0">
       </tt:Bounds>
     </tt:VideoSourceConfiguration>
     <tt:AudioSourceConfiguration token="000">
       <tt:Name>Audio_000</tt:Name>
       <tt:UseCount>2</tt:UseCount>
       <tt:SourceToken>000</tt:SourceToken>
     </tt:AudioSourceConfiguration>
     <tt:VideoEncoderConfiguration token="000">
       <tt:Name>VideoE_000</tt:Name>
       <tt:UseCount>1</tt:UseCount>
       <tt:Encoding>H264</tt:Encoding>
       <tt:Resolution>
         <tt:Width>1920</tt:Width>
         <tt:Height>1080</tt:Height>
       </tt:Resolution>
       <tt:Quality>4</tt:Quality>

:
<----cut ----="" here="" response="">

now lets get the URL of a specific profile token ("000"). Send this body:
 
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema"> <soap:Body> <trt:GetStreamUri> <trt:StreamSetup> <tt:Stream>RTP-Unicast</tt:Stream> <tt:Transport> <tt:Protocol>UDP</tt:Protocol> </Transport> </trt:StreamSetup> <trt:ProfileToken>000</trt:ProfileToken> </trt:GetStreamUri> </soap:Body> </soap:Envelope>

and you get this kind of response containing the URL:
<SOAP-ENV:Body>
  <trt:GetStreamUriResponse>
    <trt:MediaUri>
      <tt:Uri>rtsp://192.168.14.51:554/user=admin_password=1234_channel=1_stream=0.sdp?real_stream</tt:Uri>
      <tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
      <tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
      <tt:Timeout>PT10S</tt:Timeout>
    </trt:MediaUri>
  </trt:GetStreamUriResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>



lets test it:
open it (rtsp://192.168.14.51:554/user=admin_password=1234_channel=1_stream=0.sdp?real_stream)
in VLC (window/android) or some other RTSP Player (i like android VXG RTSP player)
it should show the live stream
(note vlc tends to crash some times. try a different app or VLC beta if this happens)

5. check still image (jpg) URL

send this body (update the profile token id to yours):
 
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema"> <soap:Body> <trt:GetSnapshotUri > <trt:ProfileToken>000</trt:ProfileToken> </trt:GetSnapshotUri> </soap:Body> </soap:Envelope>

you should get something like:

<SOAP-ENV:Body>
 <trt:GetSnapshotUriResponse>
   <trt:MediaUri>
     <tt:Uri>http://192.168.14.51/webcapture.jpg?command=snap&amp;channel=1</tt:Uri>
     <tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
     <tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
     <tt:Timeout>PT10S</tt:Timeout>
   </trt:MediaUri>
 </trt:GetSnapshotUriResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>





Paste the URL in the browser URL section it check if it works ... :)

6. Other cool stuff you can do with onvif

There are a lot of things you can do with onvif
A spec PDF can be found here:
http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf
(openipcam is a great resource site)
skip directly to "appendix B2" with the SOAP examples.
I am sure you will manage from there ...


7. Security

You ip cam is a basically a linux box. lately too many ip cams have been 
victims of hosting malware/botnet/viruses.

These cams can easily hide a program waiting for a C&C server to tell them to start blasting 
an IP with denial of service packets or just be used as proxy for hacking activities.

I recommend - reserve your ip cam a dedicated ip in your router or just assign it a 
static ip + set firewall rules in your router not to let any packet in/out (especially out)
if it is not on the port you are using.

Also change the defaul user/passwords

Also - from time to time bring up wireshark on your localnet and just look at the traffic.



 

2 comments:

  1. Super useful article, thank you :)

    I have a 'V380E' camera which this has helped me to get running with VLC.

    On the subject of blocking it from using the Internet - yes 100% agree. These things are a botnet-by-design - most of https://pierrekim.github.io/blog/2017-03-08-camera-goahead-0day.html still applies

    I blocked all traffic from and to mine, but then the time would always be stuck in 1970. I noticed with tcpdump that one of the many NTP servers it tries to reach is 'time.nasa.gov'.

    I set up a fake DNS entry on my local resolver for time.nasa.gov to point to an NTP server on the local network, and hey presto the time works again :)

    ReplyDelete

Feel free to comment. No links/URLs allowed in comments.