July 07, 2019

Nebula level19 write up

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

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

Level19

About
There is a flaw in the below program in how it operates.

관련 사항.
아래의 프로그램은 실행 간 결함이 발생한다.

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

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

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

int main(int argc, char **argv, char **envp)
{
  pid_t pid;
  char buf[256];
  struct stat statbuf;

  /* Get the parent's /proc entry, so we can verify its user id */

  snprintf(buf, sizeof(buf)-1, "/proc/%d", getppid());

  /* stat() it */

  if(stat(buf, &statbuf) == -1) {
      printf("Unable to check parent process\n");
      exit(EXIT_FAILURE);
  }

  /* check the owner id */

  if(statbuf.st_uid == 0) {
      /* If root started us, it is ok to start the shell */

      execve("/bin/sh", argv, envp);
      err(1, "Unable to execve");
  }

  printf("You are unauthorized to run this program\n");
}

It is inappropriate to indirectly check the permission of the current process through the PPID.

PPID를 통하여 현재 프로세스의 권한을 간접적으로 점검하는 것은 부적절하다.

In older versions of Linux (Ubuntu 6.1 to 14.0) systems, the orphan process's parent process is designated with "init" process(PID: 1, root account permissions).

구 버전의 리눅스(Ubuntu 6.1~14.0) 시스템에서는 고아(orphan) 프로세스는 부모 프로세스로 "init" 프로세스(PID: 1, root 계정 권한)가 지정된다.

level19@nebula:/tmp$ ./exploit
I am 3155 → Parent. 부모
You are unauthorized to run this program → Bypass failed parent. 우회에 실패한 부모
level19@nebula:/tmp$ I am 0 → Child. 자식
[Child] Waiting...(ppid: 1) → Orphaned child. 고아가 된 자식
[Child] Execute shell(ppid: 1) → Child trying to bypass. 우회를 시도하는 자식
You have successfully executed getflag on a target account

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

Nebula level17 write up

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

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

Level17

About
There is a python script listening on port 10007 that contains a vulnerability.

관련 사항.
10007 포트에서 동작중이며 취약점을 지닌 파이썬 스크립트가 하나 있다.

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

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

Source code.    소스코드.
#!/usr/bin/python

import os
import pickle
import time
import socket
import signal

signal.signal(signal.SIGCHLD, signal.SIG_IGN)

def server(skt):
  line = skt.recv(1024)

  obj = pickle.loads(line)

  for i in obj:
    clnt.send("why did you send me " + i + "?\n")

skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
skt.bind(('0.0.0.0', 10007))
skt.listen(10)

while True:
  clnt, addr = skt.accept()

  if(os.fork() == 0):
    clnt.send("Accepted connection from %s:%d" % (addr[0], addr[1]))
    server(clnt)
    exit(1)

The main part to look at is the part that receives data of size 1024 Bytes from the client, and performing deserialization by calling "loads()" function of "pickle" module.

주요하게 보아야할 부분은 클라이언트로부터 1024 Bytes 크기의 데이터를 입력받는 부분과, "pickle" 모듈의 "loads()" 함수를 호출하여 역직렬화(Deserialization)를 수행하는 부분이다.

The data transmitted from the client is expected to be serialized data.

클라이언트로부터 전송되는 데이터는 직렬화(Serialization)된 데이터일 것으로 기대하고 있다.

level17@nebula:/tmp$ python ./exploit.py | nc 127.0.0.1 10007
Accepted connection from 127.0.0.1:36499
^C
level17@nebula:/tmp$ ls
exploit.py  rst.txt  VMwareDnD  vmware-root
level17@nebula:/tmp$ cat ./rst.txt
You have successfully executed getflag on a target account

Nebula level16 write up

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

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

Level16

About
There is a perl script running on port 1616.

관련 사항.
1616 포트에서 동작하는 Perl 스크립트 프로그램이 존재한다.

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

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

Source code    소스코드.
#!/usr/bin/env perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub login {
  $username = $_[0];
  $password = $_[1];

  $username =~ tr/a-z/A-Z/; # conver to uppercase
  $username =~ s/\s.*//;    # strip everything after a space

  @output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`;
  foreach $line (@output) {
      ($usr, $pw) = split(/:/, $line);

      if($pw =~ $password) {
          return 1;
      }
  }

  return 0;
}

sub htmlz {
  print("<html><head><title>Login resuls</title></head><body>");
  if($_[0] == 1) {
      print("Your login was accepted<br/>");
  } else {
      print("Your login failed<br/>");
  } 
  print("Would you like a cookie?<br/><br/></body></html>\n");
}

htmlz(login(param("username"), param("password")));

(1) @output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`;
(2) `egrep "^$username" /home/flag16/userdb.txt 2>&1`;
(3) egrep "^$username" /home/flag16/userdb.txt 2>&1
(4) egrep "^`■■■■■■■■`" /home/flag16/userdb.txt 2>&1

I have listed the order in which the original appearance of the target code is interpreted when it is recognized and executed as a shell command.

공격할 코드의 원래 모습이 쉘 명령어로 인식되어 실행될 때 어떻게 해석되는지를 순서대로 나열해보았다.

(1) It is the appearance of the code to attack.
(1) 공격할 코드의 모습이다.

(2) Focused on code related to shell commands.
(2) 쉘 명령어와 관련된 코드에 초점을 맞추었다.

(3) The Perl grammar recognizes strings enclosed in backquotes(`) as commands to be passed to the shell. So the range of strings to be passed to the shell is like this.

(3) Perl 문법은 백쿼트(`)로 둘러싸인 문자열을 쉘에 넘길 명령어로 인식한다. 이에 따라 쉘에 전달될 문자열의 범위는 이렇게 된다.

