[Dreamhack] Path Traversal

securitykss·2023년 2월 16일
0

Pwnable 강의(dreamhack)

목록 보기
39/58

이 글은 https://dreamhack.io/lecture/courses/111 을 토대로 작성한 글입니다.

1. Introduction

리눅스 프로그램은 파일 시스템에 접근하여 어떤 파일의 데이터를 읽거나, 파일에 데이터를 쓸 수 있다.

예를 들어, 리눅스의 기본 유틸리티인 cat으로 파일의 데이터를 출력하면, cat은 파일을 열고, 읽은 다음에 stdout에 데이터를 출력한다.

로컬 파일 시스템에 접근하는 서비스를 외부에 공개할 때는 접근할 수 있는 파일의 경로에 제한을 두어야 한다.

예를 들어, 사용자에게 각자의 디렉토리를 생성해주고, 그 디렉토리를 누그나 자유롭게 활용할 수 있는 서비스가 있다면

악의적인 사용자가 다른 사용자의 파일을 훔치거나, 서버의 파일을 조작하여 서버를 장악할 수 있다.

Path Traversal은 위와 같은 서비스가 있을 때, 사용자가 허용되지 않은 경로에 접근할 수 있는 취약점을 말한다.

사용자가 접근하려는 경로에 대한 검사가 미흡하여 발상하며, 임의 파일 읽기 및 쓰기의 수단으로 활용될 수 있다.

2. 리눅스 경로

리눅스에는 파일의 경로를 지정하는 두 가지 방법으로 절대 경로(Absolute Path)와 상대 경로(Relatvie Path)가 있다.

2.1 절대 경로

절대 경로는 루트 디렉토리('/')부터 파일에 이를 때까지 거쳐야 하는 디렉토리 명을 모두 연결하여 구성한다.

각 디렉토리는 '/'로 구분되며, 끝에 대상 파일의 이름을 추가하여 완성한다.

리눅스의 파일 시스템에서 한 파일에 대응되는 절대 경로는 유일하며, 이는 그 파일만의 고유한 값이다.

그래서 현재 사용자가 어떤 디렉토리에 있더라도, 절대 경로를 사용하면 대상 파일을 가리킬 수 있다.

위의 그림에서 target을 가리키는 경로는 /a/b/c/target 이다.

2.2 상대 경로

상대 경로는 현재 디렉토리를 기준으로 다른 파일에 이르는 경로를 상대적으로 표현한 것이다.

리눅스에서 ..는 이전 디렉토리를, .는 현재 디렉토리를 의미하는데, 이를 이용하여 상대 경로를 구성할 수 있다.

절대 경로와 달리 어떤 파일을 가리키는 상대 경로의 수는 무한하다.

위의 그림에서 d를 현재 경로라고 할 때, target을 가리키는 상대 경로는 ../c/target 이다.

3. Path Traversal

Pathe traversal은 권한 없는 경로에 프로세스가 접근할 수 있는 취약점을 말한다.

여기서 권한은 리눅스 파일 시스템에서의 권한이 아니라, 서비스 로직 관점에서 권한을 의미한다.

3.1 예제 코드

/etc/passwd를 읽을 수 있는 입력을 해보자

// Name: path_traversal.c
// Compile: gcc -o path_traversal path_traversal.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int kMaxNameLen = 0x100;
const int kMaxPathLen = 0x200;
const int kMaxDataLen = 0x1000;
const char *kBasepath = "/tmp";

int main() {
  char file_name[kMaxNameLen];
  char file_path[kMaxPathLen];
  char data[kMaxDataLen];
  FILE *fp = NULL;

  // Initialize local variables
  memset(file_name, '\0', kMaxNameLen);
  memset(file_path, '\0', kMaxPathLen);
  memset(data, '\0', kMaxDataLen);

  // Receive input from user
  printf("File name: ");
  fgets(file_name, kMaxNameLen, stdin);

  // Trim trailing new line
  file_name[strcspn(file_name, "\n")] = '\0';
  
  // Construct the `file_path`
  snprintf(file_path, kMaxPathLen, "%s/%s", kBasepath, file_name);

  // Read the file and print its content
  if ((fp = fopen(file_path, "r")) == NULL) {
    fprintf(stderr, "No file named %s", file_name);
    return -1;
  }

  fgets(data, kMaxDataLen, fp);
  printf("%s", data);

  fclose(fp);

  return 0;

}

3.3 입력값

현재 경로가 /tmp로 되어 있다.

그렇기에 입력값은

../etc/passwd로 하면 읽어 낼 수 있다.

이렇게 /etc/passwd를 조작하여 root의 비밀번호를 제거하거나, ssh의 설정을 변경하는 등 서버에 위협이 되는 행위를 할 수 있다.

마치며

절대 경로(Absolute Path): 루트 디렉토리에서 접근할 파일 및 디렉터리 위치까지 모두 표현하는 방식

상대 경로(Relative Path): 현재 사용자의 위치를 기준으로 다른 파일이나 디렉터리의 경로를 표현하는 방식.

Path Traversal: 경로 문자열에 대한 검사가 미흡하여 허용되지 않는 경로에 접근할 수 있는 취약점

Reference

https://dreamhack.io/lecture/courses/111

profile
보안 공부를 하는 학생입니다.

0개의 댓글