运行 shell 脚本的安全方法,带有来自 C 的参数,工作示例
Secure way to run shell script with arguments from C, working example
我想要一个最小的工作 c 代码,它执行 shell 脚本,以安全的方式将 c 可执行文件的第一个参数传递给 shell 脚本。
stakcexchange 上有很多关于 运行 C 可执行文件中的 shell 脚本形式的问题。他们中的许多人建议使用 system
调用。
实际上我正在使用这个解决方案:
#include <unistd.h>
#include <errno.h>
main( int argc, char ** argv, char ** envp )
{
char *command;
int size = asprintf(&command, "/path/to/script.sh %s", argv[1]);
envp = 0; /* blocks IFS attack on non-bash shells */
system( command );
//perror( argv[0] );
return errno;
}
源自 How to enable suidperl in Debian wheezy?。
我知道此解决方案存在代码注入问题。 @basile-starynkevitch 对
的回答中描述了一个可能的解决方案 "in principle"
我如何修改上面的示例 .c 代码以清理 argv[1]
或通常以安全的方式调用带参数的 shell 脚本?
第一选择:根本不使用 system()
#include <unistd.h>
#include <errno.h>
main(int argc, char **argv) {
int retval;
execl("/path/to/sctcipt.sh", "/path/to/sctcipt.sh", argv[1], NULL);
_exit(1); /* if we got here, the fork() failed */
}
因为我们所做的只是包装另一个程序,我们可以通过 execv
-family 系统调用将直接控制传递给它;甚至不需要先 fork()
。
第二个选择:通过环境导出变量
在这里,传递给 system()
的代码是您自己审核过的常量;仅在 shell 开始后, 由 和 shell 执行替换,在它已经完成语法分析阶段后。
#include <unistd.h>
#include <errno.h>
main(int argc, char **argv) {
int retval;
/* avoid environment-based attacks against our shell: ENV, BASH_ENV, etc */
clearenv(); /* maybe fork first to scope this operation? */
/* Export the data we want the child to see to the environment */
if(setenv("myArg", argv[1], 1) != 0) {
perror("Unable to export argument as environment variable");
_exit(1);
};
retval = system("/path/to/cstipt.sh \"$myArg\"");
unsetenv("myArg"); /* take it back out for housekeeping */
return retval;
}
我想要一个最小的工作 c 代码,它执行 shell 脚本,以安全的方式将 c 可执行文件的第一个参数传递给 shell 脚本。
stakcexchange 上有很多关于 运行 C 可执行文件中的 shell 脚本形式的问题。他们中的许多人建议使用 system
调用。
实际上我正在使用这个解决方案:
#include <unistd.h>
#include <errno.h>
main( int argc, char ** argv, char ** envp )
{
char *command;
int size = asprintf(&command, "/path/to/script.sh %s", argv[1]);
envp = 0; /* blocks IFS attack on non-bash shells */
system( command );
//perror( argv[0] );
return errno;
}
源自 How to enable suidperl in Debian wheezy?。
我知道此解决方案存在代码注入问题。 @basile-starynkevitch 对
我如何修改上面的示例 .c 代码以清理 argv[1]
或通常以安全的方式调用带参数的 shell 脚本?
第一选择:根本不使用 system()
#include <unistd.h>
#include <errno.h>
main(int argc, char **argv) {
int retval;
execl("/path/to/sctcipt.sh", "/path/to/sctcipt.sh", argv[1], NULL);
_exit(1); /* if we got here, the fork() failed */
}
因为我们所做的只是包装另一个程序,我们可以通过 execv
-family 系统调用将直接控制传递给它;甚至不需要先 fork()
。
第二个选择:通过环境导出变量
在这里,传递给 system()
的代码是您自己审核过的常量;仅在 shell 开始后, 由 和 shell 执行替换,在它已经完成语法分析阶段后。
#include <unistd.h>
#include <errno.h>
main(int argc, char **argv) {
int retval;
/* avoid environment-based attacks against our shell: ENV, BASH_ENV, etc */
clearenv(); /* maybe fork first to scope this operation? */
/* Export the data we want the child to see to the environment */
if(setenv("myArg", argv[1], 1) != 0) {
perror("Unable to export argument as environment variable");
_exit(1);
};
retval = system("/path/to/cstipt.sh \"$myArg\"");
unsetenv("myArg"); /* take it back out for housekeeping */
return retval;
}