(4) Assumed situation a malicious string in the range.
(4) 해당 범위에서 악성 문자열이 들어갈 때를 가정한다.

level16@nebula:/tmp$ ls -al
……
-rwxrwxrwx 1 level16 level16  31 2019-06-19 01:29 EXPLOIT
-rw-r--r-- 1 flag16  flag16   59 2019-06-19 01:30 rst
……
level16@nebula:/tmp$ cat ./rst
You have successfully executed getflag on a target account

Nebula level15 write up

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

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

Level15

About
strace the binary at /home/flag15/flag15 and see if you spot anything out of the ordinary.

관련 사항.
"/home/flag15/flag15" 경로의 파일을 strace 명령어로 실행하라. 그리고 평소와 다른 부분을 확인하라.

You may wish to review how to “compile a shared library in linux” and how the libraries are loaded and processed by reviewing the dlopen manpage in depth.

당신은 "리눅스에서 공유라이브러리를 컴파일 하는 방법"과 "dlopen"의 매뉴얼 패이지를 통해 라이브러리가 로드되고 처리되는 방법에 대해서 알고 싶어질 것이다.

Clean up after yourself :)    클리어하기를 기원한다. :)

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

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

Source code    소스코드.
There is no source code available for this level    미공개.

We have tried to utilize environment variables in the previous challenge, so now we will use the RPATH property. Let's utilize the path "/var/tmp/flag15/tls/i686/sse2/cmov/libc.so.6", which is the first search path.

이전 챌린지에서 환경 변수를 활용하는 것은 해보았으니 이번엔 RPATH 속성을 활용해볼 것이다. 관련하여 최초로 탐색하는 경로인 "/var/tmp/flag15/tls/i686/sse2/cmov/libc.so.6"를 활용해보도록 한다.

level15@nebula:/var/tmp/flag15/tls/i686/sse2/cmov$ gcc -shared -fPIC -Wl,--version-script=./version.map,-static -static-libgcc -o ./libc.so.6 ./libc.so.6.c
level15@nebula:/var/tmp/flag15/tls/i686/sse2/cmov$ /home/flag15/flag15 sh-4.2$
sh-4.2$ id
uid=1016(level15) gid=1016(level15) euid=984(flag15) …
sh-4.2$ getflag
You have successfully executed getflag on a target account

Nebula level14 write up

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

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

Level14

About
This program resides in /home/flag14/flag14. It encrypts input and writes it to standard output. An encrypted token file is also in that home directory, decrypt it :)

관련 사항.
관련 프로그램은 "/home/flag14/flag14" 위치에 존재한다. 이 프로그램은 표준 입력으로부터의 입력 값을 암호화하여 표준 출력으로 출력한다. 암호화된 토큰 파일이 또한 해당 디렉토리에 존재한다. 이를 복호화 해보라.

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

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

Source code    소스코드.
There is no source code available for this level    미공개.

level14@nebula:/home/flag14$ echo "00000" | ./flag14 -e
01234level14@nebula:/home/flag14$
level14@nebula:/home/flag14$ echo "12345" | ./flag14 -e
13579level14@nebula:/home/flag14$
level14@nebula:/home/flag14$ echo "11111" | ./flag14 -e
12345level14@nebula:/home/flag14$
level14@nebula:/home/flag14$ echo "22222" | ./flag14 -e
23456level14@nebula:/home/flag14$
level14@nebula:/home/flag14$ echo "aaaaa" | ./flag14 -e
abcdelevel14@nebula:/home/flag14$
level14@nebula:/home/flag14$ echo "abbbbbbbbb" | ./flag14 -e
acdefghijklevel14@nebula:/home/flag14$

The pipeline (|) symbol allows you to pass values to the standard input of the program as above.

파이프라인(|) 기호를 통해서 위와 같이 프로그램의 표준 입력으로 값을 전달할 수 있다.

level14@nebula:/home/flag14$ python /tmp/exploit.py
845■■■■■■■■■■■■■■■3165
level14@nebula:/home/flag14$ su - flag14
Password:
flag14@nebula:~$
flag14@nebula:~$ getflag
You have successfully executed getflag on a target account

Nebula level13 write up

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

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

Level13

About
There is a security check that prevents the program from continuing execution if the user invoking it does not match a specific user id.

관련 사항.
이 프로그램을 실행시키는 사용자의 UID가 지정된 값이 아니라면, 이후 내용이 진행되지 않도록 보호하는 보안 점검 장치가 있다.

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

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

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

#define FAKEUID 1000

int main(int argc, char **argv, char **envp)
{
  int c;
  char token[256];

  if(getuid() != FAKEUID) {
      printf("Security failure detected. UID %d started us, we expect %d\n", getuid(), FAKEUID);
      printf("The system administrators will be notified of this violation\n");
      exit(EXIT_FAILURE);
  }

  // snip, sorry :)

  printf("your token is %s\n", token);
}

There are two important features of the "LD_PRELOAD" environment variable.

"LD_PRELOAD" 환경 변수에는 중요한 특징이 2 가지가 있다.

The first is that programs with setUID set are not applied to this environment variable.

첫 번째는, setUID가 설정된 프로그램은 이 환경 변수에 적용받지 않는다는 점이다.

The second is that if there is a function with the same name as the existing library(duplicate), the function of the library registered in this environment variable is called.

두 번째는, 기존의 라이브러리에 있는 함수와 동일한 이름의 함수가 존재한다면(중복), 두 함수 중, 이 환경 변수에 등록된 라이브러리의 함수가 호출된다는 점이다.

level13@nebula:/tmp$ ./flag13
your token is b7057■■■■■■■■■■■■■■■■■■■ac58
level13@nebula:/tmp$ su flag13
Password:
sh-4.2$
sh-4.2$ getflag
You have successfully executed getflag on a target account