formigarafa / robotito

Terminal shell accessible through a jabber connection
MIT License
72 stars 18 forks source link

Research: Are you using it? #4

Open formigarafa opened 8 years ago

formigarafa commented 8 years ago

Please leave a :+1: to let me know who are using Robo-TiTO.

If you have any concerns, suggestion or even complaint, now is the time and this is the place.

I have been noticing some posts and comments about the project around the web and I would like to have your opinion to guide my the next steps.

thanks.

damionx7 commented 8 years ago

Yes I am using it . And it works flawlessly . Just Add rvm instructions for noobies :)

FrederikLauber commented 7 years ago

Maybe I am to stupi dbut how does this one time password thing work? Can't I just bypass that and only allow commands from a predefined jid? I think there is no support for encryption, so if someone can fake my jid, he can also just man in the middle me, no?

formigarafa commented 7 years ago

Hello @FrederikLauber, The One Time Password resolve the problem of someone looking over your shoulders while you type a password. As you might have noticed this has been added recently, and resolves this issue very well. If someone could fake your jid (including the resource part) after you provide a password and before you close your session, well, yes, they would have access to your very same session. You would probably see other messages/responses being sent around. I have never suffered a man-in-the-middle attack, maybe just because no one cares about where I use this client on. BTW, I, in no way, think this as a ssh replacement. This is more like a router port redirection replacement. In one of my experiments I have made it to run only specific commands that would only open a ssh reverse tunnel. It is not hard to achieve if you think you will be safer that manner. In another hand, at this very same recent additions I have extracted the client in a way that it would be trivial to replace by another solution than Jabber/XMPP. I have thought about Slack, initially, but if you could suggest any secure IM protocol, maybe we could give it a go. What do you think?

FrederikLauber commented 7 years ago

Still, why have the password in the first place? Assuming you cannot fake the jid: Why have the password? Even if someone saw your account name, he cannot do anything with it because he does not know your password of your jabber account. Assuming he can fake your jid (basically meaning he is your jabber provider), a password does not help.

Ended up just writing my own bot in python.

formigarafa commented 7 years ago

@FrederikLauber If you try to talk with the bot using a newly created google hangouts account the JID does not match your email. I don't know if that JID (2fn2zs1hq4x5z033ivf4cuwiwi@public.talk.google.com/lcsw_hangouts_4B9A8524) is even constant across the lifetime of the account. Besides the fact it would be a burden to the user to find out what is the actual JID being used by himself behind the scenes. So I decided to give up on the whitelist as a authentication option for me. Is the code for your bot public available?

FrederikLauber commented 7 years ago

Ah that makes sense. I am using a "proper" xmpp provider so I basically have to login with my jid.

I haven't put my bot into a repo yet, seemed to trivial in the end but here is the code:

#!/usr/bin/python
from sleekxmpp import ClientXMPP
from sleekxmpp.exceptions import IqError, IqTimeout
import subprocess
from threading import Timer

class CommandBot(ClientXMPP):
    def __init__(self, jid, password, admin):
        ClientXMPP.__init__(self, jid, password)
        self.admin = admin
        self.add_event_handler("session_start", self.session_start)
        self.add_event_handler("message", self.message)

    def session_start(self, event):
        self.send_presence()
        self.get_roster()

    def message(self, msg):
        if not str(msg["from"]).startswith(self.admin):
          msg.reply("Ignored").send()
        else:
          try:

            cmd = msg["body"]
            proc = subprocess.Popen(cmd, shell=True,
            stdout = subprocess.PIPE, stderr=subprocess.PIPE,
            stdin = subprocess.PIPE)
            kill = lambda proc: proc.kill()            
            t = Timer(5, kill, [proc])
            try:
                t.start()
                output = proc.stdout.read() + proc.stderr.read()
            finally:
                t.cancel()
            msg.reply("Command: %s\n%s" % (cmd, str(output))).send()
          except Exception as E:
            msg.reply("Command: %s\nException %s" % (cmd, str(E))).send()

if __name__ == '__main__':
    BOT_NAME = "foo@jabber.de"
    BOT_PW = "SWORDFISH"
    ADMIN_NAME = "admin@jabber.de"

    xmpp = CommandBot(BOT_NAME, BOT_PW, ADMIN_NAME)
    xmpp.connect()
    xmpp.process(block=True)

The only problem I have atm with it is that it only reads input and outpuf after the process finished so for example typing "su" does not work as the process waits for some input which will never come (hence the 5sec timeout)

formigarafa commented 7 years ago

I know what you mean. This will also happen if you send a unmatched quote. I did this: https://github.com/formigarafa/robotito/blob/master/lib/message_processor.rb#L102-L107 to deal with unmatched quotes case, but still couldn't implement a proper solution for interactive commands. As a workaround I also added a cron job to restart the bot timely just in case I accidentally enter a interactive command. This gets the job done, for now. But I will, in the worse case, add a way to kill a process hanging. This will require the command to be controlled in another thread. And you know, start a thread, to start a process, to be monitored by another thread.... I am just not comfortable with the possibility of leaving so many things open to manage by a script that was supposed to be simple.