본문으로 바로가기
반응형
< 제로보드 4.0.0 pl4 취약점 >
[제작: AmesianX in Null@Root ( TFT4 Version )]

( *주의: 윈도 사용하시면 워드패드에서 줄 바꾸지 않음을 체크하시고 보십시오. )

1. 서론
안녕하십니까?
언더 해커 그룹 Null@Root 에서 TFT4( Task Force Team 4: Web Board Project ) 의 팀장을 맡게된 AmesianX 입니다.
이 무더운 여름, 밤 잠은 설치시지 않고 잘 주무시는 지요?
저희 TFT4 팀은 밤잠도 설쳐가며 몇일간의 끊임없는 삽질과 분석의 결과 여러 국내 게시판의 취약점을 찾아내었습니다.
지금부터 설명드리는 사항은 현시각으로 봤을때 가장 최신 버젼인 제로보드(ZeroBoard) 4.0.0 pl4 버젼에서 발견된 취약점을 근거로 해킹을 하는 해커의 입장에서 쓴 가상 시나리오 입니다.

2. 본론 - [ 소주제: 제로보드 4.0.0 pl4 을 해킹하려면 발상의 전환이 필요했다..!? ]
제로보드는 국내에서 가장 널리 쓰이고 있는 보드로 알고 있습니다. 그래서 그런지 그 기능과 스킨이 아주 훌륭해 보였습니다. 물론, 소스는 말할 필요도 없이 꼼꼼하고 훌륭한 테크닉으로 보였습니다. 제가 PHP로 게시판을 만든 다면 부분부분 소스를 뽑아서 쓰고 싶어질만큼 말입니다. 게다가 이 게시판을 만든 자칭 zero님은 해커들의 공격에 대비해서 개발을 하시는 훌륭한 분이신 것 같아서 이런 게시판을 상대로 취약점을 찾아내기란 고달픈 작업이었습니다.
( 제로보드 옛 버젼에서 if 문 중에 주석을 달아 놓으셨는데 조건에 안맞으면 "틀림없이 해킹이다"라고 달아 놓으셨더군요.. ^^; )
처음에 시도한 것이 해커들이 주로 타겟으로 삶는 업로드를 이용한 공격이었습니다. PHP 파일을 업로드한후 실행시켜서 관리자 권한(저희는 관리자 권한을 목표로 했음, 관리자 권한을 따면 쉘 띄우는 건 기존의 방법이 있으므로..)을 획득하는 시나리오 였습니다. 예전에 테크노트2001 보드에서 관리자 권한을 획득할때 발견했던 업로드 버그를 사용했더니 필터링에 걸리는 파일인 PHP와 CGI, HTML, ... 기타 등등 ( write_ok.php 파일을 보면 필터링 코드를 볼 수 있음.) 을 제외하고는 원하는 상위 디렉토리에 업로드가 가능했습니다.

==================================
버그 1: 상위디렉으로 업로드 버그
==================================

첨부파일란에 c: empa.txt?../a.txt 라고 입력하고 글 입력을 완료하면 a.txt 라는 파일은 본래의 업로드 디렉토리 속 으로 들어가지 않고 그 상위 디렉토리로 들어가게 된다. 물론, a.txt 파일의 내용도 제대로 보존된 상태로 말이다. 기존에는 ../a.txt 라는 식으로 업로드를 해서 단순히 링크를 거는 식을 취하거나 아니면 본래 업로드 디렉토리속에 들어 가되 확장자 필터링을 피하는 방식이었다. 예를 들어, a.txt.php 같은 방식을 말한다.
하지만, c: empa.txt?../a.txt 는 ?를 기준으로 좌우를 분리 했을때 왼쪽의 c: empa.txt 는 지금 업로드 하고 있는
파일의 내용이 되며 오른쪽에 ../a.txt 는 업로드 하는 파일의 이름으로 간주된다.
의심이 들거든, 직접 테스트 해보시길 바람. 여기에는 약간의 공식이 적용되기도 했는데 예를 들어, 상위디렉토리로 네번 을 거슬러 올라간다고 친다면 c:\cdea.txt?../../../../a.txt 가 되어야만 제대로 업로드 되기도 한다.
해설을 하자면 ?을 기준으로 좌측의 디렉 수는 5개(temp,b,c,d,e) 오른쪽의 디렉 수는 4개 (../../../../) 로써 오른쪽이 하나가 적을때 제대로 되는 것인데... 비교적 일정한 패턴을 갖고 있는 것 같았다. 중요한 것은 ? 을 기준으로 오른쪽 부분에 ../../cgi-bin/a.txt 처럼 디렉토리는 지정 할 수 없다. 오로지 ../ 의 연속만이 통용될 뿐이었다.
게시판에 따라서 c: empa.txt?/../a.txt 처럼 앞에 /를 붙여서 /../a.txt 해야 하는 경우도 있다. 이것은 게시판에서 자체적으로 / 를 붙이는 코드를 안 넣었기 때문인데 킴스보드와 제로보드는 앞에서 말한 부분중에 /../a.txt 가 아니라 ../a.txt로 해야만 제대로 될 것이다. 이유는 소스중에 / 를 자체적으로 붙이고 있다.

