我想启动一个bash脚本(读: bash脚本)作为根,而不是用户调用它,但是bash忽略脚本上的setuid,所以我选择编写一个非常小的脚本,它接受脚本/参数并使用setuid set调用它。
这样做的效果很好,我进一步验证了脚本是否设置了setuid,可执行文件和setuid()调用了文件的所有者,而不是根文件,以避免程序的任何误用,最后我使用了下面的程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
char *command;
int i, file_owner, size = 0;
struct stat status_buf;
ushort file_mode;
// Check argc
if (argc < 2) {
printf("Usage: %s <script> [arguments]\n", argv[0]);
return 1;
}
// Make sure the script does exist
if(fopen(argv[1], "r") == NULL) {
printf("The file %s does not exist.\n", argv[1]);
return 1;
}
// Get the attributes of the file
stat(argv[1], &status_buf);
// Get the permissions of the file
file_mode = status_buf.st_mode;
// Make sure it's executable and it's setuid
if(file_mode >> 6 != 567) {
printf("The file %s should be executable and should have setuid set, please chmod it 0106755.\n", argv[1]);
return 1;
}
// Get the owner of the script
file_owner = status_buf.st_uid;
// setuid
setuid(file_owner);
// Generate the command
for (i = 1; i < argc; i++) {
size += strlen(argv[i]);
}
command = (char *) malloc( (size + argc + 11) * sizeof(char) );
sprintf(command, "/bin/bash %s", argv[1]);
if (argc > 2) {
for (i = 2; i < argc; i++) {
sprintf(command, "%s %s", command, argv[i]);
}
}
// Execute the command
system(command);
// free memory
free(command);
return 0;
}这个练习不仅是为了解决我的问题,而且也是一种更深入C的方法,那么你有什么建议呢?有什么需要改进的吗?
发布于 2011-06-09 23:54:46
我会做的一件事是
变化
sprintf(command, "%s %s", command, argv[i]);使用strcat
虽然这确实适用于许多实现,但它并不被认为是“安全的”
参考https://stackoverflow.com/questions/1283354/is-sprintfbuffer-s-buffer-safe
https://codereview.stackexchange.com/questions/2883
复制相似问题