I am designing an C++ app that, among other things, executes a few scripts every now and then. The app should be efficient and preferably platform independent.
The i
3) It is not quite platform independent (Now, this would be a concern. I would really love to see an example where it behaves differently on different platforms)
Well, for instance system("ls")
would probably fail in Windows, since there is no ls command.
4) It is a security concern. (Again, this would be an issue. Can someone provide an example of a potential security problem with system() ? )
If the argument passed to system
comes from user input, and not properly validated, it can be used to execute unwanted things with the privilege levels of the original executer. If its static content, its quite easy to find that within an executable image and modify it to do nasty things as well.
I used the system() call in my CGI C++ app under windows and Linux too.
One problem I had was when using system() was not having the proper access rights to execute my skript with the web user.
I did not have that problem any more when using the CreateProcess() method.
Regarding security concerns, a classical example about (4) is the following scenario: imagine the user is prompted to give some directory name to be backed up into a std::string dirname
; then you'll compute some backup directory name into a std::string backup
and do
system((std::string{"cp -a "} + dirname + " " + backup).c_str())
Now think what happens if a malicious user enter foo bar; rm -rf $HOME; ls
as the dirname
and backup
is /vol/backup_2015_fev/
. The system
command would execute
cp -a foo bar; rm -rf $HOME; ls /vol/backup_2015_fev/
which is not what you expected (all the user's $HOME
would be deleted!). This is an example of code injection, and when using system
you should ensure that it never happens (e.g. by sanitizing and/or escaping every user input related string)
Also, the PATH
might not be what you believe it is (e.g. starting with /tmp/
and a malicious user having done ln -s /bin/rm /tmp/cp
before your system
runs).
I maintain a system that consists of several separate executables. In this case I have control over the permissions, names, calling conventions, security over all supported platforms. In this case, system() works just fine. The applications communicate through a RDBMS.
Again, as others have noted "The Devil's in the details".
(3) If you just want a counterexample, for example grep behaves differently on Solaris vs Linux vs whatever.
(4) Your program's privileges are inherited by its spawned programs. If your application ever runs as a privileged user, all someone has to do is put their own program with the name of the thing you shell out too, and then can execute arbitrary code (this implies you should never run a program that uses system
as root or setuid root).
(5) It will probably be saner to maintain in the long run to use the posix facilities because you won't have to rely on a specific set of external scripts or binaries already existing wherever your program runs.
Whatever command you want to execute just store that in a file c.txt. Pass that file to the execl()
like as done below.
fd = open("c.txt", O_CREAT | O_RDWR, 00777);
write(fd,arr,sizeof(arr));
if(fork() == 0)
{
execl("/bin/sh", "sh", "-c","sh c.txt", (char *) 0);
}