July 07, 2019

Nebula level11 write up

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

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

Level11

About
The /home/flag11/flag11 binary processes standard input and executes a shell command.

관련 사항.
실행파일 "/home/flag11/flag11"은 표준 입력을 받고 쉘 명령을 실행한다.

There are two ways of completing this level, you may wish to do both :-)

클리어에는 두 가지 방법이 있는데, 두 방법 모두 시도해보기 바란다.

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

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

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

/* * Return a random, non predictable file, and return the file descriptor for it. */

int getrand(char **path)
{
  char *tmp;
  int pid;
  int fd;

  srandom(time(NULL));

  tmp = getenv("TEMP");
  pid = getpid();

  asprintf(path, "%s/%d.%c%c%c%c%c%c", tmp, pid,
      'A' + (random() % 26), '0' + (random() % 10),
      'a' + (random() % 26), 'A' + (random() % 26),
      '0' + (random() % 10), 'a' + (random() % 26));

  fd = open(*path, O_CREAT|O_RDWR, 0600);
  unlink(*path);
  return fd;
}
void process(char *buffer, int length)
{
  unsigned int key;
  int i;

  key = length & 0xff;

  for(i = 0; i < length; i++) {
      buffer[i] ^= key;
      key -= buffer[i];
  }

  system(buffer);
}

#define CL "Content-Length: "

int main(int argc, char **argv)
{
  char line[256];
  char buf[1024];
  char *mem;
  int length;
  int fd;
  char *path;

  if(fgets(line, sizeof(line), stdin) == NULL) {
      errx(1, "reading from stdin");
  }

  if(strncmp(line, CL, strlen(CL)) != 0) {
      errx(1, "invalid header");
  }

  length = atoi(line + strlen(CL));

  if(length < sizeof(buf)) {
      if(fread(buf, length, 1, stdin) != length) {
          err(1, "fread length");
      }
      process(buf, length);
  } else {
      int blue = length;
      int pink;

      fd = getrand(&path);

      while(blue > 0) {
          printf("blue = %d, length = %d, ", blue, length);

          pink = fread(buf, 1, sizeof(buf), stdin);
          printf("pink = %d\n", pink);

          if(pink <= 0) {
              err(1, "fread fail(blue = %d, length = %d)", blue, length);
          }
          write(fd, buf, pink);

          blue -= pink;
      } 

      mem = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
      if(mem == MAP_FAILED) {
          err(1, "mmap");
      }
      process(mem, length);
  }
}

By registering the public key (mykey.pub) value in the "~ / .ssh" directory of the flag11 account, you can log in with the flag11 account without a password.

공개키(mykey.pub) 값을 flag11 계정의 "~/.ssh" 디렉토리에 등록하면, 비밀 번호 없이도 flag11 계정으로 로그인할 수 있다.

The private key and the public key are paired with each other and are designed to recognize that they originated in the same place.

개인키와 공개키는 서로가 쌍을 이루며, 같은 곳에서 기원했음을 알아볼 수 있도록 설계되어 있다.

In general, when encrypting arbitrary information with a private key and transmitting it, the server decrypts with a public key. if it is successful, it means a pair of authentication information that can be trusted by each other.

일반적으로, 임의의 정보를 개인키로 암호화하여 전송하면, 서버는 공개키로 해독(복호화)하는데, 만약 성공하면 서로가 신뢰 할 수 있는 인증정보의 쌍임을 아는 방식이다.

level11@nebula:/tmp$ ssh -i ./mykey flag11@127.0.0.1
……
flag11@nebula:~$ getflag
You have successfully executed getflag on a target account