Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Advertise on LowEndTalk.com
How can I run a command visiting a URL?
New on LowEndTalk? Please read our 'Community Rules' by clicking on it in the right menu!

How can I run a command visiting a URL?

479555479555 Member

Hi guys,

I have been looking for a quick and reliable way to run a python script that requires sudo by accessing a URL, but didn't have much luck.

I found a service which might have been a good fit - it's called Webhook Relay - the owner is a great guy and helped me at the beginning, but unfortunately I can't afford to pay for the premium plan, nor I fully understand how to reliably use the service.

Basically, I have a smart lock (Sherlock S2) which has a bluetooth remote. I opened it up and wired the remote to a Raspberry Pi, and I'm using the GPIOs of the RPi to power it and emulate a button press sending "pulses" using a python script (I need to run it with sudo because apparently that's required to control the GPIOs).

TL;DR: what I'd like to achieve is to be able to execute a python script when I visit, let's say, http://192.168.1.2/open_the_door and have the Raspberry Pi open the door.

Is there an easy way to do this? I read about many tools which I don't know how to use (Django and many many others) and I was wondering if there was an easier way or some sort of workaround.

Any help would be greatly appreciated!

Comments

  • hzrhzr Member, Moderator
    edited June 30

    pip3 install flask

    from flask import Flask
    app = Flask(__name__)
    
    
    @app.route('/unguessable_routeprotect_this')
    def opendoor():
        # do terrible gpio garbage
        return "door should be open, if not house is on fire"
    
    if __name__ == '__main__':
        app.run()
    

    python3 filename.py (can just run this as root and ignore the sudo stuff, but holy hell turn off debug mode and protect it, use mtls, use client certs, ip whitelisting, whatever)

    curl ip:5000/unguessable_routeprotect_this

    Thanked by 3479555 Pwner raindog308
  • LTnigerLTniger Member

    "Help, my house is hacked". This close reality is kinda scary.

    Thanked by 3Shot2 CConner Ouji

    hostWP.net - Wordpress Hosting Platform.

  • hzrhzr Member, Moderator

    @LTniger said: "Help, my house is hacked". This close reality is kinda scary.

    I have been locked in an office before because a smart lock's cloud service was down

    Thanked by 2skorous Aidan
  • PwnerPwner Member

    @LTniger said:
    "Help, my house is hacked". This close reality is kinda scary.

    I care about security more than most, but it all depends on the implementation of this too. If done correctly, then the risk of being compromised is no better than accessing anything else online.

    That being said, I won't complain too much if someone manages to hack into a vending machine and can trigger it to dispense my favorite snacks for me.

  • vyas11vyas11 Member

    @hzr said:

    @LTniger said: "Help, my house is hacked". This close reality is kinda scary.

    I have been locked in an office before because a smart lock's cloud service was down

    That's a not so smart service then

    Thanked by 1Aidan
  • somiksomik Member

    @vyas11 said:

    @hzr said:

    @LTniger said: "Help, my house is hacked". This close reality is kinda scary.

    I have been locked in an office before because a smart lock's cloud service was down

    That's a not so smart service then

    Always ensure the smart lock has a manual bypass to prevent this from happening.

    In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    Don't be so serious. It's just a forum. No one cares what you think anyway.

  • farsighterfarsighter Member
    edited July 1

    @hzr said:
    python3 filename.py

    LOL that reminds me that years ago, before I started learning Python I needed a similar solution (which in my case was simply to store a GET request into a text file).
    That was far beyond my skills at that time so I found an example on Google of how to parse GET (and other) requests, and with efforts managed to mix it with another example from Google of how to save a variable to file... It worked eventually.

    Fortunately I still have this, so here it is (ignore unnecessary lines lol)
    ( @479555 you can easily remove text_file lines and do something else with the variable... maybe an 'if' statement which runs your script when self.path[2:] matches something)

    #Usage: http://IP:8088/?fart then fart will be stored in output.txt
    from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
    from urlparse import parse_qs
    import cgi
    
    class GP(BaseHTTPRequestHandler):
        def _set_headers(self):
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
        def do_HEAD(self):
            self._set_headers()
        def do_GET(self):
            self._set_headers()
            text_file = open("output.txt", "w")
            text_file.write(self.path[2:])
            text_file.close()
            print parse_qs(self.path[2:])
            self.wfile.write("Get Request Received!")
        def do_POST(self):
            self._set_headers()
            form = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
                environ={'REQUEST_METHOD': 'POST'}
            )
            print form.getvalue("foo")
            self.wfile.write("POST Request Received!")
    
    def run(server_class=HTTPServer, handler_class=GP, port=8088):
        server_address = ('', port)
        httpd = server_class(server_address, handler_class)
        print 'Server running at localhost:8088...'
        httpd.serve_forever()
    
    run()
    

    If you want I'll make it nicer for you when I wake up

    Thanked by 1479555
  • 479555479555 Member

    @hzr said:
    pip3 install flask

    > from flask import Flask
    > app = Flask(__name__)
    > 
    > 
    > @app.route('/unguessable_routeprotect_this')
    > def opendoor():
    >     # do terrible gpio garbage
    >     return "door should be open, if not house is on fire"
    > 
    > if __name__ == '__main__':
    >     app.run()
    > 

    python3 filename.py (can just run this as root and ignore the sudo stuff, but holy hell turn off debug mode and protect it, use mtls, use client certs, ip whitelisting, whatever)

    curl ip:5000/unguessable_routeprotect_this

    Thanks but I don't really understand what you wrote. I should install flask and then...?

    1. Where should I paste that code?
    2. What does routeprotect mean?
    3. What do you mean by "# do terrible gpio garbage"? Should I paste the python script there?
    4. What are name and main?
    5. What is debug mode, mtls and client certs?

    I really appreciate your help but as you can see what you wrote is way out of my league.

    @hzr said:

    @LTniger said: "Help, my house is hacked". This close reality is kinda scary.

    I have been locked in an office before because a smart lock's cloud service was down

    Luckily my lock works locally using bluetooth so even if the servers go down I can still operate the lock.

    @LTniger said:
    "Help, my house is hacked". This close reality is kinda scary.

    That seems very very unlikely. To do that you need to find someone that knows that I have a smart lock, what type, they have to know that I'm controlling the remote through a Raspberry Pi which is behind a multi NAT which is a nightmare to access, they need to have a valid reason to risk jail time just to have a look at my home, the skills to hack into my network and then figure out how to open the door once inside the RPi.

    I mean, it's possible but it's unlikely, I'm fine with the risk.

    @somik said:

    In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    My lock closes the door mechanically through a key just like a person would do, so I don't think that would be possible.

  • 479555479555 Member

    @farsighter said:
    If you want I'll make it nicer for you when I wake up

    If you think I could use your method to achieve what I'm trying to do I'd really really appreciate that! :)

  • LTnigerLTniger Member

    I won't trust a lock from aliexpress...

    hostWP.net - Wordpress Hosting Platform.

  • sdglhmsdglhm Member
    edited July 1

    @vyas11 said: That's a not so smart service then

    Well. Opening the doors because the cloud service was down was considered smart, but 100+ robbed houses says otherwise.

    @somik said: In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    Not all locks can be opened with a magnet. Some just need a light tap.

    I repeat, RAID is not backup | Looking for a developer for your next project? - Hire me

  • farsighterfarsighter Member
    edited July 1

    @479555 said:

    @farsighter said:
    If you want I'll make it nicer for you when I wake up

    If you think I could use your method to achieve what I'm trying to do I'd really really appreciate that! :)

    OK here it is for you.
    Save this script and run then visit http://IP:8088/?opengate
    If 'opengate' is what comes after the question mark then script /root/file.py will execute

    #Usage: Save this script and run then visit http://IP:8088/?opengate
    #if 'opengate' is what comes after the question mark
    #then script /root/file.py will execute
    from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
    from urlparse import parse_qs
    import cgi 
    class GP(BaseHTTPRequestHandler):
        def _set_headers(self):
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
        def do_GET(self):
            self._set_headers()
            if self.path[2:] == 'opengate':
               execfile('/root/file.py')
            print parse_qs(self.path[2:])
            self.wfile.write("Get Request Received!")
    def run(server_class=HTTPServer, handler_class=GP, port=8088):
        server_address = ('', port)
        httpd = server_class(server_address, handler_class)
        print 'Server running at localhost:8088...'
        httpd.serve_forever()
    run()
    
    Thanked by 2479555 t0m
  • 479555479555 Member

    @farsighter said:

    @479555 said:

    @farsighter said:
    If you want I'll make it nicer for you when I wake up

    If you think I could use your method to achieve what I'm trying to do I'd really really appreciate that! :)

    OK here it is for you.
    Save this script and run then visit http://IP:8088/?opengate
    If 'opengate' is what comes after the question mark then script /root/file.py will execute

    > #Usage: Save this script and run then visit http://IP:8088/?opengate
    > #if 'opengate' is what comes after the question mark
    > #then script /root/file.py will execute
    > from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
    > from urlparse import parse_qs
    > import cgi 
    > class GP(BaseHTTPRequestHandler):
    >     def _set_headers(self):
    >         self.send_response(200)
    >         self.send_header('Content-type', 'text/html')
    >         self.end_headers()
    >     def do_GET(self):
    >         self._set_headers()
    >         if self.path[2:] == 'opengate':
    >            execfile('/root/file.py')
    >         print parse_qs(self.path[2:])
    >         self.wfile.write("Get Request Received!")
    > def run(server_class=HTTPServer, handler_class=GP, port=8088):
    >     server_address = ('', port)
    >     httpd = server_class(server_address, handler_class)
    >     print 'Server running at localhost:8088...'
    >     httpd.serve_forever()
    > run()
    > 

    Thank you so much! I'll try tonight or tomorrow!

  • rcxbrcxb Member
    edited July 1

    @479555 said:
    what I'd like to achieve is to be able to execute a python script when I visit, let's say, http://192.168.1.2/open_the_door and have the Raspberry Pi open the door.

    Find the cgi-bin folder for your web server. Put a script in there. Only thing special it needs to do is print Content-Type: text/html first. Can be written in python or anything else.

    Based on the little info you've provided, here's a basic shell script:

    #!/bin/sh
    echo "Content-Type: text/html"
    echo ""
    echo "<pre><tt>"
    sudo "/path/to/python-command.py" 2>&1
    

    Assuming you name the file lockdoor.cgi, run chmod a+x lockdoor.cgi
    Then you run it by going to http://URL/cgi-bin/lockdoor.cgi

    The user that the web server runs under (could be apache, nginx, www, or similar on your system) needs to be allowed run the sudo command. You need a line like:

    www    ALL=(ALL)    NOPASSWD:/path/to/python-command.py
    

    And also remove the requiretty line in /etc/sudoers.

    Thanked by 3t0m 479555 TimboJones
  • rcxbrcxb Member

    @479555 said:
    you need to find someone that knows that I have a smart lock, what type, they have to know that I'm controlling the remote through a Raspberry Pi which is behind a multi NAT which is a nightmare to access, they need to have a valid reason to risk jail time just to have a look at my home, the skills to hack into my network and then figure out how to open the door once inside the RPi.

    Actually, anybody that learns the URL to your door lock just needs to create a web-page which quietly causes your browser to make a request to that URL in the background, and get you to visit it by whatever means. e.g. "Hey, look at this funny picture!"

    Thanked by 1t0m
  • somiksomik Member

    @479555 said:

    @somik said:

    In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    My lock closes the door mechanically through a key just like a person would do, so I don't think that would be possible.

    Both motor based and solenoid based electronic locks can be bypassed very easily with a magnet. For the motor based, you have to move the magnet in a circular motion near the motor for it to turn as if power is applied to open the door (like the action of turning a key, where the key is still left in the lock). For solenoid based one, bring it near, and move it in the direction the solenoid would go. That usually unlocks it in a jiffy.

    There are known prevention to these by changing the lock design, but smart locks are designed by electronic engineers (like me), not by locksmiths.

    Thanked by 1479555

    Don't be so serious. It's just a forum. No one cares what you think anyway.

  • @somik said:

    @479555 said:

    @somik said:

    In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    My lock closes the door mechanically through a key just like a person would do, so I don't think that would be possible.

    Both motor based and solenoid based electronic locks can be bypassed very easily with a magnet. For the motor based, you have to move the magnet in a circular motion near the motor for it to turn as if power is applied to open the door (like the action of turning a key, where the key is still left in the lock).

    And what command does he put into his python script that will "move the magnet in a circular motion near the motor"?

  • somiksomik Member

    @TimboJones said:

    @somik said:

    @479555 said:

    @somik said:

    In my case, I would just carry around a large magnet. Those work wonders for bypassing electronic locks without any key or code.

    My lock closes the door mechanically through a key just like a person would do, so I don't think that would be possible.

    Both motor based and solenoid based electronic locks can be bypassed very easily with a magnet. For the motor based, you have to move the magnet in a circular motion near the motor for it to turn as if power is applied to open the door (like the action of turning a key, where the key is still left in the lock).

    And what command does he put into his python script that will "move the magnet in a circular motion near the motor"?

    Erm...

    import magnet
    from colleagues import friend
    
    strong_magnet = magnet(999)
    
    friend_move(strong_magnet)
    

    I haven't tried the code but it "should" work :tongue:

    Thanked by 1TimboJones

    Don't be so serious. It's just a forum. No one cares what you think anyway.

  • 0xbkt0xbkt Member

    You may also run a plain CGI script (written in Bash, Perl, or any glue language, maybe on Apache) to both contract with HTTP and run arbitrary Unix commands.

    Thanked by 1479555
  • 479555479555 Member
    edited July 3

    @479555 said:

    @farsighter said:

    @479555 said:

    @farsighter said:
    If you want I'll make it nicer for you when I wake up

    If you think I could use your method to achieve what I'm trying to do I'd really really appreciate that! :)

    OK here it is for you.
    Save this script and run then visit http://IP:8088/?opengate
    If 'opengate' is what comes after the question mark then script /root/file.py will execute

    > > #Usage: Save this script and run then visit http://IP:8088/?opengate
    > > #if 'opengate' is what comes after the question mark
    > > #then script /root/file.py will execute
    > > from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
    > > from urlparse import parse_qs
    > > import cgi 
    > > class GP(BaseHTTPRequestHandler):
    > >     def _set_headers(self):
    > >         self.send_response(200)
    > >         self.send_header('Content-type', 'text/html')
    > >         self.end_headers()
    > >     def do_GET(self):
    > >         self._set_headers()
    > >         if self.path[2:] == 'opengate':
    > >            execfile('/root/file.py')
    > >         print parse_qs(self.path[2:])
    > >         self.wfile.write("Get Request Received!")
    > > def run(server_class=HTTPServer, handler_class=GP, port=8088):
    > >     server_address = ('', port)
    > >     httpd = server_class(server_address, handler_class)
    > >     print 'Server running at localhost:8088...'
    > >     httpd.serve_forever()
    > > run()
    > > 

    Thank you so much! I'll try tonight or tomorrow!

    Just tried, I works but with a latency of about 3 minutes, for some reason. Better than nothing I guess but a bit too much to use it in everyday life.

    EDIT: I think it takes some time to "start" at first but then it is istantaneous! This is awesome!

  • 479555479555 Member
    edited July 3

    @rcxb said:

    @479555 said:
    what I'd like to achieve is to be able to execute a python script when I visit, let's say, http://192.168.1.2/open_the_door and have the Raspberry Pi open the door.

    Find the cgi-bin folder for your web server. Put a script in there. Only thing special it needs to do is print Content-Type: text/html first. Can be written in python or anything else.

    Based on the little info you've provided, here's a basic shell script:

    #!/bin/sh
    echo "Content-Type: text/html"
    echo ""
    echo "
    

    <

    pre>"

    sudo "/path/to/python-command.py" 2>&1
    

    Assuming you name the file lockdoor.cgi, run chmod a+x lockdoor.cgi
    Then you run it by going to http://URL/cgi-bin/lockdoor.cgi

    The user that the web server runs under (could be apache, nginx, www, or similar on your system) needs to be allowed run the sudo command. You need a line like:

    www    ALL=(ALL)    NOPASSWD:/path/to/python-command.py
    

    And also remove the requiretty line in /etc/sudoers.

    Thank you but that's too difficult for me, I don't even know if I have a web server nor what that would be!

Sign In or Register to comment.