[Pwnable] 21. Logical Bug: Path Traversal

wonder_land·2022년 11월 24일
0

[Pwnable]

목록 보기
21/21
post-thumbnail

[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.


  1. 서론
  2. 리눅스 경로
  3. Path Traversal
  4. Q&A
  5. 마치며

1. 서론

리눅스 프로그램은 파일 시스템에 접근하여 어떤 파일의 데이터를 읽거나, 파일에 데이터를 쓸 수 있습니다.
예를 들어, 리눅스의 기본 유틸리티인 cat으로 파일의 데이터를 출력하게 하면,
cat은 파일을 열고, 읽은 다음에 stdout에 데이터를 출력합니다.

로컬 파일 시스템에 접근하는 서비스를 외부에 공개할 때는 접근할 수 있는 파일의 경로에 제한을 두어야 합니다.
예를 들어, 사용자에게 각자의 디렉토리를 생성해주고, 그 디렉토리를 자유롭게 활용할 수 있게 해주는 서비스가 있다고 합시다.
이런 서비스를 개발할 때는 당연히 사용자 자신의 디렉토리만 접근할 수 있게 해야 합니다.
악의적인 사용자가 다른 사용자의 디렉토리에 접근하면 악용이 될 수 있기 때문이죠.

'Path Traversal'은 위와 같은 서비스가 있을 때,
사용자가 허용되지 않은 경로에 접근할 수 있는 취약점을 말합니다.
사용자가 접근하려는 경로에 대한 검사가 미흡하여 발생하며, 임의 파일 읽기 및 쓰기의 수단으로 활용될 수 있습니다.


2. 리눅스의 경로

리눅스에는 파일의 경로를 지정하는 두 가지 방법으로

  1. 절대 경로(Absolute Path)
  2. 상대 경로(Relative Path)

두 가지가 있습니다.

1) 절대 경로(Absolute Path)

  • 절대 경로(Absolute Path)
    : 루트 디렉토리(/)부터 파일에 이를 때까지 거쳐야 하는 디렉토리 명을 모두 연결하여 구성
    : 각 디렉토리는 /로 구분되며, 끝에 대상 파일의 이름을 추가하여 완성

리눅스 파일 시스템에서,
한 파일에 대응되는 절대 경로는 유일하며, 그 파일만의 고유한 값입니다.
그래서 현재 사용자가 어떤 디렉토리에 있더라도, 절대 경로를 사용하면 대상 파일을 가리킬 수 있습니다.

/a/b/target

2) 상대 경로(Relative Path)

  • 상대 경로(Relative Path)
    : 현재 디렉토리를 기준으로, 다른 파일에 이르는 경로를 상대적으로 표현한 것
    : 리눅스에서 ..은 이전 디렉토리, .은 현재 디렉토리를 의미하고, 이를 이용하여 상대 경로를 구성

절대 경로와 다르게,
어떤 파일을 가리키는 상대 경로의 수는 무한합니다.

../c/target
../../../a/b/c/target

3. Path Traversal

  • Path Traversal
    : 권한이 없는 경로에 프로세스가 접근할 수 있는 취약점

여기서의 '권한'은 리눅스 파일 시스템에서의 권한이 아닌,
서비스 로직 관점에서의 권한을 의미합니다.
(앞서 서론에서 예시로 든 예제에서 알 수 있습니다.)

아래의 예시는 Path Traversal 취약점이 있는 예제 코드입니다.

// 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;
}

위의 코드에서 /etc/passwd라는 파일을 읽기 위해서는 파일 이름이 ../etc/passwd가 되면 됩니다.

이를 통해 알 수 있듯이,
Path Traversal은 서버의 중요한 데이터를 공격자에게 노출시키는 취약점입니다.
만약 파일에 데이터를 쓸 수 있다면, /etc/passwd를 조작하여 root의 비밀번호를 제거하거나 ssh의 설정을 변경하는 등 서버에 위협되는 행위도 할 수 있습니다.


4. Q&A

-


5. 마치며

-

[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.

profile
아무것도 모르는 컴공 학생의 Wonder_Land

0개의 댓글