6/12 Inside of a C++ program, I do a "ps | grep usename" for logging
purposes. where username = getenv("USER"); Doing this directly is a
gigantic security hole because someone could set $USER to some command
line and execute arbitrary code. What's the best way to make this
safe? Is there some standard way to check the input in a case like
this?
\_ How about "ps | grep \"username\""?
\_ man getuid, man getpwuid
\_ How's your motd logger going?
\_ I hope OP isn't doing this for a motd logger. There are much
easier ways than writing C++.
\_ Some versions of ps support a -U flag (or similar) that lets you
pass in the username OR userid. Safest way would be to (1) take the
username and translate it to the uid via getpwuid, getpwnam,
&c.; (2) exec ps (w/ the full path) and that uid; and (3) read the
output in C++. Any otherway is not 100% safe.
output in C++. Any other way is not 100% safe.
If your version of ps does not support user filtering, you should
exec ps (w/ the full path) and read/filter the output yourself.
Whatever you do, don't use system() and if you are running as root,
please drop privileges before calling exec().
\_ Not running as root. system() is bad, huh?
\_ Yes. system invokes a shell for you (in some cases csh). And
please use a full path, last thing you want is to be running
a PFY's hax0r'ed version of ps.
\_ system() is basically a wrapper around '/bin/sh -c $command'
with all the vulnerabilities and performance hit you get from
spawning the /bin/sh -c and what the shell might do with
$command. You're generally safer with fork && exec(command)
though then you have to deal with $PATH and massaging the
arguments.
\_ you should also read up on IFS.
\_ you should also read up on IFS. --psb
\_ What is IFS?
\_ IFS stands for Internal Field Separator, it is
what the shell uses to separate elements of the
various *PATH variables, among other things.
\_ and at the heart of many old skool attacks
such as /usr/lib/ex3.7preserve and other
insecure popen() problems.
insecure popen() problems. --psb
\_ Ok, but the command line I'm passing to system is pretty
complex. I don't care much about the performance, since
the logging is pretty rare. But I used "ps | grep $USER |
| sort | head" to get only the results I wanted. Seems
like fork exec would in this case would be hard. -op
\_ yes it would be. secure code is hard. insecure
code is easy.
\_ One possible sol'n would be to implement your filter
as a one line perl command and then send the output of
ps to that perl command. You would reduce the problems
to two fork/execs and would increase your security.
But the safest way is still to do as much as you can
in C and not in the shell via system().
BTW, why do use use $USER from the environment? Can't
you read it in using a CLI option or use the current
user id via getuid() or geteuid()?
\_ Actually, because I didn't know about getuid().
\_ I'm not sure what exactly you are trying to do,
but I think you can do all of it w/o system()
and not too much work in c++. Based on the above,
it seems like you could read the output of ps -U
[uid] (or equivalent) into a STL string vector,
sort the results and take the top 10. |