들어가며
서론
리눅스는 파일 시스템에 접근해서 파일의 데이터를 읽거나, 쓸 수 있다.
cat으로 출력하면, cat은 파일을 열고, 일고 stdout에 데이터를 출력한다.
로컬에서 접근하는걸 외부에 공개할때 접근에 제한을 두어야 한다..
- 예를 들어, 사용자에게 각자 디렉토리를 주고, 자유롭게 활용할 수 있게 한다면,
- 개발자는 사용자의 디렉토리만 접근하게 해야한다.
- 나쁜 놈들이 다름 파일을 훔치거나, 조작하여 서버를 장악할 수 있기 때문이다.
Path Traversal
: 위와 같은 서비스에서 사용자가 허용되지 않은 경로에 접근할 수 있는 취약점을 말한다.
사용자가 접근하는 경로에 검사가 나빠서, 임의 파일 읽기 쓰기의 수단으로 활용될 수 있다.
리눅스 경로
절대 경로와 상대 경로
리눅스에는 파일의 경로를 지정하는데 2가지 방법이 있는데
- 절대 경로(Absolute Path)와
- 상대경로(Relative Path)가 있따.
디렉토리 구조 예시
절대 경로
루트 디렉토리('/')부터 파일에 이를 때까지 거쳐하는 디렉토리 이름을 모두 연결해서 한다.
각 디렉토리는 '/'로 구분하고, 끝에 파일이름을 추가하여 완성한다
절대경로는 그 파일만의 값이 유일한 값이다. 그래서 현재 어디에 있더라도, 절대 경로로는 그 파일을 가리킨다.
ex) 아까 예시로 보면 /a/b/c/target 이게 절대 경로다.
상대 경로
현재 디렉토리를 기준으로 해서 다른 파일의 경로를 상대적으로 표현했따.
리눅스에서 '..는 이전 디렉토리를, '.'은 현재 디렉토리를 의미한다.
여러게가 나올 수 잇다.
ex) 현재 디렉토리가 d 일때 target을 가리키려면, ../c/target , ./../c/target , ../../../a/b/c/target 등이 있다.
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;
}
👆 이런 코드가 있다. 여기에는 path traversal 취약점이 있다.
'/etc/passwd'를 읽을 수 있는 입력을 찾아보자
아래는 코드를 분석한 것이다.
1. 헤더 파일 포함
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
stdio.h : 표준 입출력
stdlib.h : 일반적인 유틸리티 함수 제공
string.h : 문자열 관련 함수 사용
2. 상수 정의
const int kMaxNameLen = 0x100;
const int kMaxPathLen = 0x200;
const int kMaxDataLen = 0x1000;
const char *kBasepath = "/tmp";
- kMaxNameLen: 파일 이름의 최대 길이를 256(0x100) 바이트로 정의합니다.
- kMaxPathLen: 전체 파일 경로의 최대 길이를 512(0x200) 바이트로 정의합니다.
- kMaxDataLen: 파일에서 읽어올 데이터의 최대 길이를 4096(0x1000) 바이트로 정의합니다.
- kBasepath: 기본 경로로, /tmp 디렉토리를 지정합니다.
3. 변수 선언 및 초기화
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);
memset 함수를 사용하여 이 변수들을 모두 널 문자('\0')로 초기화합니다.
버퍼의 불필요한 데이터를 없게 한다.
4. 사용자 입력 받기
// Receive input from user
printf("File name: ");
fgets(file_name, kMaxNameLen, stdin);
fgets: 입력 받아 file_name 변수에 저장합니다. 최대 256바이트까지 입력받을 수 있습니다.
5. 입력값 처리
// Trim trailing new line
file_name[strcspn(file_name, "\n")] = '\0';
fgets는 입력후 자동으로 \n을 추가함. 이거를 제거하는 코드
'strcspn으로 \n을 찾고 null문자를 넣는다;.
6. 파일 경로 구성
// Construct the `file_path`
snprintf(file_path, kMaxPathLen, "%s/%s", kBasepath, file_name);
snprintf 를 사용하여 파일 경로를 구성
기본경로(/tmp)와 사용자가 입력한 파일 이름결 합쳐서 최종 경로를 만듬.
ex) temp.txt 입력하면 /temp/temp.txt 가 됨
7. 파일 열기 및 읽기
// Read the file and print its content
if ((fp = fopen(file_path, "r")) == NULL) {
fprintf(stderr, "No file named %s", file_name);
return -1;
}
fopen: 파일 경로를 이용해 파일을 읽기 모 드("r")로 연다. (파일이 없거나 실패하면 null 반환)
파일을 열지 못하면 에러 메세지 출력하고 종료한다.
fgets(data, kMaxDataLen, fp);
printf("%s", data);
fgets : 파일에서 데이터를 읽어 data 변수에 저장 ( 최대 4096바이트)
그리고 읽은 데이터를 출력한다...
8. 파일 닫기 및 프로그램 종료..
fclose(fp);
return 0;
열었던 파일을 닫고 정상적으로 종료한다.
File name: ../etc/passwd
이렇게 ../를 사용해 상위 디렉토리에 접근 할 수 있다.
path traversal은 서버의 데이터를 공격자에게 노출하고 파일에 데이터를 쓸 수 있다면 조작할 수 도 있다.
마치며
- 절대 경로(Absolute Path): 루트 디렉토리에서 접근할 파일 및 디렉터리 위치까지 모두 표현하는 방식
- 상대 경로(Relative Path): 현재 사용자의 위치를 기준으로 다른 파일이나 디렉터리의 경로를 표현하는 방식.
- Path Traversal: 경로 문자열에 대한 검사가 미흡하여 허용되지 않는 경로에 접근할 수 있는 취약점
끝
'hacking > pwnable' 카테고리의 다른 글
[Dream hack] sint (p32) (0) | 2024.09.05 |
---|---|
[Dream hack] cmd_center (0) | 2024.09.04 |
[Dream hack] Tool: pwntools (0) | 2024.08.07 |
[Dream hack] Quiz: Static Link vs. Dynamic Link-4 (0) | 2024.08.02 |
[Dream hack] Quiz: Static Link vs. Dynamic Link-3 (0) | 2024.08.02 |