제로보드4의 보안 취약점에 대한 정보와 패치 자료들을 공유하는 곳입니다.
제로보드4로 사이트를 운영하시는 분들의 많은 관심과 정보 공유 부탁드립니다.
보안 관련 내용이 아닌 경우 삭제될 수 있습니다.
최근에 제가 관리하는 사이트는,
인젝션공격에서 벋어났습니다만,
이것저것 제로보드를 완전히 뜯어 고친것이라,
제로보드팁이라고 하기엔 무리가 있어서 소개하기는 좀 그렇습니다.
파일들의 이름을 모두 바꾸고,
DB필드명까지 바꾸는 것이 팁이 될 수 있을까요?
일단은 이전에 만들어 놓은 소스가 있어서 공개해 드리고요.
공격받은 사이트를 원복하는데 조금이라도 시간을 줄이기 위해서 만들어 놓은 소스를 올립니다.
2개의 파일을 만들어서,
제보보드폴더내로 올려둡니다.
하나는 공격을 받았는지 확인하는 확인용 파일 하나와,
여기에서 공격을 받았으면 DB에서 삭제하는 삭제용 파일 하나가 되겠네요.
stream.php
------------------------------------------------------------------------------------
<?
require "../zboard/lib.php"; // ◀--- 사이트의 상황에 맞게 수정해주세요~
if(!$connect) $connect = dbconn();
$View_Level="1"; // 실행권한조정(현재1등급)
if(!$member) $member=member_info();
if(!$member[no]) Error("권한이 없습니다(1)! ","window.close");
if($member[level]>$View_Level) Error("권한이 없습니다(2)! ","window.close");
$que2 = "select name from zetyx_admin_table";
$result2=mysql_query($que2) or Error(mysql_error());
while($temp2 = mysql_fetch_array($result2)){
$board_name=$temp2[name];
$check=0;
echo("$board_name - 악성스크립트 인젝션공격 확인시작!<br/>\n");
$que = "select no, memo from zetyx_board_$board_name order by no desc";
$result=mysql_query($que) or Error(mysql_error());
while($data = mysql_fetch_array($result)){
$mem_no = $data[no];
$check_memo=$data[memo];
///////////////////////////////////////////////////////////////////////////////////////////////////////////
$sp_change_word = "SCRIPT Language=JavaScript src="./;
$sp_change_word_pattern ="/".str_replace("\0","\\0",preg_quote($sp_change_word,"/"))."/i";
$check_memo = preg_replace($sp_change_word_pattern, "", $check_memo);
///////////////////////////////////////////////////////////////////////////////////////////////////////////
if($check_memo<>$data[memo]) {
$check=1;
echo("$mem_no | ");
}
}
if($check==0) {
echo("$board_name - 악성스크립트 인젝션공격이 없었습니다!<br/><br/>\n");
} else {
echo("<br/>$board_name - 해당번호의 게시물에 포함되어 스크립트가 있습니다!<br/><br/>\n");
}
}
echo("악성스크립트 확인시에는 따로 프로그램을 돌려주세요!~ <a href="./stream_run.php" target=_blank>[삭제링크]</a><br/><br/>\n");
if($connect) mysql_close($connect);
?>
------------------------------------------------------------------------------------
stream_run.php
------------------------------------------------------------------------------------
<?
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 아래에 삭제할 스크립트를 적어주세요!
$sp_change_word = "<SCRIPT Language=JavaScript src="http://hanphil.or.kr/bbs/data/young/brod.js></script>";
///////////////////////////////////////////////////////////////////////////////////////////////////////////
require "../zboard/lib.php"; // ◀--- 사이트의 상황에 맞게 수정해주세요~
if(!$connect) $connect = dbconn();
$View_Level="1"; // 실행권한조정(현재1등급)
if(!$member) $member=member_info();
if(!$member[no]) Error("권한이 없습니다(1)! ","window.close");
if($member[level]>$View_Level) Error("권한이 없습니다(2)! ","window.close");
$sp_change_word2 = "<";
$sp_change_word_pattern2 = "/".str_replace("\0","\\0",preg_quote($sp_change_word2,"/"))."/i";
$sp_change_word3 = preg_replace($sp_change_word_pattern2, "<", $sp_change_word);
echo("'$sp_change_word3'<br/>스크립트를 삭제합니다.<br/><br/>\n");
$que2 = "select name from zetyx_admin_table";
$result2=mysql_query($que2) or Error(mysql_error());
while($temp2 = mysql_fetch_array($result2)){
$board_name=$temp2[name];
$check=0;
echo("$board_name - 악성스크립트 삭제시작!<br/>\n");
$que = "select no, memo from zetyx_board_$board_name order by no desc";
$result=mysql_query($que) or Error(mysql_error());
while($data = mysql_fetch_array($result)){
$mem_no = $data[no];
$check_memo=$data[memo];
///////////////////////////////////////////////////////////////////////////////////////////////////////////
$sp_change_word_pattern = "/".str_replace("\0","\\0",preg_quote($sp_change_word,"/"))."/i";
$check_memo = preg_replace($sp_change_word_pattern, "", $check_memo);
///////////////////////////////////////////////////////////////////////////////////////////////////////////
if($check_memo<>$data[memo]) {
$check=1;
echo("$mem_no | ");
$check_memo=addslashes($check_memo);
mysql_query("update zetyx_board_$board_name set memo='$check_memo' where no='$mem_no'") or error(mysql_error());
}
}
if($check==0) {
echo("$board_name - 악성스크립트 인젝션공격이 없었습니다!<br/><br/>\n");
} else {
echo("<br/>$board_name - 해당번호의 게시물에 포함되어있는 스크립트가 모두 삭제되었습니다!<br/><br/>\n");
}
}
if($connect) mysql_close($connect);
?>
------------------------------------------------------------------------------------
stream.php를 홈페이지 어디에 링크를 하나 만들어서, 수시로 확인하시고,
여기에서 걸려든다면, 게시물에서 삽입된 스크립트를 확인하시고,
stream_run.php의 상단부분에 해당 스크립트를 기록하고 한번 돌려주면 됩니다.
이때 주의 하실 사항은 최근에는 악성스크립트 앞뒤로 공백이 많이 들어가더군요.
따라서, 공백도 같이 생각하셔서 적어주셔야, 게시물의 앞부분에 공백이 생기지 않겠지요.
인젝션공격 자체가 특정게시판에만 이루어지기 때문에,
해당게시판에서만 돌리다가, 귀찮아서 전체게시판을 한번에 처리하도록 대~충 코딩했습니다.
허접코딩이지만, 몇일만에 한번씩 확인하는 용도라.. ^^;
ps. 확인사항
에디터에서 게시물이 등록될 때,
따옴표 " 가 마음대로 붙어서, 위의 소스대로 사용하시면 안됩니다.
확인하셔서 수정후에 사용하세요~

제로보드4의 경우에는 파일 명까지 완전하게 개조하는게 기능적으로나 보안적으로나 좋은것 같습니다.
디시인사이드가 그렇게 하고있지요...
그리고 한국인터넷진흥원에서 캐슬이라는 웹보안 솔루션을 제공하는데 그걸 적용해보시면 어떨까요?
Krcert/CC 홈페이지 가시면 있답니다~