I want to block a set of commands as soon as they are entered by the user on the terminal.
How can I do that?
Just blocking a certain set of commands is dangerous, and probably not what you want. If someone has shell access, chances are pretty good that they can figure out how to do something -- anything they want, really -- just by using a few elementary commands. To determine that you're actually "preventing" anything, you would have to do a careful audit of all the allowed commands and determine that none of them allow the user to do something you don't want. That's a pretty tall order.
For example, if you allow them access to echo
, chmod
and base64
, then they could take a binary on their system, base64
it, paste it into their shell with echo 'long_base64_data' | base64 -d > bin.bin
and then chmod +x bin.bin
and then ./bin.bin
-- and it can do anything that the glibc
and syscalls on the system allow.
Similarly, if any interpreter is allowed, be it perl
, python
, ruby
, or even (arguably) bash
, they should be able to use that to eventually get down to arbitrary code execution -- again, anything that the kernel's syscalls allow.
If you don't trust someone to have full shell access on your system, don't give them shell access at all. Otherwise, you need to come up with some custom network protocol that assumes the user is hostile and restricts them to a very small subset of well-known and studied actions, that are known to be safe even if the user attempts to do something nasty.
To answer the actual question you asked, naively: You can obviously do things like chmod o-x /bin/rm
if you think that's actually going to stop the user from removing files (in that case only the owner of the rm
command will be able to execute it, which is usually root
); but if that's all you do, then they can use busybox
or any of the aforementioned scripting languages to remove a file. Or they can echo executable code to a file, make it executable, and run it. And I'm sure I'm omitting even trickier ways for someone to execute arbitrary code with a shell, such as shell command injection into a command that, on the surface, appears to be innocent and doesn't explicitly allow arbitrary commands. In fact, I can think of a command off the top of my head that was installed on Ubuntu and had a comment in it like "we really should think of a better way to do this because this allows arbitrary shell code injection". It's still not fixed.
The shell, to a large extent, assumes that the operator is trusted. Even a regular user shell (non-root) assumes a great deal of trust. If your reason for wanting to prevent the user from executing commands is in any way related to not fully trusting them, I would find another way to do what you're trying to do without giving them shell access at all.
By the way, the purpose of the user shell's somewhat reduced privileges is to protect the (assumed-trusted) user from themselves, and to protect the user from malicious programs. Protecting the user from themselves and protecting the user from malicious programs is a totally different problem from protecting the operating system from an untrusted user. Shells just can't do that very well by their nature.
In other words, preventing the execution of a "set" of shell commands and then giving someone shell access is like trying to stop a tsunami by putting a few poles in the sand on the beach. There are still millions of other places where the water can go, so even if the water runs into all your poles, that doesn't hinder it in the least from coming up the beach (and it'll likely tear down your poles and bring it along with the tsunami, anyway). You need to build a bona fide water dam spanning many miles. Fortunately, in the digital world, building a fairly good dam is a lot easier than it is to do in real life. There's a thing called an HTTPS server
and a number of server-side programming languages which accomplish this task quite well, on the whole. Certainly much better than a shell.
chmod 700
.