

문제는 PHP로 작성된 백오피스 시스템으로, 특정 경로의 파일을 열람할 수 있는 기능이 존재했다.
초기에 /view.php?file=... 방식으로 접근하여 LFI(Local File Inclusion)를 시도했으나, 다음과 같은 필터링이 있었다.
if (preg_match('/flag|:/i', $file)) {
exit('Permission denied');
}
즉, flag나 :가 포함된 경로는 모두 차단되었고, 이는 /var/www/uploads/flag.php나 php://filter 접근이 불가능함을 의미했다.
하지만 index.php의 코드를 분석해보니 다음과 같은 코드가 발견되었다.
include $_GET['page'] ? $_GET['page'].'.php' : 'main.php';
여기에는 필터링이 전혀 없었기 때문에, 이쪽에서 직접 LFI를 시도할 수 있다는 걸 알게 되었다.
먼저 파일을 실행하려고 다음과 같이 접근했지만
/index.php?page=../uploads/flag

can you see $flag?란 결과만 출력되었다.
아마 파일을 실행하는것에 문제가 있다고 판단했다.
이후 php://filter를 통해 파일 실행이 아닌 파일 내용을 base64로 읽어오는 우회 방식을 사용했고,
아래와 같이 요청함으로써 소스코드를 획득하였다.
/index.php?page=php://filter/convert.base64-encode/resource=/var/www/uploads/flag

결과로 출력된 base64 문자열을 디코딩한 결과, flag를 성공적으로 획득할 수 있었다.
이번 문제를 통해 단순한 LFI만으로는 충분하지 않으며, 코드 실행과 코드 열람은 다르다는 점을 명확히 느꼈다.
초기에는 필터링된 /view.php에서 우회 시도를 반복했지만, 실제 취약점은 필터링이 없는 index.php에서 발생했다.
또한, php://filter/convert.base64-encode를 이용한 소스코드 유출 기법은 LFI 문제에서 매우 강력한 테크닉이라는 것을 체감할 수 있었다.
단순히 파일을 include하거나 실행하려는 시도 외에도, 실행되지 않는 .php 파일의 내용을 읽고 싶을 때 filter를 이용한 접근이 유효하다는 점을 실습을 통해 배웠다.
앞으로 LFI 문제가 나왔을 때는 include되는 대상과 위치, 필터링 여부, 출력 여부를 종합적으로 고려해서 접근하는 습관을 가져야겠다고 느꼈다.