( P.S: 이 방법이 테크노트, 킴스보드, 제로보드 에서 다 통한 것으로 보아서 게시판 자체의 취약점이 아니라 아파치 자체 의 버그가 아닐까 생각된다. 아니면 일부러 넣은 부가기능이라던지.. )
=======================================================
버그 2: 변수 내용을 바꿔서 다른 파일 복사해내기!
( 일명: 파일 복사 버그 )
[ MySql ID와 암호를 획득하는데 사용된 버그.. !! ]
=======================================================

다음의 코드를 발견해 내기까지 수많은 삽질이 있었다....
멤버 여러분의 열화와 같은 참여로 테스트 게시판에는 수많은 삽들이 꽂혔고 그 중에 한 개의 삽이 정곡을 찌르게 되었다. 다음을 보자..

다음의 코드는 member_write_ok.php 라는 파일에 있다. 하필 member_write_ok.php 냐고 말할지도 모르겠는데 일부러 정한 것이 아니라 제로보드 오른쪽 위에보면 sign in 이라고 있당. 고것을 살짝 누르면 가입하라는 창이 나오는데 소스보기를 하면 action에 member_write_ok.php 라고 되어 있을 것이고 HTML의 input에서 사용된 값들이 넘어가게 되는 파일이다. 즉, 사용자가 가입할때 넘기는 입력내용들을 서버에서 처리하는 파일이다.

[ member_write_ok.php 파일 중에서 버그가 있는 부분 : 사진 업로드 부분 ]
[ 이 부분은 사진 업로드를 처리하는 코드이다. ]

if($picture_name)
{
if(!eregi(".gif",$picture_name)&&!eregi(".jpg",$picture_name)) Error("사진은 gif 또는 jpg 파일을 올려주세요");
$size=GetImageSize($picture);
//if($size[0]>200||$size[1]>200) Error("사진의 크기는 200*200이하여야 합니다");
$kind=array("","gif","jpg");
$n=$size[2];
$path="icon/member_".time().".".$kind[$n];
@copy($picture,$path);
$picture_name=$path;
}

