프로젝트/DVWA 실습

DVWA 실습 #5-1 - File Inclusion(low)

하루히즘 2021. 1. 12. 16:29

2021/01/12 - [프로젝트/DVWA 실습] - DVWA 실습 #5 - File Inclusion

 

DVWA 실습 #5 - File Inclusion

DVWA의 네 번째 실습 대상인 File Inclusion이다. 각 파일을 클릭하면 특정 php 코드가 실행되며 URL에 파일 이름이 파라미터로 전달된다. 이 특성을 활용하여 웹 서버가 다른 파일을 읽도록 하는 것이

haruhiism.tistory.com

문제 해결 방법

Low 단계에서는 아무런 필터링도 거치지 않고 파일 이름을 파라미터로 받아서 include 하고 있다. 

세 개의 파일이 각각 고유의 링크를 가지고 있으며 page 파라미터로 파일 이름을 확장자까지 포함하여 GET메서드로 직접 넘기면 해당 파일의 내용이 페이지에 렌더링 된다. 이 단계에서는 단순히 URL의 page 파라미터를 조작하면 LFI, RFI 둘 다 실행할 수 있다. 일단 이번 실습에서 요구하는 "../hackable/flags/fi.php"를 include 해보자.

다른 곳에 위치한 fi.php 파일을 Directory Traversal을 이용하여 읽었기 때문에, 정확히는 해당 php 파일을 실행했기 때문에 다른 파일의 내용(영화에서 나온 명언 목록)이 현재 페이지에 출력된 것을 알 수 있다. 비슷하게 응용하면 /etc/passwd 파일도 읽을 수 있을 것이다. 그런데 문제에서는 총 5개의 명언을 찾길 원하는데 현재 include 된 파일에는 3개밖에 보이지 않는다. 그렇다면 php 소스 코드를 직접 읽어봐야 숨어있는 명언을 찾을 수 있지 않을까? 이때는 php의 Wrapper를 사용할 수 있다.

 

PHP: Supported Protocols and Wrappers - Manual

Even though their names will be the same, you can have more than one //memory or //temp stream open concurrently; each time you fopen() such a stream, a NEW stream will be opened independently of the others.This is hinted at by the fact you don't add any u

www.php.net

php에서는 include()나 fopen() 같은 파일 시스템 함수를 읽을 때 다양한 URL 스타일 프로토콜을 사용할 수 있도록 지원하고 있다. HTTP의 'http://', FTP의 'ftp://' 처럼 URL에 붙는 프로토콜 스타일을 지원하는 것인데 웹 브라우저에서 해당 프로토콜로 외부 자원에 접근하기 위해 사용할 때와 거의 동일하게 사용할 수 있다. 그러나 http 프로토콜이 'http:'처럼 불완전(의도된 기능이지만)하게 입력해도 제대로 동작하는 반면 php Wrapper에서는 'scheme://' 형식으로 지정해야 한다. 

 

Wrapper는 파일(file://), HTTP(http://), FTP(ftp://), I/O Streams(php://) 등이 있는데 여기서 I/O Streams를 활용하면 php 소스 코드를 추출할 수 있다(드림핵). 정확히는 File Inclusion 공격으로 include되는 내부 php 소스 코드를 base64처럼 php 엔진에 의해 실행되지 않는 코드로 인코딩한 후 출력하여 이를 다시 디코딩하여 원래 소스 코드를 찾아내는 것이다. I/O Streams Wrapper는 다양한 I/O Stream(stdin, stdout, stderr)에 연결할 수 있으며 공격자가 입력한 파라미터에 의해 파일 스트림이 열릴 수도 있다. 이 파일 스트림으로 연 php 소스 코드를 I/O Streams의 filter 기능을 활용하여 소스 코드를 읽어서 실행하기 전에 다른 형식(base64)으로 변환할 수 있는 것이다. 필터는 문자열, 변환, 압축, 암호화 총 4가지가 있는데 이 중 변환 필터의 convert.base64-encode/decode를 사용할 수 있다. 이는 모든 입력값에 대해 base64_encode(), base64_decode() 함수를 호출하는 것과 동일하며 다음처럼 읽을 파일과 작업에 적용할 필터를 지정할 수 있다.

include 'php://filter/read=convert.base64-encode/resource=test.php';

필터를 적용하겠다는 I/O Stream을 의미하는 "php://filter/" 같은 URL에 위처럼 read, write, resource 매개변수를 슬래시로 구분하여 전달해줄 수 있다. 위 코드는 스트림에서 리소스를 읽을 때(read) base64로 인코딩하는 필터(convert.base64-encode)를 적용하며 리소스(resource)는 'test.php' 파일이라는 것을 의미한다. 즉 include 명령어로 test.php 파일 스트림을 읽는데 base64로 인코딩 된 것으로 읽으라는 것이며 이렇게 되면 test.php 파일을 읽고 실행하는 게 아니라 인코딩 된 test.php 파일의 소스 코드가 대신 출력된다.

실제로 플래그 파일에 대해서 필터를 적용한 결과 위처럼 base64 코드가 출력되었으며 이를 디코딩하면 아래처럼 fi.php 파일의 소스 코드를 확인할 수 있다.

소스 코드를 확인한 결과 제임스 본드, 셜록 홈즈, 해커스뿐 아니라 로미오와 줄리엣, 스니커즈 등 다양한 영화의 명대사가 담겨있는 것을 확인할 수 있었다. 아무튼 이렇게 php의 Wrapper 기능을 활용하여 총 5개의 대사를 모두 찾을 수 있었다.

재밌는 것은 file4.php 파일도 있다는 것이다. 파일 목록이나 어디에도 나와있지 않았지만 파일명이 file1.php, file2.php, file3.php 인 것을 보고 혹시 file4도 있나 추측해서 접속해봤더니 찾을 수 있었다. 주어진 파일만 보지 말고 숨겨진 파일도 예측하면서 샅샅이 찾아보는 습관을 가지라는 의미인 것 같다.