Illustration by Ondřej Šponiar

An unlikely XXE in Hikvision’s Remote Access Camera Cloud

TLDR: While trying to get admin credentials on my locked down Elisa Live IP camera, I discovered a XML External Entity (XXE) vulnerability on one of the backend systems of HiKVision, the manufacturer of the camera which is the market leader on IP cameras and PVRs.

Insecurity and the IoT era go hand in hand. A quick search in google will reveal hundreds of white papers and articles that have been published over the last few years.

About two months ago I had a free weekend so I wanted to play around with a cloud camera. I searched in Amazon for a cheap one with no published security vulnerabilities. I found this one: Elisa Live 720p HD IP Camera.

I will try to keep this post short so I will focus on the discovery of the XXE. I will not detail all the steps that I took to investigate the camera itself, only the relevant parts that lead to the XXE discovery.

The Camera

The camera itself is a white-labelled RC8221 manufactured by Hikvision, a $20bn company that is the market leader (~20%) in the surveillance products industry. Elisa, a Finnish company, provides a cloud app that you can access in order to view the live stream of your camera.

As the trend dictates, you cannot get access to the camera itself without going through their cloud platform. In other words, the camera’s stream is uploaded to their backend system and you access the stream through a web or mobile app.

Getting my feet wet

I connected the camera through its Ethernet interface to my lab and started intercepting network traffic. If you ever want experiment with IoT devices I highly recommend that for your first round of investigation you do not have an active internet connection. Some devices are shipped with old/insecure firmware, the very first thing they will do is check if an update is available.

Wireshark revealed two interesting and unencrypted calls:

POST Request to

A POST request to, Looks like a base64 encoded password. Let’s note this down for later.

And a GET request that downloaded the updated firmware from an s3 bucket.
The firmware can be downloaded here.

GET request

(not)Getting Access to my Camera

A quick nmap scan showed a few open ports, including a web server with a login form. After trying a few default username/password combinations common for hikvision cameras, I quickly realised that I wasn’t going to go anywhere. The controller that accepts the credentials is protected with HTTP Digest Access Authentication, a unique feature of this firmware.

Playing around with the firmware using binwalk and hiktools,I was able to extract some interesting information, but nothing regarding the Digest Authentication. Just for reference, the root password is hiklinux, these are the contents of the /etc/passwd file:

The passwd file

The SSH port was closed so I couldn’t take advantage of this. I have to note that on my very first portscan before updating the firmware ssh was open.

At this point I backtracked and tried explore other avenues.

Getting Access to your Camera

Going back to the first POST request we can see that it includes a base64 encoded string. Unfortunately it decodes to garbage, meaning that it’s probably symmetrically encrypted. The key has to be somewhere in the firmware, it’s just a matter of finding it. I didn’t verify if this password is used to authenticate the camera to the server, or if this is a password that is generated by the camera upon boot and submitted to Hikvision.

I have to admit that I was a bit discouraged with my progress. Over two days spent with little to show. I quickly browsed Hikvision’s website and found this:

Send E-mail to to report the security flaw you find and we will contact you as soon as possible. To protect information security for users and enterprise, please do not publish or spread the flaw. HSRC will reward the reporter according to the Hikvision Security Flaw Assessment.

Cool, a bug bounty program. Let’s play around with the POST request.

As this is an XML post request, the first thing I tried was to see if we can request a local or external file with the SYSTEM entity. The local file method didn’t work, so I fired up a VPS and waited for incoming connections. It worked:

Testing for XXE
We got a new friend

Things were starting to get interesting. Since we can use the SYSTEM entity to load external files, let’s try to pass a malicious DTD that will call back to our VPS with the contents of a file, say /etc/hosts.

A great tool that automates this procedure is XXEinjector.

Retrieving the contents for /etc/hosts

Success. We can read arbitrary files on the server. But what permissions does the Tomcat server run with? We were able to get the contents of /etc/shadow, so root.

At this point I stopped and started the process of disclosing the findings to Hikvision. If I was a malicious attacker, I would probably continue by fully enumerating the 10 servers (The vulnerability existed in all geographically distributed API servers of If getting the Tomcat database connection strings didn’t lead anywhere, there probably would be more things that one could look for like scripts that connect to other server with hardcoded credentials.

Ultimately, It wouldn’t be that difficult to get access to more than 100k cloud based cameras and DVRs.

The vulnerable servers are part of the backend system of , a service that Hikvision offers to access your PVRs and Cameras via the web.

Vendor communication timeline and bounty:

  • 25/8/16: Send first email to HSRC
  • 30/8/16: No reply from HSRC, send a quick email to verify receipt
  • 6/9/16: Send a new email including marketing and PR Hikvision contacts
  • 7/9/16: HSRC acknowledged receipt and requested further info
  • 8/9/16: Hikvision fixed the vulnerability and asked me to re-test it
  • 25/9/16: Received my bounty by post. A 69$ cloud camera.
  • 25/9/16: (╯°□°)╯︵ ┻━┻


If you are accepting XML content, make sure you are not vulnerable to XXE. Also make sure you use HTTPS for EVERYTHING, I cannot think of any reason to not do so.