[이 코드에서 취약점?]
$picture_name 이라는 변수와 $picture 라는 변수가 보이고 있다. 이 두 변수가 어디에서 정의되었는지 또, 이미 어떤 값들이 들어 있는지 알아보았더니 전혀 정의되거나 다른 값들이 들어가 있지 않았다.
lib.php 파일에도 없었다. 그렇다면 $picture 나 $picture_name 변수는 어디서 값을 받아 오는 것일까!?
앞에 멤버 가입창에서 소스보기를 한 것이 기억날 것이다. 그 곳에서 자세히 찾아보면 name=picture 라고 되어 있는 부분 이 보인다. 바로 이것이다. PHP에서는 쿼리로 넘어오는 것들을 그냥 앞에 $을 붙여서 내부 변수로 사용한다. 즉, 건네받은 picture는 PHP에서 $picture 이런식으로 다룬다는 것이다.
그렇다면 하나는 해결되었는데 $picture_name 은 몰까..? 아무리 찾아봐도 답이 나오지 않았다.
생각끝에 $picture_name 역시 외부에서 넘어 오는 값이라 생각하기에 이르렀다.
만약 그렇게만 된다면 우리가 직접 picture와 picture_name 을 쿼리로서 넘겨줄 수 있을 것이고 그렇게 되다면 위의 소스 에서 들어난 취약점을 이용해서 내부파일을 복사할 수 가 있을 것 같았다.
위 소스에서 자세히 보자..
처음 부분은
if(!eregi(".gif",$picture_name)&&!eregi(".jpg",$picture_name)) Error("사진은 gif 또는 jpg 파일을 올려주세요");
이다. 본인은 PHP를 잘 모른다. 오로지 C언어만 알고 나머지 언어들은 주섬주섬 줏어들은 통밥으로 가늠해 보건데 확장자 필터링 부분이다. 아마, 누가 보더라도 확장자 필터링 코드라는 것을 한눈에 알 수 있을 것이다.
여기서 눈여겨 봐야 할 것은 $picture_name 이다. eregi 함수는 .gif 와 .jpg 확장자를 $picture_name 변수에 들어있는 문자열에서 검색하고 있는 것이다. 해석하자면 $picture_name에서 .gif 문자열도 없고 .jpg 문자열도 없으면 에러라 는 것이다. 즉, $picture_name은 어떤식으로든지 .gif나 .jpg 라는 문자열을 포함해야 한다는 것이다.
그래야 if 문 조건을 만족시켜서 if 문 내부로 들어갈 수 있기 때문이다.
스르륵 훑어 내려가다 "보면 아항! 바로 이거야"라는 탄성이 나올 것이다. 바로 copy 함수에서 $picture를 $path로 복사하는 내용이다. $picture_name이 아닌 $picture 이다. 아주 웃기다고 생각할지도 모르겠는데 확장자 필터링은 $picture_name 으로 하고 정작 파일 복사는 $picture 을 원본으로 하니 결국 $picture_name 으로 확장자 필터링을 무사히 건너뛴후에 $picture에 원하는 파일이름을 넣어서 복사 시키믄 읽지 못하는 PHP 파일이라 할지라도 웹상에서 복사된 경로와 파일명을 입력한 후에 내용을 읽을 수가 있는 것이다.
결국, $picture_name 과 $picture를 조작해 주어야 한다는 것인데 그것이 가능한지는 다음의 몇가지 테스트를 해보면 알 수 있다.

