I have been working on a project that uses PIDs, /proc
and command line analysis to validate processes on a system. My code had to be checked by the security guys who manage to break it with a single line... embarrassing!
#!/usr/bin/env perl
$0="I am running wild"; # I had no clue you can do this!
system("cat /proc/$$/cmdline");
print("\n");
system("ps -ef | grep $$");
# do bad stuff here...
My questions:
I see some uses cases for the above, like hiding passwords given on the command line (also bad practice) but I see a lot more problems/issues when one can hide processes and spoof cmdline
. Is there a reason it is allowed? Isn't it a system vulnerability?
How can I prevent or detect this? I have looked into /proc
mount options. I also know that one can use lsof
to identify spoofed processes based on unexpected behavior, but this won't work in my case. At the moment I am using a simple method to detect if the cmdline
contains at least one null (\0
) character which assumes that at least one argument is present. In the above code, spaces need to be replaced with nulls to bypass that check which is something I couldn't find how to implement in Perl - writes up to the first \0
.
To answer 1:
It's because of how starting a new process actually works.
You fork()
to spawn a duplicate instance of your current process, and then you exec()
to start the new thing - it replaces your current process with the 'new' process, and as a result - it has to rewrite $0
.
This is actually quite useful though when running parallel code - I do it fairly frequently when fork()
ing code, because it makes it easy to spot which 'thing' is getting stuck/running hot.
E.g.:
use Parallel::ForkManager;
my $manager = Parallel::ForkManager -> new ( 10 );
foreach my $server ( @list_of_servers ) {
$manager -> start and next;
$0 = "$0 child: ($server)";
#do stuff;
$manager -> finish;
}
You can instantly see in your ps
list what's going on. You'll see this sort of behaviour with many multiprocessing services like httpd
.
But it isn't a vulnerability, unless you assume it's something that it's not (as you do). No more than being able to 'mv' a binary anyway.
Anyway, to answer 2... prevent or detect what? I mean, you can't tell what a process is doing from the command line, but you can't tell what it's doing otherwise anyway (there's plenty of ways to make a piece of code do something 'odd' behind the scenes).
The answer is - trust your security model. Don't run untrusted code in a privileged context, and it's largely irrelevant what they call it. Sure, you could write rude messages in the process list, but it's pretty obvious who's doing it.