[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.
- 서론
- 리눅스 경로
- Path Traversal
- Q&A
- 마치며
리눅스 프로그램은 파일 시스템에 접근하여 어떤 파일의 데이터를 읽거나, 파일에 데이터를 쓸 수 있습니다.
예를 들어, 리눅스의 기본 유틸리티인 cat
으로 파일의 데이터를 출력하게 하면,
cat
은 파일을 열고, 읽은 다음에 stdout
에 데이터를 출력합니다.
로컬 파일 시스템에 접근하는 서비스를 외부에 공개할 때는 접근할 수 있는 파일의 경로에 제한을 두어야 합니다.
예를 들어, 사용자에게 각자의 디렉토리를 생성해주고, 그 디렉토리를 자유롭게 활용할 수 있게 해주는 서비스가 있다고 합시다.
이런 서비스를 개발할 때는 당연히 사용자 자신의 디렉토리만 접근할 수 있게 해야 합니다.
악의적인 사용자가 다른 사용자의 디렉토리에 접근하면 악용이 될 수 있기 때문이죠.
'Path Traversal'은 위와 같은 서비스가 있을 때,
사용자가 허용되지 않은 경로에 접근할 수 있는 취약점을 말합니다.
사용자가 접근하려는 경로에 대한 검사가 미흡하여 발생하며, 임의 파일 읽기 및 쓰기의 수단으로 활용될 수 있습니다.
리눅스에는 파일의 경로를 지정하는 두 가지 방법으로
두 가지가 있습니다.
- 절대 경로(Absolute Path)
: 루트 디렉토리(/
)부터 파일에 이를 때까지 거쳐야 하는 디렉토리 명을 모두 연결하여 구성
: 각 디렉토리는/
로 구분되며, 끝에 대상 파일의 이름을 추가하여 완성
리눅스 파일 시스템에서,
한 파일에 대응되는 절대 경로는 유일하며, 그 파일만의 고유한 값입니다.
그래서 현재 사용자가 어떤 디렉토리에 있더라도, 절대 경로를 사용하면 대상 파일을 가리킬 수 있습니다.
/a/b/target
- 상대 경로(Relative Path)
: 현재 디렉토리를 기준으로, 다른 파일에 이르는 경로를 상대적으로 표현한 것
: 리눅스에서..
은 이전 디렉토리,.
은 현재 디렉토리를 의미하고, 이를 이용하여 상대 경로를 구성
절대 경로와 다르게,
어떤 파일을 가리키는 상대 경로의 수는 무한합니다.
../c/target
../../../a/b/c/target
- 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
의 설정을 변경하는 등 서버에 위협되는 행위도 할 수 있습니다.
-
-
[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.