How to properly escape ash input?

Hello, I'd like to make a simple web service on my lede router, which will invoke etherwake. I don't have enough flash to install http daemon, lua or some higher level language, so I have thought on netcat (which I have in firmware) and simple ash script, which could simulate simple web server, something like https://debian-administration.org/article/371/A_web_server_in_a_shell_script. Sorry if it's too of topic, but if it would not run on lede, I'd simply use php exec, but php is too big for 4MB flash. I have self compiled binary just with packages I need, yet I have only few kiloytes left, just for the script :thinking:

Router and script will be accessible from internet, so I'd like to have it correctly escaped, if it is possible at all.

Script should take parameter from url, something like http://myledeip:port/wakepc1, which will execute etherwake 12:34:65:78:00:aa

I need to wake 3 different devices, so I need to parse parameters. But anyone could exploit pipe, semicolon, && " ' and other control characters to remotely insert and execute arbitrary commands. So is it possible to properly escape variable that can contain virtually anything in ash?

Thank you.

To answer that specific question, "yes" -- ash should handle quotes/escapes much as POSIX sh As long as you are looking at sh and not bash documentation, you should be OK.

On implementing the script, personally, I'd pass a token over the wire, then have the script take the proper action based on the token. Passing "arbitrary" data to a shell is always asking for trouble, even more so when the channel is both unencrypted and unauthenticated.

http://myledeip:port/11%3A22%3A33%3A44%3A55%3A66%20%3B%20rm%20-rf%20%2F*.*

On re-reading, it seems like you already acknowledge that. Yes, it is a major challenge to have scripts be robust to malicious or even unintentional command injection. It's a general question that perusal of Stackoverflow or the like will reveal many options. Anything that looks "too simple to be true" probably relies on non-POSIX bash extensions.

Thank you for reply. The problem is that whatever approach I take, attacker can inject any characters using curl or direct socket connection. And how to properly parse or work with input that can be interrupted with control characters I have no idea. But I fail to belive, that such simple looking thing as escaping is not possible in ash :wink:

Without seeing your code, I can't comment on its security (and I'd hesitate to declare it "safe" even if I saw it), but one approach is to make sure that it is never tokenized by the shell and always kept in single-string (quoted) form.

Thank you for reply. Yes, I can read input into variable and leave it in single quotes, but what if ash while reading encounters single qute? This will terminate my first single quote and let the attacker do whatever he wants, so the variable could look like 'some my string ';attackers whatever;' rest of of my string'.

I have thought about using that script on https://debian-administration.org/article/371/A_web_server_in_a_shell_script It looks clean enough, but I don't know how will ash behave when it will read control characters.

#!/bin/sh -vx is your friend

What does it do? I looked into man page, but I'm not very clever from that.

From man sh or an online man page:

           -v verbose       The shell writes its input to standard error as it is read.  Useful for debugging.

           -x xtrace        Write each command to standard error (preceded by a ‘+ ’) before it is executed.  Useful for debugging.

-x will include the expansion just prior to execution.

Perhaps it might be better to address the cause of the challenge

If your router has a USB socket, you can buy a 16 GB stick and, with a little command-line work, use it for the "overlay" partition and have plenty of room. There are instructions at https://openwrt.org/docs/guide-user/additional-software/extroot_configuration

1 Like

I would use the script in your first post.

But

Instead of having one scripted web server I would have three listening on three different ports.

I would not parse any input but simply call etherwake for one dedicated PC in each script, since you only have three PC to wake.

@mbo2o: This is what I have in pocket as a last resort, but It's a waste of resources having 3 netcats running :wink: It is still acceptable even for 32MB device I think, some ram is free.

@jeff thank you, sorry, my bad, I have looked into wrong man page (this one came second on startpage and I hit by accident: http://heirloom.sourceforge.net/sh/sh.1.html) I will try to debug the code. Router is old cheap wr841n v8, without usb. Because it works fine and eats below 2W I don't want to replace it. And also I like to play and found it challenging to run http server in bash :sunny:

I also thought about creating 3 users, for each pc one, and giving them etherwake instead of ash on logon, but I have not tried if it will work :wink: But it is not that user friendly as opening bookmark on your phone. Linux possibilities are endless and that is why I like it so much.

If you do decide to pursue the shell-based approach, be careful with what you find on the web as many GNU-based OSes use bash by default and the "bash-isms" may not be implemented in sh or ash. Only a small fraction of posts I've seen allude to use of these "tricks" that aren't supported unless you have bash installed.

Also, depending on the client making the request, the "url extractor" isn't very robust. There is already an "HTTP/2.0" out there, and expecting a single space followed by the HTTP request version may cause you problems.

I don't understand why you need netcat.

I thought just three scripts that take no arguments with hardcoded etherwake call for one dedicated PC each, and three different ports in inetd.conf for each script.

@mbo2o It is interesting approach, but I have no idea how you can listen on port using inet.d. The caveat I see is that every portscan would wake the PCs. They are not that frequent, but I see them time to time, mostly from chinese IPs.

You might also consider sed to accept the input, search for the GET, extract a single character, then use a case statement on that single character.

WAIT, this is on your outside IP????

Bad plan to expose anything but robust services on your outside IP. ssh into the box please.

1 Like

Sure, that's why I wanted to correctly escape the input :wink: I have thought it is not a problem to replace unwanted characters by tr or whatever, but the more and more I'm reading, I'm starting to believe there's no way to make it secure. Maybe httpd which is inside busybox might fit, then replace the control characters and when it's clean, read it by sh.

I'll bet that whatever you expose someone can cause a buffer overrun or the like and, at best, crash your router.

I wouldn't even expose uhttpd with TLS v1.2 and certificates. Even dropbear worries me. I explicitly specify my VLAN-restricted management interface for uhttpd for LuCI as I consider any wireless client as potentially hostile.

Edit: Take a look at authorized_keys and, in particular the command="command" option. I don't know how much of "real" ssh is implemented in dropbear, but that is a much safer way to "run a command".

I agree, have you ever tried to run dropbear on port 22 and looked into logread? That was hell on earth from chinese farms, but they have never crashed the router :wink: That's why I started to randomly change my wan mac every day which cause change of IP, run dropbear on non standart port and use DROP instead of REJECT in firewall.
I think that I have no other option than to believe httpd (or whatever service) is safe enough, otherwise I'd need to travel to the place by mysleft and do it all there :slight_smile: I'd not believe luci either, that's why I don't use it at all, but main reason is it eats too much flash :wink:

The ssh-port attempts are to gain login. Moving the port may keep your logs cleaner, but don't remove the risk. Once a script finds a vulnerable service, on any port, then it moves to trying to exploit vulnerabilities. You're asking for trouble for yourself, as well as not taking into consideration that it may just be a C&C channel a larger "hack" is trying to establish. You may end up being the reason the hackers can hide their tracks as an unwitting middleman for their overall goals. Yes, even your connection and your router could be an enabler in a deadly DDoS attack, or a penetration into a "more interesting" target.