회원가입

로그인

아이디
비밀번호
ID/PW 찾기
아직 회원이 아니신가요? 회원가입 하기

웹 해킹 2/15 (Open 함수 사용시 주의할점)

Profile
:맥노턴
/*
http://beist.org
beist@hanmail.net
wowcode at wowhacker team
*/
2) Open 함수 사용시 주의할점

이번 주제는 Web 프로그래밍 중에서 가장 일어나기 쉬운 버그 중의 하나이다.
Web CGI 에서 File Open 은 많이 쓰이는 알고리즘 중에 하나이다. 하지만
이 알고리즘이 잘못 쓰여졌을 경우에 심각한 Security Hole 을 일으킬 수도
있다.

Web CGI 에서 File Open 이 쓰이는 경우를 보자. 예를 들어 Web Page 의 Menu
를 구현한다고 하자.

menu.html

<html>
<head>
<title>Beist Home 에 오신 것을 환영합니다.</title>
</head>
<body>
<center>
<a href=link.php?file=profile.html>나의소개</a><br>
<a href=link.php?file=board.html>게시판</a><br>
<a href=link.php?file=site.html>추천사이트</a><br>
</center>
</body>
</html>

간단하게 구현해 본 Menu 이다. Menu 는 나의소개, 게시판, 추천사이트로 나뉘
어져 있으며 link.php 라는 File 을 통해 접근을 한다. 각 페이지를 모두 설명할
필요는 없으니 profile.html 파일만 따로 작성하여 설명하겠다.

link.php

1   <?
2
3   $exist = file_exists("./$file");
4   if(!$exist)
5   {
6    echo "$file 파일은 없다.\n";
7    exit;
8   }
9
10  $fp=fopen("./$file", "r");
11
12  while(!feof($fp))
13  {
14     $msg .= fgets($fp,100);
15  }
16
17  $msg=nl2br($msg);
18
19  echo $msg;
20
21  ?>

profile.html

<html>
<head>
<title>yo man.. i'm beist</title>
<body>
전 남자에요. 84 년생이고요. 별명은 스누피.
</body>
</html>

link.php 의 기능은 간단하다. 먼저 fopen 을 시도하기 전에 file_exists 를
이용하여 현재 디렉토리에 그런 파일이 있는지 없는지 확인을 하고 없으면
script 실행을 중지시킨다. 존재한다면 fopen 을 이용하여 현재 디렉토리를 기준으로
read mode 로 file 핸들러를 연다. 그리고 $msg 에 file 의 내용을 담은 후에
사용자에게 뿌려준다. 여기에서는 현재 directory 를 기준으로 한다는 것을
명시하기 위하여 $file 앞에 ./ 를 붙였지만 ./ 를 붙이지 않아도 php 에서는
현재 directory 에서부터 찾으라는 것으로 인식한다.

만약 link.php?file=profile.html 이라고 한다면 file 변수의 값인 profile.html  을 열어서 사용자에게 보여주는 것이다.

[요청]
http://server/link.php?file=profile.html

[결과]
전 남자에요. 84 년생이고요. 별명은 스누피.

하지만 이런 알고리즘은 취약성을 갖는다. link.php 를 요청할때 file 의 변수를
cracker 임의대로 변경하여 요청을 한다면 link.php 에서는 cracker 가 임의로
변경한 file 의 내용을 돌려줄 것이다.

예를 들어

[요청]  http://server/link.php?file=../../../../../../../../../etc/passwd
  
[결과]
root:*:0:0:root:/root:/usr/local/bin/bash
daemon:*:1:1:Owner of many system processes:/root:/sbin/nologin  operator:*:2:5:System &:/:/sbin/nologin  bin:*:3:7:Binaries Commands and Source,,,:/:/sbin/nologin  tty:*:4:65533:Tty Sandbox:/:/sbin/nologin  kmem:*:5:65533:KMem Sandbox:/:/sbin/nologin  ................................

file 의 값을 상위디렉토리로 이동하기 위하여 ../ 를 여러개를 붙였고 etc
directory 밑에 존재한 passwd file 을 열어서 cracker 는 passwd file 을
볼 수 있었다.

해결책을 알아 보자.

개발자가 이 상황에서 신경써야 할 부분은 link.php 를 호출할때 인자로 딸려오는
변수 $file 이다. cracker 가 $file 의 내용을 변경하더라도 link.php 에서는
올바르게 처리할 수 있어야 한다.

추천하는 처리 방법은 $file 의 내용을 조사하여 .. 같은 문자가 있다면 필터링을
하는 것이다. 다음은 취약성을 개선한 소스이다.

link2.php

1  <?
2   if(eregi("\.\.", $file))
3   {
4     echo "장난하니?.. file 이름에 .. 가 들어있으면 안됩니다.";
5     exit;
6   }
7   $exist = file_exists("./$file");
8   if(!$exist)
9   {
10   echo "$file 파일은 없다.\n";
11   exit;
12  }
13
14  $fp=fopen("./$file", "r");
15
16  while(!feof($fp))
17  {
18    $msg .= fgets($fp,100);
19  }
20
21  $msg=nl2br($msg);
22
23  echo $msg;
24
25  ?>

2 번째 라인에서 eregi 를 이용하여 $file 의 내용에 .. 가 있는지 check 를
하였다. 만약 .. 라는 스트링이 $file 안에 존재한다면 cracking 시도로 간주
하고 script 실행을 중지시키고, 들어있지 않다면 정상적으로 script 를 계속
실행한다.

[요청]  http://server/link.php?file=../../../../../../../../../etc/passwd
  
[결과]
장난하니?.. file 이름에 .. 가 들어있으면 안됩니다.

이런 식으로 해결을 할 수도 있고 eregi_replace 를 이용하여 .. 를 공백으로
만들어 무시할 수도 있을 것이다.

위의 방법에 대하여 어떤 문제점이 발생할 수도 있다. Shell 에서는 (bash
shell 기준) ../ 말고도 상위디렉토리로 접근하는 방법이 있다.

예를 들어

$ cd ./.\./

이렇게 입력하면 상위 디렉토리로 이동한다는 것을 뜻한다. 그래서 만약 해커가

http://server/link.php?file=./.\./.\./.\./.\./.\./etc/passwd

이런식으로 요청을 한다면 eregi 는 체크를 하지 못할 것이다. 하지만 이 것은 걱정
하지 않아도 된다. 왜냐하면 data 가 전송되어질때 encode-decode 과정에서 \ or
' or " 앞에는 \ 문자가 하나 더 붙기 때문이다. 그래서 실제로 저렇게 요청을
한다더라도

./.\\./.\\./.\\./.\\./.\\./etc/passwd

이란 파일을 열려고 시도하게 된다. 하지만 만약 php.ini 같은 설정 파일에서
magic_quote 값을 변경하였을 경우 escape (\) 문자가 앞에 붙지 않게 된다.
그래서 cracker 의 요청대로 passwd 파일을 open 할 것이고 출력하게 된다.

Profile
:맥노턴
레벨 31
370472/
-7%
McNorton & Education Lab.
Director
댓글
0
댓글 쓰기
권한이 없습니다.

로그인

아이디
비밀번호
ID/PW 찾기
아직 회원이 아니신가요? 회원가입 하기