-
Notifications
You must be signed in to change notification settings - Fork 4
FAQ
Is it possible to allow a command with wildcard or similar arguments? For example if I want to restrict 'rm' to a specific directory, for example: 'rm /path/to/*'
Thanks for asking. That's a great question with a complicated answer:
No, that's not possible (in general). It was a deliberate design decision to only allow complete, explicit commands, not just prefixes and not rich pattern matching (but see below). This is for security reasons.
For example, what does "*" mean? It might mean any string of any length. That would mean that your example would allow this: "rm /path/to/something; sudo rm -rf /" where the "*" matches "something; sudo rm -rf /". If that seems like a silly example that could be prevented by not allowing shell meta-characters (except for the fact that many shell commands contain shell meta-characters and so they can't be excluded), what if "*" matched "../../../../../etc/passwd"?
I know that "*" in shell globbing doesn't include "/" characters so this might look like a bad example, but the general principle is valid. "*" in an authorization directive isn't the same thing as "*" in a shell command and so thought has to go into its definition. "*" can even mean different things in the same shell depending on which options are set in the shell (e.g. EXTENDED_GLOB and GLOB_DOTS in zsh).
Preventing things like this means trying to be very very clever about deciding what to allow and what not to allow. I know I'm not clever enough to do that successfully in all cases and I don't want to be responsible for a security disaster. Different shells have different syntax and different meta-characters and anyone can invent a new shell whenever they want. The only way for sshdo to work with every possible shell and any possible command is to know nothing about them and not try to. That's the system administrator's responsibility.
But also, "*" means something in the shell commands themselves. If "*" is meant to apply to the command(s) being allowed, how would you express a command that contained the "*" character that needed the shell to interpret the "*"? It quickly becomes a nightmare of complicated syntax that the user might get wrong, potentially leading to a security issue. Shell syntax is already complex enough without layering another syntax for authorization directives over the top of it. So the authorization directives are explicit, complete, (almost) literal shell commands.
So, you can allow rm to delete all files in a specific directory with "rm /path/to/*" but that authorization directive won't allow rm to delete any file in that directory.
Having said that, sshdo does support deliberately simple pattern matching. The hash character (#) represents decimal digits by default. A single # means one or more digits. Multiple #s means exactly that many digits. It can be reconfigured to mean hexadecimal digits (or just literal hash characters).
So, you can use patterns, but only for digits (decimal or hexadecimal). This is enough for matching things like sequence numbers and date/time stamps in file names. If you can control the choice of names for the files in that directory, you might be able to make sure that they are of a form that can work with sshdo's simple pattern matching. It is likely that this is possible with automated or scripted commands.
Also, sshdo can be put into learning mode to learn from existing behaviour and construct authorization directives by itself, even determining patterns to match similar commands by itself. Of course, the system administrator then has the responsibility of approving the semi-automatically generated policy and installing it if they determine that it is safe to do so.
Also, the absence of any additional syntax for authorization directives (apart from simple # pattern matching) is what makes it possible to have a learning mode and the ability to learn and unlearn automatically from observed behaviour. This is much more important than adding syntax to support writing complex policies manually. Semi-automatic policy generation is much more friendly/scalable than manual policy creation.
I think this approach is secure, and just flexible enough, and very easy to use most of the time.
Sshdo is really aimed at limiting ssh key use to a set of fixed (or very similar) automated or scripted commands. I don't think that greater flexibility in command matching is really needed in that context. What you're asking for seems more relevant to commands that vary all the time. But even then, if they only vary from time to time, you can turn on learning mode at any time to gather new authorization directives as system behaviour changes.
But if you really need globbing or regular expressions (and trust yourself to never get the syntax wrong and put your hosts at risk), then I'd recommend considering this alternative:
authprogs - SSH Command Authenticator
https://github.com/daethnir/authprogs
I had a case where sshdo couldn't express the arguments needed so I changed/wrapped the program in question to read arguments from stdin if there were none on the command line. Then, sshdo was instructed to allow the program with no arguments. You could do something like this and have your program carefully check that each argument is a file in the given directory before deleting it.
In other words, I don't want to be responsible for trying to second guess the semantics of any given command (or the syntax of any given shell). If you need something more flexible, you will need to analyse the security implications yourself and wrap your original command in a new sshdo-friendly command that performs whatever additional security checks are needed.
Sorry I couldn't give you the answer you probably wanted, but there are several approaches above that you can investigate that might allow you to get what you need done. If not, authprogs should be able to do what you want.