위의 코드에서 if($picture_name) { 다음 부분에 echo("picture_name = $picture_name"); echo("picture = $picture");
exit; 를 삽입해 보자. 이렇게 자신의 테스트 서버에서 소스 수정을 가한후에 제로보드 우측 상단에 sign in 을 누르고 정식으로 가입을 해보자.
( 주의: 테스트전에 제로보드 설정에서 가입할때 그림 파일을 첨부할 수 있도록 해놓자. 테스트를 위해서.. 나중에는 이런 설정이 없이도 통하는 것을 볼 수 있다. )
테스트를 해보면 $picture_name과 $picture 에 어떤 값들이 들어가 있는지 볼 수 있을 것이다. 그림파일이 제대로 업로드가 되었다면 아마도 picture_name = icon1.gif 처럼 그리고 picture = c:apm_setupserverapachephpE265.TMP
처럼 나올 것이다. 물론, 자신의 환경에 따라 파일이름이나 경로가 틀릴 수 있지만 형식은 변함이 없다. 리눅스에서 테스트 해봐도 $picture가 /tmp/phpE265.TMP 처럼 임시 파일 이름을 갖고 있는 변수라는 것은 변함이 없었다.
$picture_name 은 올린 파일의 이름이며 $picture 는 임시 파일 이름이라는 것이다.
이제 남은 테스트 하나는 $picture_name과 $picture 두개의 변수를 사용자 맘대로 조작이 가능하느냐 아니냐 이다.
방금 전처럼 그림파일을 선택해서 한다면 분명 원하는 파일이름을 집어 넣을 수 없다. 또한 위의 소스 코드에서 if($picture_name) 을 보면 알 수 있듯이 $picture_name 이 참 이어야지만(값이 존재해야지만..) 원하는 일을 할 수 있을 것이다. $picture_name 이 참이라는 뜻은 결국, $picture_name에 0이 아닌 어떤 값이 존재해야 한다는 것을 의미하고 그 조건을 충족시켜 주어야 한다. 여기서 잠시 $picture_name과 $picture에 들어갈 값을 생각해 보자. 돌을 잘 굴리다 보면 제로보드는 $picture_name 을 가지고 필터링을 하며 이 것을 처리하는 구문으로 들어가려면 $picture_name 이 참(TRUE)이어야 한다. $picture_name에 0이 아닌 어떤 값이 있다면 참이라고 했으므로 어떤 문자열을 주면 된다. 대신 다음 구문이 필터링 부분이기 때문에 최소한 .jpg 혹은 .gif 라는 문자열을 갖고 있어야만 할 것이다.
즉, 다음 구문에서 $picture_name 은 .jpg 라는 문자열만 갖고 있어도 모두 에러 없이 통과한다는 것이다.

if($picture_name) // $picture_name 이 0이 아닌 어떤 값을 갖고 있다면 if 구문 내부로 들어감.
{
if(!eregi(".gif",$picture_name)&&!eregi(".jpg",$picture_name)) Error("사진은 gif 또는 jpg 파일을 올려주세요");
// $picture_name 에 .gif 나 .jpg 문자열이 존재한다면 OK! 에러 없이 다음 구문으로 넘어감.

여기까지 통과 하면 다음은

$size=GetImageSize($picture);

인데 재밌게도 $picture 를 갖고 사이즈를 구함을 알수 있다. 이 구문에서 에러가 나지 않을려면 $picture에는 존재하고 있는 파일이름이 들어가야 하며 그 파일은 어떤 사이즈(용량)가 있어야 한다. ( 존재하지 않는 파일이라면 용량이 없을 거고 GetImageSize는 존재 하지 않는 파일의 용량을 구하려 할 것이므로 에러를 낸다. )
다음 세줄은 $kind[$n]를 이용해서 확장자를 선택하는 것인데 결국 알아야 할 값은 $n이 뭐냐이다.
그래야지 $kind[$n] 에서 $n 이 2라면 $kind[2] 가 되서 $kind[2]에 해당하는 jpg가 확장자가 될 것이기 때문이다.
$kind=array("","gif","jpg");
$n=$size[2];
$path="icon/member_".time().".".$kind[$n];
대략 이런식으로 해서 $path 는 "icon/member_어쩌구저쩌구숫자.확장자" 형식을 갖게 된다.
$path는 다음 구문을 보면 알 수 있듯이 복사되는 원본이 아닌 복사 되는 타겟 파일이다.
가장 유심히 봐야할 것은 다음 구문인데 @copy($picture,$path);
결국 우리가 원하는 작업을 하는 copy 구문이다. 이 앞에 있었던 여러 구문들은 솔직히 이 copy 구문을 만나기위해서 요리조리 우회한 과정에 불과한 것이다.
이 copy 구문은 $picture를 $path로 복사하는 것이다.
즉, $picture에 ./config.php 가 들어 있다면 ./config.php 가 $path 에 지정된 파일이름(경로까지 포함)으로 복사되는 것이다. (또한 ./config.php 파일은 이미 존재하는 파일이며 용량이 있기 때문에 위에서 이미지 사이즈 구하는 함수 부분에서 에러가 나지 않는다. )
이렇게 해서 $picture_name 으로 필터링을 우회하고 $picture로 실속을 챙겨야 한다.
$picture_name은 config.jpg.php 라고 그냥 .jpg 문자열을 포함한 이름으로 정한다.
$picture 는 ./config.php 로 해서 copy함수가 실행되면 ./config.php 파일을 타겟으로 복사할 것이다.
( 참고: 여기서 ./config.php 가 복사되는 타겟이 될 $path는 나중에 설명함. )
자 이제 구상이 다 끝났으니 조작한 $picture_name 과 $picture를 member_write_ok.php에 넘겨야 할 차례다.
sign in 을 눌러서 멤버 가입 창을 열자.. 그 다음에 소스 보기 창을 연 후에 다음의 두줄을 추가해주자.


또한 action을 타겟 서버의 제로보드 게시판 member_write_ok.php 가 위치한 url로 바꿔라..
혹시 모르니까 에서도 value를 해당 타겟 게시판의 id로 값을 정해주자..

역시 마찬가지로 referer 도 타겟 게시판으로 바꿔줘 보자.. (혹시 모르므로.. )
마지막으로 소스에서 그림파일 업로드 부분이 있으면 지워주자..
왜냐면 진짜로 그림 파일 업로드 없이 짝퉁으로 속여서


이 두 줄을 넣어 준 것이니깐 그림파일 업로드 부분이 HTML에 들어있으면 겹치기 때문이다.
이런식으로 타겟 서버의 환경에 맞춰줘야 할 것이다.
어떤 곳에서는 직업을 입력하라는 부분이 더 있을 수도 있고 혹은 주민등록 번호를 입력하
라는 부분이 추가 되어 있을 수 있다. 이런 경우에도 방금과 마찬가지로 조작해서 추가해 주자.
다음에 나오는 소스는 위와같은 과정을 거쳐서 제작한 HTML 소스 이다.

==================================== HTML 소스 (브라우져로 불러보자..)===================================





























































































































* 회원가입시 입력된 정보는 불건전한 목적으로 사용되지 않습니다



ID
Password 확인 :
Name
E-mail
공개
Homepage
공개
ICQ
공개
Mailling List 메일링 가입
Photo 공개
자기 소개서
공개
개인정보 공개 정보 공개





















Copyright 1999-2001 Zeroboard
/ skin by Styx





============================================= HTML 소스 끝 ==============================================

이 HTML 파일을 브라우져로 불러들여서 가입을 했을때 정상적으로 처리가 되었다는 메세지가 나올경우에
제빨리 login 을 해서 myinfo 를 눌러보자. 그 다음에 소스 보기를 눌러라..
이런 일련의 동작은 최대한 빨리 이루어 지는게 좋다.
왜냐?
위에서 기억하는가? copy 구문에서 $picture는 $path로서 복사되는데 $path는 time 함수를 쓰는 랜덤파일
네임이다. 소스를 다시한번 보길 바란다. $path는 member_ 에 996745142 처럼 time() 함수를 사용해서 나온
값을 붙인후에 끝에 .확장자를 붙이게 된다. 다행히도 $picture가 ./config.php 처럼 jpg 확장자를 갖고 있지
않아서 인지 .jpg 라고 붙지 않는다. 그냥 .에서 끝이난다.
즉, member_996745138. 이런 식의 파일로 icon 이라는 디렉토리 속에 생기게 된다.
이런 일련의 과정을 취하고 난후에 http://www.AmesianX.com/zboard/icon/member_996745138. 이라는 파일이 생기게
되고 이 파일은 ./config.php 가 복사된 것이다.
그래서 브라우져로 http://www.AmesianX.com/zboard/icon/member_996745138.
를 읽어 들임으로서 ./config.php 파일 내용을 볼 수 있다는 것이다.

< * 시간으로 생성된 랜덤 파일을 어떻게 예측하나!? >
간단하다. 위에서 말했듯이 가입이 정상적으로 처리가 되었다는 메세지가 뜨자마자 login을 한다.
(그럴려면 미리 창을 두개 띄워두는게 빠를 것이당..)
로그인이 되면 sign in 이 있던 자리에는 myinfo 라는 버튼이 생기게 된다.
그걸 누르면 자신의 가입당시 입력한 내용이 있는 개인 정보 페이지가 뜰 것이고 뜨자마자 소스
보기를 누른다.
그러면 다음과 같은 내용이 맨 밑에 있을 것이다.

996745142.3994 은 time 함수로 나온 값이다. 즉, 로딩이 완료 되고서 소스 보기로 보면 이미 time 함수가 서버에서
실행된 후에 나온값이 기록되어 있는 것이다. 996745142 라는 값이 찍혀 있음을 확인했다면 여기서 1씩 빼면서
http://www.AmesianX.com/zboard/icon/member_996745141.
http://www.AmesianX.com/zboard/icon/member_996745140.
http://www.AmesianX.com/zboard/icon/member_996745139.
이런식으로 1씩 빼면서 파일을 유추해 나가야 한다.
위에 설명한 내용을 시간지연 없이 일련의 과정으로서 스르륵 해냈다면
소스 보기로 구한 996745142 라는 숫자에서 4를 빼면 원하는 파일이다.
즉, member_996745138. 이라는 파일이 생성되어 있을 것이다.
아주 빨리 하니깐 3을 빼면 되었고 아주 느리게 하니깐 파일이름을 유추하기가
불가능 했다. 페이지를 로딩하는데 시간지연이 없고 본인이 일련의 가입과정후에 로그인하고 myinfo를 누른 다음
소스보기 까지 속도가 크게 느리지 않는다면 거의 평균 4를 빼면 되었다. 그러니깐 약 4초가 소요되었다는 소리인
것 같다. 그래서 위에 말한대로 한다면 생성된 파일을 유추하기는 쉬울것이다.
만약, 10까지 빼보면서 해봤는데도 파일이 없다고 나온다면 본인이 아주 느리게 로그인을 한 것이거나
파일이 생성되지 않은 것일 확률이 크다. 아니면 icon 디렉토리 지정을 하는 것을 빼먹었거나. ㅋㅋㅋ ^^;
( zboard/icon/member_996745138. <-- icon 디렉토리속에 생성된당.. )
( 굳이 이런 과정없이 가입후 소스 보기를 바로 그 창에서 해서 타임을 얻어낼 수 있긴 하지만 본인이 테스트 하
면서 이렇게 하니깐 4만 빼면 바로 뜨길래 이렇게 한 것임. 어떤 일정한 공식처럼.. 잘 통하길래.. ^^)

[ 초 간단 버젼 ]
위에 있는 HTML을 사용해서 가입한다. 로그인한다. myinfo 누른다. 소스 보기한다. 맨 밑에 있는 숫자를 복사하고서
member_숫자-4. 이렇게 조합한후에 http://www.AmesianX.com/zboard/icon/member_숫자-4. 이렇게 하면 됨.
1~10 까지 빼면서 해도 안되면 파일 생성이 안됐거나 가입후에 로그인하고 myinfo를 누르는 작업에서 너무 많이 시간
을 지체한 것이다. 창을 여러개 띄우고 최단시간으로 해내면 3정도만 빼도 된다. 빼는 이유는 서버와 클아이언트의
로딩과 time함수의 실행시간 등등 여러가지 요인에의해서 나오는 시간차인데 소스 보기를 느리게 하믄 느리게 할 수록
시간차가 많이 벌어지므로 파일 유추에 실패할 확률이 높다. 본인은 거의 실패율 0% 였다.
거진 4를 빼면 다 통했음. 간혹 3 인 경우는 나의 마우스 돌리미와 키보드 두드리미 능력이 넘 빨라서리.. ^^;
서버 환경에 영향을 받을 수 있지만 그래도 10초안에 해결됨으로 1~10 까지만 빼가면서 하면 됨.

[참고]
위에서 숫자는 말했다시피 time() 함수의 실행에의해 나온 날짜를 유닉스에서 말하는 tick(?) 으로 변환한 수기때문에
시시각각 숫자는 증가할 것이다. 또, 멤버 가입 창은 사이트 마다의 설정에 따라서 다르게 나올 수 있다. 예를 들어 주민
등록 번호 입력을 요구하는 부분이 더 추가 되어있을 수도 있고 직업을 묻는 부분이 더 추가 되어 있을 수 도 있는 것이다.
소스 보기를 이용해서 주민등록 번호라든지 직업이라든지 그 부분에 해당하는 name을 보고 자신이 돌릴 HTML에 처음에
설명했던 방법처럼 추가해 주면 된다. 직업은 name=job 이라고 되있을 거고, 주민등록 번호는 name=jumin1과
name=jumin2 로 되있을 것이다.

이런식으로 자신의 HTML 소스 속에 추가해야 한다는 것임.
이미 이 리포트를 읽는 사람이라면 지금까지 설명들이 너무 자질구레하게 길게 늘어 놓은 것이라는 것을 눈치 챘을 것이다.
물론, ./config.php 파일뿐만이 아니라 nobody로 읽을 수 있는 내부 파일은 모두 볼 수 있다는 것도 말이다.

3. 패치 및 대책
업로드 버그는 패치가 아파치 쪽에서 이루어져야 할 것으로 보인다. 또한, 대부분의 국내 게
시판에서는 이 같은 신(NEW) 업로드 버그에 대비해서 만들어져 있는 보드는 없는 것 같다.
세개의 게시판이 모두 통한 상태이고 근본적으로 어떻게 이런일이 일어나는지 테스트 해 볼려
면 매우 짜증나는 일이라서 건강을 위해 다른 사람에게 몫을 넘기려 한다.
제로보드의 버그는 if( $picture_name ) 부분에 환경설정 변수 부분을 첨가해야 할 것이다.
본인이 스트레스로 인해 원형탈모증으로 고생하고 있으므로(뒷통수에 땜빵이.. ㅋ~ㅇ)
더 물으면 분명 독자의 코에서 캐찹이 흐르지 않을까 예상된다.
하지만 명색이 버그 리폿이니만큼 땜빵 몇개 더 생기는 것을 감수하고 좀더 설명하자면..
대략 훑어 보니깐 배열로 멤버 가입창에대한 설정을 읽어들이는 것 처럼 보이는데
찾아 봤더니 $group[use_picture] 이다. 그래서 패치할 부분은 다음과 같다....
zeroboard 의 PHP 파일들 중에서 전부 if( $picture_name ) 이라고 된 부분을 검색한 후에
if( $picture_name && $group[use_picture] )
이렇게 수정해 놓고 가입시 사진 파일을 업로드 못하도록 막아 놓는게 일단 좋을 것 같다.
만약 사진 파일을 업하게 설정해놓고 위에처럼 패치만 한 상태라면 자신의 코속에 두 손가락을
넣고 한번 지긋이 눌러 주길 바란다. 그래야 캐찹이 흐를테니..
이유인 즉, 그림파일을 업로드 하도록 설정하믄 패치 하나마나 같은 방법으로 복사버그가 통하기
땜시 만약 사진 파일을 업로드를 해야겠다고 박박 우겨대는 사람이 있다면 코에서 흐르는 캐찹을
발라먹을 준비를 하는게 좋을 것이다. ( 라이트 펀치가 코에 작렬할지도 모르기 땜시당.. ^^ )
그래도 명색이 버그 리폿이니 임시 방편 정도야 제공을 못하겠십니껴~?
박박 우겨대는 사람은 보시옹.. 다음 처럼 코드를 좀 수정해야 할 것입니다.
$picture에 임시 파일이름이 윈도에서는 확장자가 .TMP가 붙었는데 리눅스에서도 마찬가지였
는지 가물가물한데 마찬가지 였으면 .TMP 를 eregi 로 검색해서 없으면 에러를 내믄 될 것 같다.
이것도 근본적인 해결책이 아닌것 같은데 이유는 위의 설명을 다 이해한 사람이라면 소기 목적
은 달성하지 못하더라도 일부러 에러를 내도록 조작이 가능하다는 것을 알 수 있을테니깐 말이다.
아구아궁.. 머리 아프네.. 땜빵이 생기는 소리가 들려오고 있기땜시 임시 방편으로 .TMP 를
eregi 로 검색하는 구문을 추가해서 악성 코드가 통과하지 못하도록 제약을 걸어버립시다.
근본적인 해결책은 원작자님이신 zero님에게 맡기기로 한당.
다음은 임시방편으로 패치된 상태다.
===================================== 임시 패치 =====================================================
if($picture_name && $group[use_picture]) // 그림 업로드 설정 안해놓으면 버그 원천 봉쇄 할 수 있겠지용?
{
if(!eregi(".gif",$picture_name)&&!eregi(".jpg",$picture_name)) Error("사진은 gif 또는 jpg 파일을 올려주세요");
if(!eregi(".TMP",$picture)) Error("너 수쓰냐? 죽고잡구나!?"); // .TMP 필터링을 하나 추가해서 공격을 좀 어렵게 만듬.
$size=GetImageSize($picture);
//if($size[0]>200||$size[1]>200) Error("사진의 크기는 200*200이하여야 합니다");
$kind=array("","gif","jpg");
$n=$size[2];
$path="icon/member_".time().".".$kind[$n];
@copy($picture,$path);
$picture_name=$path;
}
===================================================================================================
이렇게 하면 위에서 처럼 아무 파일이나 복사해서 읽는 버그를 막을 수 있다.
패치해야 할 부분을 찾으려고 파일들을 검색해 보니깐
member_join_ok.php , member_modify_ok.php , admin_exec_member.php
세개의 파일이 걸려 나왔다.
모두 위처럼 패치해 주자.
원작자님이신 zero님이 패치해 주실때까장...
구해주세요~ Zero 맨~!
빰~ 빰~! 빠빰~! 빰~ 빰~! 빠빰~!
Ze~ ro맨~!!! (음향 효과: 콜라 따르는 소리~ )
=================================================================================================

4. 후기
비록 관리자 권한을 직접적으로 획득하는데는 실패했지만 config.php 파일을 간접적으로 봄으로써 상대방의 데이타 베
이스에 접근할 수 있었다. 대부분 보안에 신경안쓰는 사람들은 MySql 아이디와 암호가 자신의 계정 아이디와 암호하고
일치 되도록 설정하곤 한다.( 머리나쁜 사람이 안 까먹기위한 훌륭한 방법이긴 하다.. ^^ )
또한, 이 제로보드가 만약 어떤 웹 호스팅 서버에 깔려있고 같은 서버에서 홈을 할당 받은 사람이라면 상대방의 계정 디
렉토리에서 config.php 파일은 볼 수 없지만 웹을 이용해서 위와 같은 버그로 config.php 파일을 본다면 MySql 데이터 베
이스에 접근가능하게 된다. 이렇게 될 경우 관리자 권한까지 뺏기게 되는 경우가 된다.
MySql 에 상대방 아이디와 암호로 접속한 후에 관리자 패스워드를 대략 아래와 비슷하게
USE zeroboard; ( 제로보드 데이타 베이스라고 치면.. )
UPDATE zetyx_admin_table SET password=password('1234') ( <-- 맞나? )
이런식으로 바꿀 수 도 있기 때문이다.
후기에서까지 너무 머리 아픈 글을 쓰기는 정말 싫다. 본인은 MySql을 제대로 다룰줄도 모르고 PHP 는 더욱더 모른다.
오로지 C언어를 사용했던 경험으로 통밥 굴리기에 바빴다. 역시 한가지 언어라도 제대로 하라는 소리가 맞았나 보다.
이제 잡소리는 집어 치우고 진짜 후기를 쓰고 싶다.
긴 여정이 끝나고 잠시 휴식 타임이 돌아왔는데 왜 이렇게 허전한 것일까..
긴장감이 없는 삶의 연속이 나의 원형탈모증을 더욱 아프게 한다. ㅋㅋㅋ
이 무더운 여름 밤 잠은 안오고 나는 방 한 구석 모퉁이에 앉아 쓸쓸히 담배를 한대 피운다.
친구넘들은 군대에서 휴가 받고 나와서 여인네랑 피서를 가는데 나는 지금까지 무엇을 얻었나..?
컴퓨터에 대한 지식? 시간이 가면 이것도 다 구식이 되고 쓰레기가 될 것이다.
그럼 나는 무엇을 얻기위해 이 긴 터널을 향해 달려가고 있을까?
돈? 큰집? 빠른차? 여자? 명성? 사회적 지위?
그런 것들에 과연 우리의 행복이 있을까?
어쩌다 보니 노래 가사구나.. ㅋㅋㅋ <0>,,<0> ! 피카~! 멍멍.. ^^
아무리 컴퓨터가 좋아도 이건 아닌데...
정말 아닌데...
나도 피서 가고 싶다...
정말 가고 싶다...
대따 가고 싶다...
누가 머리채라도 잡고 끌고 가줬으면...
버그 리포트를 쓰다보니 어쩌다 시간은 이미 새벽 2시...
이 담배 불이 꺼지면 이젠 눈을 붙이려 한다...
이 밤이 빨리 지나가길 빈다...
내일의 태양이 내게 빛을 비추도록...
아니.. 오늘의 태양이 내게 빛을 비추도록...

6. Thanks to ( 감사의 글 )
테스트 서버를 제공해 주시고 삽을 날리느라 힘드셨던 벌레9님과 두번씩이나 각기 다른 보드를 설치하느라 고달프셨던
( 그 느린 섭에서 어케 설치 했을깡? ㅋㅋㅋ) Anesra 님, 테스트 기간 동안 제로보드에 수많은 공격을 가해 주셨던
rootack, segovia65, ouyuen, se7en, 루나소울님 그리고 TFT4에 참여하고 싶으셨으나 마음먹은대로 잘 이루어지시지
않으셨던 분들까지 모두 감사드립니다.
::TFT4 in Null@Root::
Fighting Null@Root !
======================================== AmesianX in Null@Root ========================================
반응형

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

국내 게시판의 보안 문제 및 해결 방안  (0) 2007.03.18
제로보드 download sql injection 취약점 테스트 방법  (0) 2007.03.17
Padocon 루나틱 발표자료  (0) 2007.03.11
Log Injection  (0) 2007.03.09
Cookie SQL Injection  (0) 2007.03.09