<<

PHP LFI

web

문제

문제 분석

문제 웹사이트에 접속하면 다음과 같은 화면이 나타난다.

웹페이지 파일

hello, test 링크로 들어가보았다.

파일

테스트 하기 위한 “파일” 이라고 설명하고 있다.

문제

PHP 에서 발생할 수 있는 취약점 중, 파일에 관련된 취약점은 Local File Inclusion (LFI), Remote File Inclusion (RFI) 등이 있으며, 이 문제의 이름에서 알 수 있듯이 LFI 취약점을 사용하여 플래그를 획득하면 되는 문제이다.

또한 플래그는 /flag 파일을 실행하여 얻을 수 있다고 한다.

LFI 란?

LFI Local File Inclusion (LFI) 는 웹 서버에서 발생하는 취약점 중 하나로, 웹 서버에서 파일을 읽어오는 과정에서 발생하는 취약점이다.

예를 들어, 여러 페이지가 있는 웹사이트에서, include() 등 함수를 사용하여 다른 페이지(파일)를 불러올 때, 사용자가 입력한 값을 그대로 사용하게 되면, 사용자가 입력한 값을 조작하여 다른 파일을 불러올 수 있게 된다.

공격 방법

기본적인 LFI

기본적인 LFI에 사용되는 경로를 삽입해보았다.

?inc=/etc/passwd 를 입력하여 리눅스 사용자 정보를 확인할 수 있었다.

하지만 이 문제에서는 /flag 파일을 실행해야 함으로 다른 방법을 찾아야 한다.

/flag 를 삽입해보았으나, php 스크립트에서 필터링이 걸려있는 것으로 보인다. 필터링을 우회하기 위해, Percent Encoding을 사용하여 /flag 를 인코딩하여 삽입해보았다.

?inc=/fl%61g 를 입력하여 실행하였으나, 일반 문자열로 실행할 때와 마찬가지로 문자열이 필터링 되는것을 확인하였다.

no hack

Null Byte, 더블 인코딩, Path and Dot Truncation 등을 시도하였으나 원하는 FLAG 파일은 얻을 수 없었다.

PHP Wrapper 를 사용한 페이로드를 사용해보았다.

PHP에서의 wrapper 란?

PHP메뉴얼 에서는 wrapper를 다음과 같이 설명하고 있다.

PHP comes with many built-in wrappers for various URL-style protocols for use with the filesystem functions such as fopen(), copy(), file_exists() and filesize().
PHP에는 fopen(), copy(), file_exists() 및 filesize() 와 같은 파일 시스템 함수와 함께 사용할 수 있는 다양한 URL 스타일 프로토콜에 대한 많은 내장 래퍼가 있습니다.

파일 시스템 함수에, 실제 파일의 경로 대신 URL 스타일의 프로토콜 (http, ftp, data, php, zip 등) 을 사용할 수 있게 해주는 것이다.

except:// 래퍼를 사용해보자. 이 래퍼는 시스템 명령어를 실행하여 결과를 내용으로 반환하는 래퍼이다.

?inc=except://ls 를 입력하여 실행하였으나, 필터링이 걸려있는 것을 확인하였다.

except://

URL 프로토콜 또한 필터링 하는것을 확인하였다.

://

위 글과 이 사진으로 ://, flag 등을 필터링 하는것을 알 수 있다.

:// 문자열을 사용하지 않고 필터링을 우회할 수 있는 방법을 찾아보자.

Data URI Scheme 활용

PHP 메뉴얼의 data:// 문서를 참고하면, data 프로토콜 래퍼가 RFC 2397 표준을 따르고 있음을 알 수 있다.

RFC 2397 문서에 따르면, Data URI의 형식은 다음과 같다.

data:[<mediatype>][;base64],<data>

이를 통해, data 프로토콜은 파일의 콘텐츠를 URL로 직접 삽입할 수 있으며, base64 인코딩도 지원된다는 것을 확인할 수 있다.

이제 이를 활용하여 PHP 코드가 실행되도록 페이로드를 구성해 보자.

?inc=data:text/plain;base64,PD9waHAgZWNobyAiSGVsbG8hIiA/Pg==

<?php echo "Hello!"; ?> 를 base64로 인코딩하여 삽입하였다.

서버에서는 다음과 같이 실행된다는 것을 유추할 수 있다.

<?php

$inc = $_GET['inc'];

// (필터링 함수)

include($inc); // -> inc 에는 디코딩된 PHP 코드가 들어가게 되고, 이를 실행하게 된다.

?>

hello

위와 같이 Hello! 가 출력되는 것을 확인할 수 있다.

이제 이를 활용하여 FLAG 파일을 실행해보자.

PHP 에서는 프로세스를 실행할 때, system(), exec(), shell_exec() 등의 함수를 사용하여 프로세스를 실행할 수 있다.

system() 함수를 사용하여 /flag 바이러리를 실행하도록 페이로드를 구성해보자.

import base64

payload = "<?php system('/flag'); ?>"

# 결과값: data:text/plain;base64,PD9waHAgc3lzdGVtKCcvZmxhZycpOyA/Pg==
print(f"data:text/plain;base64,{base64.b64encode(payload.encode()).decode()}")

FLAG

flag 바이너리를 실행하여 플래그를 획득할 수 있다.

flag에서도 볼수 있듯이 lfi 라기보단 php의 allow_url_include 취약점에 더 가까운 것 같다

주석을 추가한 index.php 의 코드 ```php hello

test

"; } phpinfo(); //php.ini:allow_url_include=On //php.ini:allow_url_fopen=On ?> ```

취약점 해결방법

  • PHP 설정에서 allow_url_includeallow_url_fopenOff 로 설정한다.