본템플릿은최근해킹에주로이용되고있는주요웹보안취약점을개발단계에서부터보완하기위한목적으로한국정보보호진흥원인터넷침해사고대응지원센터해킹대응팀연구원들과국내웹보안및웹어플리케이션전문가들의참여와자문을통해제작되었습니다. 웹개발자들이보안을고려한웹프로그램제작에활용하시기바랍니다 년

Similar documents
PHP & ASP

하둡을이용한파일분산시스템 보안관리체제구현

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

JSP 의내장객체 response 객체 - response 객체는 JSP 페이지의실행결과를웹프라우저로돌려줄때사용되는객체이다. - 이객체는주로켄텐츠타입이나문자셋등의데이터의부가정보 ( 헤더정보 ) 나쿠키 ( 다음에설명 ) 등을지정할수있다. - 이객체를사용해서출력의방향을다른

PHP & ASP

PowerPoint Template

Microsoft PowerPoint 세션.ppt

Cookie Spoofing.hwp

Microsoft PowerPoint - GUI _DB연동.ppt [호환 모드]

게시판 스팸 실시간 차단 시스템

EDB 분석보고서 (04.03) ~ Exploit-DB( 에공개된별로분류한정보입니다. ** 5개이상발생한주요소프트웨어별상세 EDB 번호 종류 공격난이도 공격위험도 이름 소프트웨어이름 3037 SQL Inj

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

쉽게 풀어쓴 C 프로그래밍

PowerPoint Template

10.ppt

EDB 분석보고서 (04.06) ~ Exploit-DB( 에공개된별로분류한정보입니다. Directory Traversal users-x.php 4.0 -support-x.php 4.0 time-

Microsoft PowerPoint Python-WebDB

Microsoft PowerPoint 웹 연동 기술.pptx

Data Provisioning Services for mobile clients

<4D F736F F F696E74202D203130C0E52EBFA1B7AF20C3B3B8AE205BC8A3C8AF20B8F0B5E55D>

untitled

제목 레이아웃

The Pocket Guide to TCP/IP Sockets: C Version

** 5 개이발생한주요소프트웨어별취약점세 EDB 번호취약점종류공격난이도공격위험도취약점이름소프트웨어이름

로거 자료실


2009년 상반기 사업계획

var answer = confirm(" 확인이나취소를누르세요."); // 확인창은사용자의의사를묻는데사용합니다. if(answer == true){ document.write(" 확인을눌렀습니다."); else { document.write(" 취소를눌렀습니다.");

Javascript.pages

Observational Determinism for Concurrent Program Security

MySQL-.. 1

C++ Programming

SK Telecom Platform NATE

WEB Hacking 한국디지털미디어고등학교, T eampur e, JT JSOFT 장태 진

3장

제이쿼리 (JQuery) 정의 자바스크립트함수를쉽게사용하기위해만든자바스크립트라이브러리. 웹페이지를즉석에서변경하는기능에특화된자바스크립트라이브러리. 사용법 $( 제이쿼리객체 ) 혹은 $( 엘리먼트 ) 참고 ) $() 이기호를제이쿼리래퍼라고한다. 즉, 제이쿼리를호출하는기호

쉽게 풀어쓴 C 프로그래밊

구축환경 OS : Windows 7 그외 OS 의경우교재 p26-40 참조 Windows 의다른버전은조금다르게나타날수있음 Browser : Google Chrome 다른브라우저를사용해도별차이없으나추후수업의모든과정은크롬사용 한

쉽게 풀어쓴 C 프로그래밍

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

13주-14주proc.PDF

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

최종보고서 데이터베이스의취약점분석과해결책 제출일자 : 2012년 5월 00일과목명 : 캡스톤디자인팀명 : DIS 팀장 : 강연준팀원 : 강연준 조응철담당교수 : 양환석교수님

untitled

SOFTBASE XFRAME DEVELOPMENT GUIDE SERIES HTML 연동가이드 서울특별시구로구구로 3 동한신 IT 타워 1215 호 Phone Fax Co

Javascript

AhnLab_template

목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE

Ext JS À¥¾ÖÇø®ÄÉÀ̼ǰ³¹ß-³¹Àå.PDF

윈도우시스템프로그래밍

Data Provisioning Services for mobile clients

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

금오공대 컴퓨터공학전공 강의자료

혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 <html> 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 <html> 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

Microsoft PowerPoint - 04-UDP Programming.ppt

Microsoft Word - SKINFOSEC-CHR-026- Mass SQL Injection 탐지 우회분석 보고서.doc

DBMS & SQL Server Installation Database Laboratory

XSS Attack - Real-World XSS Attacks, Chaining XSS and Other Attacks, Payloads for XSS Attacks

PowerPoint 프레젠테이션

Tcl의 문법

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

0. 들어가기 전

PowerPoint 프레젠테이션

Microsoft Word - CrossSiteScripting[XSS].docx

Javascript

76 XSS 하 Huge-IT Slider admin.php XSS

10 강. 쉘스크립트 l 쉘스크립트 Ÿ 쉘은명령어들을연속적으로실행하는인터프리터환경을제공 Ÿ 쉘스크립트는제어문과변수선언등이가능하며프로그래밍언어와유사 Ÿ 프로그래밍언어와스크립트언어 -프로그래밍언어를사용하는경우소스코드를컴파일하여실행가능한파일로만들어야함 -일반적으로실행파일은다

쉽게 풀어쓴 C 프로그래밍

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

InsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins

Secure Programming Lecture1 : Introduction

Javascript

Oracle hacking 작성자 : 임동현 작성일 2008 년 10 월 11 일 ~ 2008 년 10 월 19 일 신규작성 작성내용

Microsoft PowerPoint - chap01-C언어개요.pptx

슬라이드 1

Research & Technique Apache Tomcat RCE 취약점 (CVE ) 취약점개요 지난 4월 15일전세계적으로가장많이사용되는웹애플리케이션서버인 Apache Tomcat에서 RCE 취약점이공개되었다. CVE 취약점은 W

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

Microsoft PowerPoint - CSharp-10-예외처리

14-Servlet

PowerPoint 프레젠테이션

Microsoft PowerPoint - Java7.pptx

학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2

1) 인증서만들기 ssl]# cat > // 설명 : 발급받은인증서 / 개인키파일을한파일로저장합니다. ( 저장방법 : cat [ 개인키

문서 템플릿

EDB 분석보고서 (06.07) ~ Exploit-DB( 에공개된취약점별로분류한정보입니다 SQL Injection 하중 index.php SQL Injection 취

슬라이드 1

Discrete Mathematics

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

PowerPoint 프레젠테이션

chap 5: Trees

HLS(HTTP Live Streaming) 이용가이드 1. HLS 소개 Apple iphone, ipad, ipod의운영체제인 ios에서사용하는표준 HTTP 기반스트리밍프로토콜입니다. 2. HLS 지원대상 - 디바이스 : iphone/ipad/ipod - 운영체제 :

adfasdfasfdasfasfadf

컴파일러

슬라이드 1

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Transcription:

웹어플리케이션보안템플릿 2006. 6

본템플릿은최근해킹에주로이용되고있는주요웹보안취약점을개발단계에서부터보완하기위한목적으로한국정보보호진흥원인터넷침해사고대응지원센터해킹대응팀연구원들과국내웹보안및웹어플리케이션전문가들의참여와자문을통해제작되었습니다. 웹개발자들이보안을고려한웹프로그램제작에활용하시기바랍니다. 2006 년 6 월 사업책임자 : 본부장김우한연구책임자 : 팀장성재모참여연구원 : 수석연구원정현철연구원한단송외부전문가 : KCC 시큐리티가성호프로그램감수 : 패닉시큐리티양정규패닉시큐리티윤달형나우콤김호

본템플릿에서는 SQL Injection 취약점, 업로드취약점, 다운로드취약점, Cross Site Script(XSS) 취약점, 접근통제취약점등해킹에가장많이이용되고있는 5가지웹보안취약점에대해안전한웹프로그래밍을위한템플릿을제공하고있다. 각각의취약점에대한간단한설명과해당취약점으로인해발생될수있는해킹사례를소개하고, ASP, PHP, JSP 등 3가지웹개발언어별로해당취약점에대한공격을차단할수있는보안템플릿을제공한다. 각기관에서사용하는웹개발언어의보안템플릿을선택하여웹프로그램개발시또는기존의웹프로그램의수정시적용시키기바란다. 개발언어별보안템플릿은가급적일반적인웹개발환경에서적용가능하도록작성하기위해노력하였다. 하지만, 각기관의웹개발환경및서비스가매우다양하므로, 정상적이서비스에지장이없도록충분한최적화작업및테스트하기를바란다.

Contents 제 1 장 SQL Injection 보안템플릿 1 제 2 장업로드보안템플릿 27 제 3 장다운로드보안템플릿 43 제 4 장 Cross Site Script (XSS) 보안템플릿 53 제 5 장접근통제보안템플릿 69 참고문헌 80

................................................

.................................................................................................... SQL Injection 보안템플릿

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 제 1 장 SQL Injection 보안템플릿 SQL Injection 이란? SQL Injection 은정상적인 SQL 질의문을변조하여불법로그인, DB 데이터열람, 시스템명령실행등을수행하는공격이다. 이공격은사용자입력값또는 URL 파라미터값에대한적절한검증작업이이루어지지않아발생된다. 사례 1. 사용자인증을비정상적으로통과한사례 < 그림 1-1> 사용자인증우회 위의그림에서공격자는신청인의인터넷접수번호를알지못하더라도 A or A = A 라는악의적인값을입력함으로써로그인이가능하다. SELECT 신청인명, 접수번호 FROM user_table WHERE 신청인명 = test AND 접수번호 = A OR A = A 이경우구문의 WHERE 절은 True AND False OR True 로전체구문이 True 가되어사용자인증모듈을우회하여로그인이가능하게된다. 이는웹프로그램이사용자입력값을적절하게검증하지않아발생한것이다. 2 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 2. URL 파라미터입력값의조작을통한공격사례 웹사이트의공지사항이나게시판등은게시글의번호를입력값으로받아해당게시글을 DB 에서찾아화면에보여준다. 하지만공격자는게시글번호입력항목에비정상적인 SQL 구문을입력함으로써, DB 가해당 SQL 문을실행하게하여 DB 조회및임의의명령실행이가능하다. SQL Injection 보안템플릿 최근중국발해킹사고에서이와같은방법을주로사용하고있으며, 아래와같은자동화된공격툴을이용하여다수의웹사이트들을공격하고있다. < 그림 1-2> SQL Injection 공격툴을사용한사례 위그림은공지사항의게시글번호를입력으로받는 id 라는파라미터가입력값을검증하지않아, SQL Injection 공격툴에의해관리자아이디와패스워드가노출되는것을볼수있다. www.krcert.or.kr 3

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 각언어별보안템플릿 1. 사용자인증을비정상적으로통과한경우 기존의로그인인증방식은아이디, 패스워드를입력받아해당값들을 WHERE 절구문에사용하여구문의참 / 거짓으로인증확인을수행한다. 이러한방법을사용할경우 SQL Injection 공격으로인증을우회할수있는취약점이존재한다. 이를보완하기위해서기존의처리방식에서 WHERE 절에아이디로질의를실행한후나온질의결과패스워드를입력된패스워드와비교하여구문의결과와입력결과를재확인하는방식으로작성하는것이바람직하다. 와 4 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <ASP 보안템플릿 > /login.asp <!--#include virtual="/include/connection.inc.asp"--><% 'DB 연결헤더 %> <!--#include virtual="/include/secure.inc.asp"--> <% ' 보안관련라이브러리 %> <!--#include virtual="/include/config.inc.asp"--> <% ' 전역변수리스트 %> <!--#include virtual="/head.asp"--><% ' 초기설정페이지 ( 에러메시지미출력 ) %> <% ' 사용되는 ID 값은유일해야한다. ' ID 에대한 PW 값을가져와서입력된패스워드와비교하는방식으로기존의로그인방식은 ID, PW 를모두확인하는방식으로 WHERE 구문의조작으로루틴을우회할수있으나해당방식은인젝션이성공한다하더라도임의의인젝션된값과입력된값을비교하게되어공격의성공율을낮출수있다. Dim strquery, strsql Dim strid, strpw SQL Injection 보안템플릿 strid = sqlfilter(request("name")) strpw = sqlfilter(request("password")) ' 입력값 NULL 체크 If Len(strID) = 0 OR Len(strPW) = 0 then ' 입력값체크실패 'Response.Write " 입력오류 " Else ' 입력되는 ID 값의존재여부파악 strsql = "SELECT count(*) FROM userinfo WHERE strid = '" & strid & "'" objrs.open strsql, objdbconn ' 유일하게존재하는경우 If objrs(0) = 1 Then objrs.close ' 접근 ID 와일치하는패스워드값을 SELECT 함으로써 SQL 구문으로인증체크를하지않도록한다. ' 오류를이용한 SQL Injection 기법에는기존의 SQL Injection 필터링방법으로통제한다. strsql = "SELECT strpassword,strname FROM userinfo WHERE strid = '" & strid & "'" objrs.open strsql, objdbconn www.krcert.or.kr 5

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 'SELECT 된패스워드와입력패스워드비교 If StrComp(trim(objRs(0)),strPW) = 0 Then ' 로그인성공후프로세스작성 Response.Write objrs(1) & " Login OK" Else ' 입력된패스워드와 SELECT 한패스워드가다를경우로그인실패 Response.Write strid & " Login Failed" End If End If 'ID 가복수개또는없을경우로그인실패 Response.Write strid & " Login Failed" objrs.close End If %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <H3><P> 텍스트상자정보입력하기 </P></H3> <form action="login.asp" name=postform method=post> <table border=0> <td> 아이디 : </td> <td><input type=text name=name size=20 value=""></td> <td> 패스워드 : </td> <td><input type=password name=password size=20 value=""></td> <td colspan= 2 align=center><input type="submit" value= " 로그인 " id=submit1 name=submit1> <input type="reset" value=" 취소하기 " id=reset name=reset></td> </table> </form> </BODY> </HTML> 6 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <PHP 보안템플릿 > /login.html <HTML> <HEAD> SQL Injection 보안템플릿 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <H3><P> 로그인 </P></H3> <form action="login.php" name=postform method=post> <table border=0> <td> 아이디 : </td> <td><input type=text name=user_id size=20 value=""></td> <td> 패스워드 : </td> <td><input type=password name=user_pw size=20 value=""></td> <td colspan= 2 align=center><input type="submit" value= " 로그인 " id=submit1 name=submit1> <input type="reset" value=" 취소하기 " id=reset name=reset></td> </table> </form> </BODY> </HTML> www.krcert.or.kr 7

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 /login.php <? require "include/connect.inc.php"; require "include/config.inc.php"; require "include/secure.inc.php"; require "include/lib.php";?> <? $connect=db_connect(); //DB 연결헤더 // 전역변수리스트 // 보안라이브러리 // 게시판라이브러리 $mb_table = "userinfo"; $user_id = sqlfilter($user_id); $user_pw = sqlfilter($user_pw); if(trim($user_id)=="") print (" 아이디를입력하여주십시요 "); if(trim($user_pw)=="") print (" 비밀번호를입력하여주십시요 "); // 회원로그인체크 $result = mysql_query("select id,user_id,password from $mb_table where user_id='$user_id'"); if ($mb_data = mysql_fetch_array($result)) { if($mb_data[password] == $user_pw) { // 회원로그인이성공하였을경우세션을생성하고페이지를이동함 // 로그인후프로세스 print (" 로그인성공 "); exit; else { // 회원로그인이실패하였을경우에러표시 print (" 로그인실패 "); exit; else { print (" 로그인실패 "); db_close($connect);?> 8 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <JSP 보안템플릿 > / login.html <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <H3><P> 텍스트상자정보입력하기 </P></H3> <form action="login.jsp" name=postform method=post> <table border=0> <td> 아이디 : </td> <td><input type=text name=id size=20 value=""></td> <td> 패스워드 : </td> <td><input type=password name=pw size=20 value=""></td> <td colspan= 2 align=center><input type="submit" value= " 로그인 " id=submit1 name=submit1> <input type="reset" value=" 취소하기 " id=reset name=reset></td> </table> </form> </BODY> </HTML> SQL Injection 보안템플릿 /login.jsp <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ include file="connection.inc.jsp" %> <%@ include file="config.inc.jsp" %> <%@ include file="secure.inc.jsp" %> <% String s_tablename = "user"; // 테이블이름 www.krcert.or.kr 9

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 String s_id, s_pw, s_name; //SQL 구문실행결과값저장 String g_id, g_pw; // 입력값저장 String s_sql; g_id = sqlfilter(request.getparameter("id")); g_pw = sqlfilter(request.getparameter("pw")); try { // 사용자 ID 만으로엔트리를가져옴 s_sql = "SELECT id,pw,name FROM " + s_tablename + " WHERE id='" + g_id + "'"; rs = stmt.executequery(s_sql); // 쿼리문실행결과값을담을객체 if (rs.next()) { s_id = rs.getstring(1); s_pw = rs.getstring(2); s_name = rs.getstring(3); else { 패 : 사용자없음 "); //DB 에서가져온사용자패스워드와입력한패스워드를비교 if (s_pw == g_pw) { // 로그인후처리프로세스 out.println(" 로그인성공 "); else { // 로그인실패시처리프로세스 out.println(" 로그인실패 : 패스워드오류 "); // 로그인실패시처리프로세스 // 에러메시지를출력하지않기위해제거하는편이바람직함 - out.println(" 로그인실 //DB 처리 stmt.close(); // 인클루드파일 (db_conn. jsp) 에서생성한 stmt 닫기 Conn.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 Conn 닫기 catch (Exception e) { out.println(e); %> 10 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 2. URL 파라미터입력값을조작한경우 각언어별보안템플릿은크게위험성이존재하는문자 ( 혹은문자열 ) 에대한필터링, 입력값을사용하는데있어데이터타입의확인방법, 공격코드로유출될수있는문자 ( 혹은문자열 ) 에대한필터링항목으로구성되어있다. <ASP 보안템플릿 > SQL Injection 보안템플릿 /include/secure.inc.asp : SQL Injection 필터링함수 <% ' 공격위험성이존재하는문자들을필터링 ' 문자열입력시에만사용 Function sqlfilter(search) Dim strsearch(5), strreplace(5), cnt, data 'SQL Injection 특수문자필터링 ' 필수필터링문자리스트 strsearch(0)="'" strsearch(1)="""" strsearch(2)="\" strsearch(3)=null strsearch(4)="#" strsearch(5)="--" strsearch(6)=";" ' 변환될필터문자 strreplace(0)="''" strreplace(1)="""""" strreplace(2)="\\" strreplace(3)="\"&null strreplace(4)="\#" strsearch(5)="\--" strsearch(6)="\;" www.krcert.or.kr 11

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 data = search For cnt = 0 to 6 ' 필터링인덱스를배열크기와맞춰준다. data = replace(data, LCASE(strSearch(cnt)), strreplace(cnt)) Next sqlfilter = data End Function %> /head.asp : 오류메시지제거에러메시지를출력하지않기위해각페이지처음부분에사용한다. <% ' 페이지에서에러가발생하여도페이지오류를외부로출력하지않기위해사용 On Error Resume Next 'On Error GoTo 0도가능하나 2003에서는실행되지않음 if err.number <> 0 then 'Response.Write err.description & "<BR>" & err.source & "<BR>" err.clear End if %> /content.asp : 인덱스번호를입력받아게시물을표시하단의웹페이지는게시물번호 (no) 값을받아 SQL 구문에대입하여게시물을출력하는웹페이지의일부이다. 이중 sqlfilter 함수를이용하여페이지시작부분에서문자를필터링하고있으며 SQL 구문수행시발생할수있는오류메시지를출력하지않아최대한정보를노출하지않도록하고있다. <!--#include virtual="/include/connection.inc.asp"--> <% 'DB연결헤더 %> <!--#include virtual="/include/secure.inc.asp"--> <% ' 보안관련라이브러리 %> <!--#include virtual="/include/config.inc.asp"--> <% ' 전역변수리스트 %> <!--#include virtual="/head.asp"--> <% ' 초기설정페이지 ( 에러메시지미출력 ) %> <% Dim strsql Dim intseq, strname, stremail, strsubject, strcontent, intcount, dtmreg_date, intexist Dim blntag, struserip 12 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 Dim atag ' 입력값이숫자형인경우 IsNumeric 함수를사용한다. If IsNumeric(seq) Then intseq = Request.QueryString("seq") Else Response.Write " 허용하지않는입력값입니다." Reponse.End End If SQL Injection 보안템플릿 ' 문자 ( 열 ) 인경우 sqlfilter 사용 'intseq = sqlfilter(request.querystring("seq")) 'SQL Injection 필터링 ' 읽은횟수검색 strsql = "SELECT count(*) FROM board WHERE intseq='" & intseq & "'" objrs.open strsql, objdbconn intexist = objrs(0) objrs.close If intexist <> 1 Then Response.Write " 해당글이없습니다." Else ' 읽은횟수증가 strsql = "UPDATE board SET intcount=intcount+1 WHERE intseq='" & intseq & "'" objrs.open strsql, objdbconn ' 게시물 SELECTZ strsql = "SELECT strname,stremail,strsubject,strcontent,intcount,struserip,blntag,dtmreg_date FROM board WHERE intseq='" & intseq & "'" objrs.open strsql, objdbconn strname = objrs(0) stremail = objrs(1) www.krcert.or.kr 13

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 strsubject = objrs(2) strcontent = objrs(3) intcount = objrs(4) struserip = objrs(5) blntag = objrs(6) dtmreg_date = objrs(7) objrs.close Set objrs = Nothing objdbconn.close Set objdbconn = Nothing ' 게시물출력값에 XSS 필터링 ' 사용자가입력하는출력되는값은 strname, stremail, strsubject, strcontent으로이부분은 XSS 공격이가능한부분들이다. ' 일반적으로본문만선택적으로 HTML 태그사용을허용하며나머지부분들은사용할수없도록하는것이바람직하다. strname = clearxss(strname, atag) stremail = clearxss(stremail, atag) strsubject = clearxss(strsubject, atag) strcontent = clearxss(strcontent, atag) %> <html> ' 줄넘김처리 strcontent = replace(strcontent, vblf, vblf & "<br>") <head> <meta name="generator" content="microsoft FrontPage 5.0"> <meta name="progid" content="frontpage.editor.document"> <meta http-equiv="content-type" content="text/html; charset=ks_c_5601-1987"> <title> 내용보기 </title> </head> <body> 14 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <div align=center> <table border=1> <td> 이름 </td> <td><%=strname%></td> <td> 등록일 </td> <td><%=dtmreg_date%></td> <td> 이메일 </td> <td><%=stremail%></td> <td> 조회 </td> <td><%=intcount%></td> <td> 제목 </td> <td colspan=3><%=strsubject%></td> <td> 내용 </td> <td colspan=3><%=strcontent%></td> <td colspan=4> <a href="list.asp"> 목록으로 </a> <a href="edit.asp?seq=<%=intseq%>"> 수정하기 </a> <a href="delete.asp?seq=<%=intseq%>"> 삭제하기 </a> </td> </table> SQL Injection 보안템플릿 </div> </body> </html> <% End If %> www.krcert.or.kr 15

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <PHP 보안템플릿 > /include/secure.inc.php : SQL Injection 필터링함수 <? //SQL 입력값문자열필터 //$str = 입력문자열 function sqlfilter($str) { //1단계? ',",NULL 문자필터링. 각문자들에백슬래쉬 (\) 삽입됨. 필수항목 // 출력시 stripslashes() 함수를이용하여백슬래쉬 (\) 를제거 if (!get_magic_quotes_gpc()) $str = addslashes($str); //3단계? 특수문자및문자열필터링 //WHERE 구문에서쓰여지는데이터만사용하는것이바람직하다. $search = array("--","#",";"); $replace = array("\--","\#","\;"); $str = str_replace($search, $replace, $str);?> return $str; /view.php : 인덱스번호를입력받아게시물을표시 <? require "include/connect.inc.php"; require "include/config.inc.php"; require "include/secure.inc.php"; require "include/lib.php";?> <? if (is_numeric($no)) { $no = ($_REQUEST[no]); //DB 연결헤더 // 전역변수리스트 // 보안라이브러리 // 게시판라이브러리 // SQL Injection 필터 16 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 else { echo " 허용하지않는입력값 "; exit; SQL Injection 보안템플릿 $board = sqlfilter($_request[board]); // SQL Injection 필터 // 읽기횟수저장 $updok = mysql_query("update $board SET hit = hit + 1 WHERE no=$no", $connect); $query = sprintf("select * FROM %s WHERE no='%d'",$board,$no); $result = mysql_query($query); $view = @mysql_fetch_array($result); //@ 를이용하여에러메세지출력을하지않는다. //XSS 필터링 $view[usrname] = clearxss($view[usrname],$avatag); $view[usremail] = clearxss($view[usremail],$avatag); $view[usrtitle] = clearxss($view[usrtitle],$avatag); $view[contents] = clearxss($view[contents],$avatag); $dates = date ("Y-m-d, h:i:s", $view[filluptime]); $perpage = 10; $tlpn = get_pagenum(); $nowpage = get_page($view[idx]); if ($view[usremail]!= "") { $name = "<a href=\"mailto:$view[usremail]\">$view[usrname]</a>"; else { $name = "$view[usrname]"; if ($view[usrhomepage]!= "") { $homeurl = "<a href=\"$view[usrhomepage]\" target=\"_blank\">[homepage]</a>"; www.krcert.or.kr 17

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 else { $homeurl = ""; echo " <html> <head> <title> 글내용보기 </title> </head> <body> <center> <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td align=\"left\"><font size=\"2\"><b> <a href=\"list.php?board=$board&page=$nowpage\"> 게시물목록 </a> <a href=\"edit.php?board=$board&no=$no\"> 수정 </a> <a href=\"delete.php?board=$board&no=$no\"> 삭제 </a> </b></font></td> </table> <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td colspan=\"2\" bgcolor=\"#a5a595\"><font color=\"white\" size=\"2\">$view[num] 번글 : <b>$view[usrtitle]</b></font></td> <td align=\"left\" bgcolor=\"#e5e5d5\"><font size=\"2\"> 조회수 : $view[hit]</font></td> <td align=\"right\" bgcolor=\"#e5e5d5\"><font size=\"2\">$name 님이 $homeurl $dates 에작성해주셨습니다.</font></td> </table>"; 18 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 if ($view[filesize] > 0) { $view[contents].= "<p align=\"right\">"; $view[contents].= "<a href=\"dn.php?board=$board&no=$view[no]\">"; $view[contents].= $view[filename]; $view[contents].= "</a>"; SQL Injection 보안템플릿 echo " <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td><font size=\"2\">$view[contents]</font> </td> </table> <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td align=\"right\"><font size=\"2\"><b> <a href=\"list.php?board=$board&page=$nowpage\"> 게시물목록 </a> <a href=\"edit.php?board=$board&no=$no\"> 수정 </a> <a href=\"delete.php?board=$board&no=$no\"> 삭제 </a> </b></font></td> </table> </center> </body> </html> ";?> www.krcert.or.kr 19

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <JSP 보안템플릿 > JSP 의경우별도의라이브러리로작성하려면클래스를생성해야하므로코드내에서할수있는방법을기술한다. JSP 의경우에러노출을막기위한특별한방법은찾을수없었으나 PreparedStatement 방식이나클래스함수중형검사를할수있는방법이존재하므로고려하도록한다. /secure.inc.jsp : SQL Injection 필터링함수 gfilter : SQL 구문중 SELECT 구문에서입력값을필터링할때사용 pfilter : SQL 구문중 INSERT/UPDATE 구문에서입력값을필터링할때사용 <%! // 공격위험성이존재하는문자들을필터링 // 입력값 : SQL 입력값 String sqlfilter(string str) { str = str.replaceall("'","''"); str = str.replaceall("\"","\"\""); str = str.replaceall("\\","\\\\"); str = str.replaceall(";",""); str = str.replaceall("#",""); str = str.replaceall("--",""); str = str.replaceall(" ",""); return (str); 사용예 ) /view.jsp : 인덱스번호를입력받아게시물을표시 <!-- www.itmembers.net의 JSP게시판만들기강좌에서손병목님이작성하신 view.jsp파일을 strip Tokonizer 사용을위해인용하였습니다. --> <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ include file="connection.inc.jsp" %> 20 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <%@ include file="config.inc.jsp" %> <%@ include file="secure.inc.jsp" %> <% String s_tablename = "bbs"; // 테이블이름 String s_sql, s_number, s_name="", s_email="", s_homepage="", s_subject="", s_memo="" ; String s_mail_addr=""; String s_page ; int i_number, i_count=0, i_page ; SQL Injection 보안템플릿 StringTokenizer st = null; // <br> 처리를위해서 String s_temp = ""; s_number = request.getparameter("number"); // view.jsp?number=10 과같이넘어온값 "10" 을받음. try { i_number = Integer.parseInt(s_number); //Integer형인경우숫자형으로형변환 //i_number = Long.parseLong(s_number); //Long형인경우 Long catch (Exception e) { stmt.close(); Conn.close(); return; //out.println(e); s_page = request.getparameter("page"); // view.jsp?page=3 과같이넘어온값 "3" 을넘겨받음. try { if(s_page==null) s_page="1"; i_page = Integer.parseInt(s_page); catch (Exception e) { stmt.close(); Conn.close(); return; //out.println(e); //s_number = sqlfilter(s_number); //SQL Injection 필터 //s_page = sqlfilter(s_page); //SQL Injection 필터 www.krcert.or.kr 21

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 try { s_sql = "select name,count,email,homepage,subject,memo from "+s_tablename+" where number='"+s_number+"'"; rs = stmt.executequery(s_sql); // 쿼리문실행결과값을담을객체 if(rs.next()) { //XSS 필터 s_name = clearxss(rs.getstring(1),avatag); i_count = rs.getint(2); s_email = clearxss(rs.getstring(3),avatag); s_homepage = clearxss(rs.getstring(4),avatag); s_subject = clearxss(rs.getstring(5),avatag); s_memo = clearxss(rs.getstring(6),avatag); if(!s_email.equals("")) { s_mail_addr="<a href=mailto:"+s_email+">"+s_email+"</a>"; else { s_mail_addr=s_email; // Enter를 <br> 로처리 st = new StringTokenizer(s_memo,"\n"); while(st.hasmoretokens()) { s_temp = s_temp + st.nexttoken()+"<br>"; s_memo = s_temp; s_sql = "update "+s_tablename+" set count = count + 1 where number = "+s_number; stmt.executeupdate(s_sql); stmt.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 stmt 닫기 22 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 Conn.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 Conn 닫기 catch (Exception e) { //out.println(e); SQL Injection 보안템플릿 %> <html> <head> <title>jsp 게시판프로젝트 - 보기 </title> <STYLE TYPE="text/css"> BODY,TD,SELECT,input,DIV,form,TEXTAREA,center,option,pre,blockquote {font-family: 굴림font- size:9pt;color:#555555; A:link {color:black;text-decoration:none; A:visited {color:black;text-decoration:none; A:active {color:black;text-decoration:none; A:hover {color:gray;text-decoration:none; </STYLE> </head> <body bgcolor=white background=./images/body_bg.gif> <img src=./images/maintitle.gif> <table border=0 cellspacing=1 cellpadding="3" width=670> <td align=center> <font color=green><b> 내용보기화면입니다.</b></font> </td> <td bgcolor="#eac3ea"> <table border=0 cellspacing=1 cellpadding=0 width=670 bgcolor="white"> <td width="100"> <p align="right"><b> 이름 </b></p> www.krcert.or.kr 23

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 </td> <td width="400"> <p><%= s_name %></p> </td> <td width="100"> <p align="right"><b> 조회수 </b></p> </td> <td> <p><%= i_count %></p> </td> <td width="100"> <p align="right"><b> 전자우편 </b></p> </td> <td colspan="3"> <p><%= s_mail_addr %></p> </td> <td width="100"> <p align="right"><b> 홈페이지 </b></p> </td> <td colspan="3"> <p><%= s_homepage %></p> </td> <td width="100"> <p align="right"><b> 제목 </b></p> </td> <td colspan="3"> <p><%= s_subject %></p> </td> 24 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 1 장 <td width="100"> <p align="right"><b> 내용 </b></p> </td> <td colspan="3"> <p><%= s_memo %></p> </td> </table> <p align="center"><a href="list.jsp?page=<%= s_page %>">[ 목록 ]</a> <a href="write.html">[ 쓰기 ]</a> <a href="modify.jsp?number=<%= s_number %>&page=<%= s_page %>">[ 수정 ]</a> <a href="delete.jsp?number=<%= s_number %>&page=<%= s_page %>">[ 삭제 ]</a></p> </td> </table> </body> </html> SQL Injection 보안템플릿 www.krcert.or.kr 25

................................................

................................................ 업로드보안템플릿

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 제 2 장업로드보안템플릿 업로드취약점이란? 첨부파일업로드기능을악용하여웹쉘 (WebShell) 과같은해킹프로그램을업로드한후, 이를실행하여웹서버권한을획득하는공격방법이다. 파일업로드취약점은크게두가지의취약점이발견되면공격이가능하다. - 서버상에서실행할수있는스크립트파일을업로드할수있어야함 - 업로드된파일의위치를알아낼수있어야하며, 그위치가웹상에서실행가능해야함 사례 아래예는그림파일을업로드하기위한게시판에서업로드취약점으로인해공격을받은사례이다. < 그림 2-1> 스크립트업로드 < 그림 2-2> 스크립트실행 위의좌측그림에서악의적인스크립트파일이업로드되는것을볼수있다. 또한, 업로드된파일의위치가아래상태표시줄에노출되고있다. 우측그림은업로드한스크립트를웹브라우져를통해실행한것이다. 이스크립트를통해해커는시스템내의파일과폴더의편집 / 삭제 / 복사 / 이동, 임의의명령실행, DB 생성및조회등의작업을할수있다. 28 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 제 2 장 각언어별보안템플릿 <ASP 보안템플릿 > /include/secure.inc.asp : 업로드파일확장자검사함수 업로드보안템플릿 <% ' 확장자검사 '$filename: 파일명 '$avaext: 허용할확장자예 ) $avaext = "jpg,gif,pdf" ' 리턴값 : true-"ok", false-"error" Function Check_Ext(filename,avaext) Dim bad_file, FileStartName, FileEndName if instr(filename,"\0") Then Response.End End if ' 업로드금지확장자체크 bad_file = "asp,html,htm,asa,hta" filename = Replace(filename, " ", "") filename = Replace(filename, "%", "") FileStartName = Left(filename,InstrRev(filename,".")-1) FileEndName = Mid(filename, InstrRev(filename, ".")+1) bad_file = split(bad_file, ",") for each p in bad_file if instr(fileendname, p)>0 then Check_Ext = "error" Exit Function end if next ' 허용할확장자체크 www.krcert.or.kr 29

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 if avaext <> "" Then ok_file = split(avaext, ",") End If for each p in ok_file if instr(fileendname, p)>0 then Check_Ext = "ok" Exit Function End If next Check_Ext = "error" End Function %> /upload.html : 업로드입력폼웹페이지 <HTML> <HEAD> <TITLE>Upload Test</TITLE> </HEAD> <BODY> <form name="frmup" method="post" action="upload.asp" enctype="multipart/form-data"> <p> 파일 : <input type="file" name="attachfile" style="border:1 solid slategray"></p> <p> 전송 : <input type="submit" style="width:150; border:1 solid slategray"></p> </BODY> </HTML> /upload.asp : 파일업로드실행페이지 <!--#include virtual="/include/connection.inc.asp"--> <% 'DB연결헤더 %> <!--#include virtual="/include/secure.inc.asp"--> <% ' 보안관련라이브러리 %> <!--#include virtual="/include/config.inc.asp"--> <% ' 전역변수리스트 %> <!--#include virtual="/head.asp"--> <% ' 초기설정페이지 ( 에러메시지미출력 ) %> <% Dim DirectoryPath DirectoryPath = Server.MapPath("Uploaded_Files") ' 파일이저장될로컬폴더경로 30 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 Dim abc, ofile, fileext Set abc = Server.CreateObject("ABCUpload4.XForm") abc.absolutepath = True 제 2 장 Set ofile = abc("attachfile")(1) Dim strfilename, FileSize, FileType, strfilewholepath If ofile.fileexists Then strfilename = ofile.safefilename FileSize = ofile.length FileType = ofile.filetype 업로드보안템플릿 니다 "");" Else '-- 업로드금지파일체크--- If Check_Ext(strFileName,fileext) = "error" Then Response.Write "<script language=javascript>" Response.Write "alert("" 파일업로드실패1 "");" Response.Write "history.back();" Response.Write "</script>" Else If ofile.length > 4096000 then Response.Write "<script language=javascript>" Response.Write "alert(""4m 이상의사이즈인파일은업로드하실수없습 Response.Write "history.back();" Response.Write "</script>" Response.end else strfilewholepath = GetUniqueName(strFileName, DirectoryPath) ofile.save strfilewholepath Response.Write " 파일업로드성공 " End if End If www.krcert.or.kr 31

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 Response.Write " 파일업로드실패 1" End If ' 유니크한파일경로및파일이름을얻어내는함수 Function GetUniqueName(byRef strfilename, DirectoryPath) Dim strname, strext ' 확장자를제외한파일명을얻는다. strname = Mid(strFileName, 1, InstrRev(strFileName, ".") - 1) strext = Mid(strFileName, InstrRev(strFileName, ".") + 1) ' 확장자를얻는다 Dim fso Set fso = Server.CreateObject("Scripting.FileSystemObject") Dim bexist : bexist = True ' 우선같은이름의파일이존재한다고가정 Dim strfilewholepath : strfilewholepath = DirectoryPath & "\" & strname & "." & strext ' 저장할파일의완전한이름 ( 완전한물리적인경로 ) 구성 Dim countfilename : countfilename = 0 ' 파일이존재할경우, 이름뒤에붙일숫자를세팅함. Do While bexist ' 우선있다고생각함. If (fso.fileexists(strfilewholepath)) Then ' 같은이름의파일이있을때 countfilename = countfilename + 1 ' 파일명에숫자를붙인새로운파일이름생성 strfilename = strname & "(" & countfilename & ")." & strext strfilewholepath = DirectoryPath & "\" & strfilename Else bexist = False End If Loop GetUniqueName = strfilewholepath End Function %> 32 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <PHP 보안템플릿 > /include/config.inc.php : 허용할확장자변수 <? $exts = "jpg,gif,swf"; // 허용할확장자리스트?> /include/secure.inc.php : 업로드확장자체크함수 제 2 장 업로드보안템플릿 <? // 확장자검사 //$filename: 파일명 //$avaext: 허용할확장자예 ) $avaext = "jpg,gif,pdf" // 리턴값 : true-"ok", false-"error" function checkext($filename,$avaext) { if(eregi("\\0",$filename)) { return "error"; // 업로드금지확장자체크 if(eregi('\.inc \.htm \.shtm \.ztx \.dot \.cgi \.pl \.phtm \.php \.ph',$filename)) return "error"; // 허용확장자가설정된경우 if ($avaext!= "") { $extfile = str_replace(","," \\.", $avaext); $extfile = "\\.". $extfile; if(eregi($extfile,$filename)) return "ok";?> return "error"; www.krcert.or.kr 33

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 /process.php : 게시판글쓰기처리웹페이지 <? require "include/connect.inc.php"; require "include/config.inc.php"; require "include/secure.inc.php"; require "include/lib.php";?> <? $connect = db_connect(); //DB 연결헤더 // 전역변수리스트 // 보안라이브러리 // 게시판라이브러리 // 입력변수처리 $board = sqlfilter($_post[board]); $name = sqlfilter($_post[name]); $title = sqlfilter($_post[title]); $email = sqlfilter($_post[email]); $homepage = sqlfilter($_post[homepage]); $content = sqlfilter($_post[content]); $passwd = sqlfilter(trim($_post[passwd])); $result = mysql_query("select MAX(num) AS num, MAX(idx) AS idx,max(no) AS no FROM $board", $connect); $ist[num] = mysql_result($result, 0, "num"); $ist[num] += 1; $ist[idx] = mysql_result($result, 0, "idx"); $ist[idx] += 1; mysql_free_result($result); $intime = time(); //$passwd = crypt($passwd); 34 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 if ($userfile_size > 0) { if (checkext($userfile_name,$exts) == "error") { echo " 파일확장자에러 "; exit; mkdir("upload/$board/$intime", 0755); exec("move \"$userfile\" \"upload/$board/$intime/$userfile_name\""); //chmod("upload/$board/$intime/$userfile_name", 0644); 제 2 장 업로드보안템플릿 $query = "INSERT INTO $board VALUES('',$ist[num], $ist[idx], '$title', '$content',0, 0, 0, 0,0, '', '$userfile_name', $userfile_size,' $name', '$passwd', '$email', '$homepage', $intime)"; $result = mysql_query($query, $connect);?> /write.html : 업로드가가능한게시판글쓰기웹페이지 <html> <head> <title> 글입력 </title> </head> <body> <center> <form method="post" action="process.php" enctype="multipart/form-data"> <input type="hidden" name="board" value="<?php=$board?>"> <table width="550" cellspacing="1" border="0" cellpadding="2"> <td align="left"><font size="2"><b> <a href="list.php?board=<?php=$board?>"> 게시물목록 www.krcert.or.kr 35

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 </a></b></font></td> </table> <table width="400" cellspacing="1" bgcolor="#a5a595" border="0" cellpadding="5"> <td width="30%" bgcolor="#a5a595" align="center"> <font size="2" color="white"><b> 작성자명 </b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><input type="text" name="name" size="10" maxlength="10"></font></td> <td width="30%" bgcolor="#a5a595" align="center"><font size="2" color="white"><b>email</b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><input type="text" name="email" size="20" maxlength="256"></font></td> <td width="30%" bgcolor="#a5a595" align="center"><font size="2" color="white"><b>homepage</b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><input type="text" name="homepage" size="20" maxlength="256"></font></td> <td width="30%" bgcolor="#a5a595" align="center"><font size="2" color="white"><b> 비밀번호 </b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><input type="password" name="passwd" size="10" maxlength="20"></font></td> <td width="30%" bgcolor="#a5a595" align="center"><font size="2" color="white"><b> 글제목 </b></font></td> 36 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <td width="70%" bgcolor="white" align="left"><font color="white"><input type="text" name="title" size="30" maxlength="256"></font></td> <!-- 파일업로드 --> <td width="30%" bgcolor="#a5a595" align="center"><font size="2" color="white"><b> 파일 </b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><input type="file" name="userfile" size="20" maxlength="256"></font></td> <td width="30%" bgcolor="#c5c5b5" align="center"><font size="2" color="white"><b> 본문 </b></font></td> <td width="70%" bgcolor="white" align="left"><font color="white"><textarea name="content" wrap="hard" rows="10" cols="36"></textarea></font></td> </table> 제 2 장 업로드보안템플릿 <input type="submit" value=" 저장하자 "> <input type="reset" value=" 재작성 "> </form> <table width="550" cellspacing="1" border="0" cellpadding="2"> <td align="right"><font size="2"><b> <a href="list.php?board=<?php=$board?>"> 게시물목록 </a></b></font></td> </table> </center> </body> </html> www.krcert.or.kr 37

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <JSP 보안템플릿 > 별도의파일업로드모듈이없어일반적으로별도의외장클래스를사용하여작성한다. /config.inc.jsp : 업로드파일저장위치변수 <% String savepath="c:/tforwindows/tomcat5/webapps/root/upload/"; // 저장할디렉토리 ( 절대경로 ) %> /secure.inc.jsp : 확장자체크함수 <% // 확장자검사 //$filename: 파일명 //$avaext: 허용할확장자예 ) $avaext = "jpg,gif,pdf" // 리턴값 : true-"ok", false-"error" String checkext(string filename, String avaext) { String chkext = "false"; if (filename.indexof("\0") > -1) { chkext = "false"; // 업로드금지확장자체크 String file_ext = filename.substring(filename.lastindexof('.') + 1); if(( file_ext.equalsignorecase("jsp") file_ext.equalsignorecase("htm") file_ext.equalsignorecase("html")) ) { //out.println(" 업로드금지확장자 "); chkext = "false"; // 허용확장자가설정된경우 38 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 if (!avaext.equals("")) { // 공백제거 avaext.replaceall(" ",""); String compstr[] = avaext.split(","); for (int i = 0;i < compstr.length; i++) { if (file_ext.equalsignorecase(compstr[i])) { chkext = "true"; else { chkext = "true"; 제 2 장 업로드보안템플릿 %> return chkext; /upload.html : 파일업로드용웹페이지 <html> <body> <form action="upload.jsp" enctype="multipart/form-data" method="post"> 이름 : <input type="text" name="username"> <BR> 파일 : <input type="file" name="upfile"> <input type="submit" value="upload"> </form> </body> </html> www.krcert.or.kr 39

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 /upload.jsp : 파일업로드처리페이지 <%@ page contenttype="text/html;charset=euc-kr" %> <%@ page import="com.oreilly.servlet.multipartrequest,com.oreilly.servlet.multipart.defaultfilerenamepolicy,java.uti l.*,java.io.*" %> <%@ include file="connection.inc.jsp" %> <%@ include file="config.inc.jsp" %> <%@ include file="secure.inc.jsp" %> <% String chkext="false"; int i, sizelimit = 5 * 1024 * 1024 ; // 5메가까지제한넘어서면예외발생 try { MultipartRequest multi=new MultipartRequest(request, savepath, sizelimit, new DefaultFileRenamePolicy()); Enumeration formnames=multi.getfilenames(); // 폼의이름반환 String formname=(string)formnames.nextelement(); // 자료가많을경우엔 while 문을사용 String filename=multi.getfilesystemname(formname); // 파일의이름얻기 chkext = checkext(filename, avaext); if(filename == null) { // 파일이업로드되지않았을때 out.println(" 파일업로드되지않았음 "); else { // 파일이업로드되었을때 if (chkext.equals("true")) { filename=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩 - 브라우져에출력 out.println("user Name : " + multi.getparameter("username") + "<BR>"); out.println("form Name : " + formname + "<BR>"); out.println("file Name : " + filename); else { 40 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 out.println(avaext+" 만가능 "); File tmp = new File(savePath+"\\"+fileName); if (tmp.exists()) { tmp.delete(); // end if catch(exception e) { out.print(" 예외상황발생..! "); %> 제 2 장 업로드보안템플릿 www.krcert.or.kr 41

................................................

................................................ 다운로드보안템플릿

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 제 3 장다운로드보안템플릿 다운로드취약점이란? 홈페이지상에서파일열람또는다운로드를위해입력되는경로를체크하지않을때웹서버의홈디렉토리를벗어나서임의의위치에있는파일 (/etc/passwd 파일등 ) 을열람하거나다운로드받는공격이다. 이공격은입력되는 URL 경로에서임의의문자 (../.. 등 ) 나주요파일명 (passwd 등 ) 에대한필터링을하지않아발생된다. 사례 아래와같이파일을다운로드받아야하는 URL 의경우공격자는 filename 변수값을../../../../../../../winnt/win.ini 와같이상대경로를이용해서시스템내부의파일을불법으로획득할수있다. http://test.site.com/board/download.jsp?num=203&filename=upload/azip.exe 다운로드파일위치및파일이름 < 그림 3-1> 시스템내부파일을획득한사례 44 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 각언어별보안템플릿 <ASP 보안템플릿 > 제 3 장 /include/config.inc.asp : 다운로드위치변수 <% UploadedPath = "/Uploaded_Files/" ' 업로드기본경로 %> 다운로드보안템플릿 /include/secure.inc.asp : 다운로드경로입력값검사 <% ' 다운로드경로체크함수 '$dn_dir - 다운로드디렉토리경로 (path) '$fname - 다운로드파일명 ' 리턴 - true: 파운로드파일경로, false: "error" Function Check_Path(dn_dir, fname) dn_dir = Replace(dn_dir, "/", "\") fname = Replace(fname, "/", "\") strfile = Server.MapPath(dn_dir) & "\" & fname ' 서버절대경로 strfname = Mid(fname,InstrRev(fname,"\")+1) ' 파일이름추출,..\ 등의하위경로탐색은제거됨 Response.Write strfname strfpath = Server.MapPath(dn_dir) & "\" & strfname ' 웹서버의파일다운로드절대경로 If strfpath = strfile Then Check_Path = strfile ' 정상일경우파일경로리턴 Else Check_Path = "error" www.krcert.or.kr 45

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 End If End Function %> /download.asp : 다운로드페이지 <!--#include virtual="/include/connection.inc.asp"--> <% 'DB 연결헤더 %> <!--#include virtual="/include/secure.inc.asp"--> <% ' 보안관련라이브러리 %> <!--#include virtual="/include/config.inc.asp"--> <% ' 전역변수리스트 %> <!--#include virtual="/head.asp"--> <% ' 초기설정페이지 ( 에러메세지미출력 ) %> <% Dim dn_dir, fname, val_ok Dim UploadedPath dn_dir = Request("dir") fname = Request("fname") ' 파일이름 ' IE 5.01 에서는이방식을사용할때메모리관련문제가발생할수있다. strua = Request.ServerVariables("HTTP_USER_AGENT") If Instr(strUA, "MSIE") Then intversion = CDbl(mid(strUA, Instr(strUA, "MSIE")+5, 3)) End If If intversion < 5.01 Then Response.Write "error" End If if fname = "" Then Response.Write "<script language=javascript>" Response.Write "alert("" 파일명을입력해주세요 "");" Response.Write "history.back();" Response.Write "</script>" End If dn_dir = UploadedPath & dn_dir val_ok = Check_Path(dn_dir, fname) If val_ok <> "error" Then ' 사용자가다운받는파일과웹서버의파일다운로드경로가맞는지비교 Set objstream = Server.CreateObject("ADODB.Stream") 'Stream 이용 Response.ContentType = "application/unknown" 'ContentType 선언 Response.AddHeader "Content-Disposition","attachment; filename=" & fname objstream.open 46 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 objstream.type = 1 objstream.loadfromfile val_ok End If download = objstream.read Response.BinaryWrite download Set objstream = nothing %> ' 객체초기화 제 3 장 <PHP 보안템플릿 > /include/config.inc.php : 다운로드경로 <? $UploadedPath = "c:/apm_setup/php/upload"; // 기본다운로드디렉토리?> 다운로드보안템플릿 /include/secure.inc.php - 경로입력값체크함수 <? // 다운로드경로체크함수 //$dn_dir - 다운로드디렉토리경로 (path) //$fname - 다운로드파일명 // 리턴 - true: 다운로드파일경로, false: "error" function checkpath($dn_dir,$fname) { $dn_dir = str_replace("\\","/",$dn_dir); // 다운로드경로에공격문자필터링 if (eregi("\.\./",$dn_dir)) { print " 허용하지않는입력값입니다."; return "error"; // 사용자입력값으로다운로드파일경로생성 $dn_file = $dn_dir. "/". $fname; //$fname 에서파일명만분리 - 파일명에공격위험성문자필터링 //$filename = substr($dn_file, strrpos($dn_file, '/') + 1); www.krcert.or.kr 47

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 $filename=basename($fname); // 분리한파일명과절대경로를재구성 $strfname = $dn_dir. "/". $filename;?> // 사용자입력값과재구성한입력값을비교하여공격위험성이존재하는지확인 if ($strfname == $dn_file) return $strfname; else return "error"; /download.php : 다운로드페이지 <? require "include/connect.inc.php"; require "include/config.inc.php"; require "include/secure.inc.php"; require "include/lib.php";?> <? // 파일명입력체크 if ($_REQUEST[fname] == "") { print " 인수를입력해주세요."; exit; //DB 연결헤더 // 전역변수리스트 // 보안라이브러리 // 게시판라이브러리 $dn_dir = $_REQUEST[dir]; $dn_fname = $_REQUEST[fname]; $bufsize = 20000; $strfname = checkpath($dn_dir, $dn_fname); if ($dn_path!= "error") { // 절대경로생성 $dn_path = $UploadedPath. $strfname; $fsize=filesize($dn_path); 48 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 else {?> // 파일전송루틴 header("http/1.1 200 OK"); header("content-length: $fsize"); header("content-type: application/force-download"); header("content-disposition: attachment; filename=$dn_fname"); header("content-transfer-encoding: binary"); if($fh = fopen($dn_path, "rb")) { while($buf = fread($fh, $bufsize)) print $buf; fclose($fh); else { echo " 파일에러 "; header("http/1.1 404 Not Found"); echo " 입력값오류 1"; 제 3 장 다운로드보안템플릿 <JSP 보안템플릿 > /config.inc.jsp : 다운로드기본경로지정 <% String DN_PATH= "C:/TforWindows/Tomcat5/webapps/root/board/uploaded_files/"; // 디폴트다운로드경로지정 %> /secure.inc.jsp : 다운로드입력값체크함수 <%! // 다운로드경로체크함수 //$dn_dir - 다운로드디렉토리경로 (path) //$fname - 다운로드파일명 // 리턴 - true: 다운로드파일경로, false: "error" www.krcert.or.kr 49

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 String checkpath(string dn_path, String fname) { // 입력되는디렉토리명에서특수문자유무검사 if((dn_path.indexof("..\\")!= -1) (dn_path.indexof("../")!= -1)) { return "error"; // 사용자입력값으로다운로드파일경로생성 if (dn_path.equals("")) { else { dn_path = dn_path + "/"; String origfile = dn_path + fname; //fname 에서파일명만분리 - 파일명에공격위험성문자필터링 fname.replaceall("\\","/"); // 일부버전에서오류발생 //String filename3 = fname.substring(fname.lastindexof('/') + 1); //fname.replaceall("\\","/") 가사용할수없는경우아래 String filename4 = fname.substring(fname.lastindexof('\\') + 1); // 분리한파일명과절대경로를재구성 String FilePath = dn_path + filename4; %> // 사용자입력값과재구성한입력값을비교하여공격위험성이존재하는지확인 if (origfile.equals(filepath)) { return (FilePath); else { return "error"; /download.jsp : 다운로드페이지 <%@ page import="java.util.*,java.io.*,java.sql.*,java.text.*" %> <%@ page contenttype="text/html;charset=euc-kr" %> <%@ include file="config.inc.jsp" %> <%@ include file="secure.inc.jsp" %> 50 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <% // 입력되는파일명의한글처리 String filename = java.net.urldecoder.decode(request.getparameter("file")); String filename2 = new String(filename.getBytes("euc-kr"),"8859_1"); String dirname = java.net.urldecoder.decode(request.getparameter("dir")); String dirname2 = new String(dirname.getBytes("euc-kr"),"8859_1"); String dn_path, FilePath; 제 3 장 dn_path = checkpath(dirname2, filename2); if (!dn_path.equals("error")) { // 파일전송프로세스 FilePath = DN_PATH+dn_path; File file = new File(FilePath); // 절대경로입력. byte b[] = new byte[(int)file.length()]; 다운로드보안템플릿 response.setheader("content-disposition", "attachment;filename=" + filename2 + ";"); if (file.isfile()) { BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream outs = new BufferedOutputStream(response.getOutputStream()); outs.close(); int read = 0; while ((read = fin.read(b))!= -1) { outs.write(b,0,read); else { %> fin.close(); out.println(" 입력값오류 1"); return; www.krcert.or.kr 51

............................................................................

................................................ Cross Site Script(XSS) 보안템플릿

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 제 4 장 Cross Site Script(XSS) 보안템플릿 XSS 취약점이란? 자바스크립트처럼클라이언트측에서실행되는언어로작성된악성스크립트코드를웹페이지, 웹게시판또는이메일에포함시켜이를열람한사용자컴퓨터에서악성스크립트가실행되게하고사용자의개인정보등을유출시키는공격이다. 이공격은사용자로부터입력받은데이터를필터링하지않고그대로동적으로생성된웹페이지에포함시켜사용자에게보여줄때발생한다. 사례 아래와같이사용자가글을입력하는부분에악의적인 JavaScript 를이용하여해당정보를열람하는사용자의 Cookie 정보등을탈취할수있다. < 그림 4-1> 악의적인 JavaScript 아래그림은해당글을열람한사용자의 Cookie 정보가공격자에게전달된것이다. < 그림 4-2> Cookie 정보가공격자에게전달된화면 54 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 각언어별보안템플릿 이 clearxss 함수는입력값에위험성이존재하는태그를필터링하도록되어있으며그외에태그에입력값으로사용하는방식 ( 예 ) <img src="[ 입력값 ] > ) 에는적용이되지않는다. <ASP 보안템플릿 > /include/config.inc.asp <% atag = "p,br" %> /include/secure.inc.asp 'XSS 허용할태그리스트 'XSS 출력필터함수 'XSS 필터함수 '$str - 필터링할출력값 '$avatag - 허용할태그리스트예 ) $avatag = "p,br" Function clearxss(strstring, avatag) 'XSS 필터링 strstring = replace(strstring, "<", "<") strstring = replace(strstring, "\0", "") 제 4 장 Cross Site Script (XSS) 보안템플릿 ' 허용할태그변환 avatag = replace(avatag, " ", "") if (avatag <> "") Then taglist = split(avatag, ",") ' 공백제거 for each p in taglist strstring = replace(strstring, "<"&p&" ", "<"&p&" ", 1, -1, 1) strstring = replace(strstring, "<"&p&">", "<"&p&">", 1, -1, 1) strstring = replace(strstring, "</"&p&" ", "</"&p&" ", 1, -1, 1) www.krcert.or.kr 55

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 next End If clearxss = strstring End Function /content.asp <!--#include virtual="/include/connection.inc.asp"--> <% 'DB 연결헤더 %> <!--#include virtual="/include/secure.inc.asp"--> <% ' 보안관련라이브러리 %> <!--#include virtual="/include/config.inc.asp"--> <% ' 전역변수리스트 %> <!--#include virtual="/head.asp"--> <% ' 초기설정페이지 ( 에러메시지미출력 ) %> <% Dim strsql Dim intseq, strname, stremail, strsubject, strcontent, intcount, dtmreg_date, intexist Dim blntag, struserip Dim atag intseq = gfilter(request.querystring("seq"))'sql Injection 필터링 ' 읽은횟수검색 strsql = "SELECT count(*) FROM board WHERE intseq='" & intseq & "'" objrs.open strsql, objdbconn intexist = objrs(0) objrs.close If intexist <> 1 Then Response.Write " 해당글이없습니다." Else ' 읽은횟수증가 strsql = "UPDATE board SET intcount=intcount+1 WHERE intseq='" & intseq & "'" objrs.open strsql, objdbconn ' 게시물 SELECTZ strsql = "SELECT strname,stremail,strsubject,strcontent,intcount,struserip,blntag,dtmreg_date FROM board WHERE intseq='" & intseq & "'" 56 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 objrs.open strsql, objdbconn strname = objrs(0) stremail = objrs(1) strsubject = objrs(2) strcontent = objrs(3) intcount = objrs(4) struserip = objrs(5) blntag = objrs(6) dtmreg_date = objrs(7) objrs.close Set objrs = Nothing 제 4 장 objdbconn.close Set objdbconn = Nothing ' 게시물출력값에 XSS 필터링 ' 사용자가입력하는출력되는값은 strname, stremail, strsubject, strcontent으로이부분은 XSS 공격이가능한부분들이다. ' 일반적으로본문만선택적으로 HTML 태그사용을허용하며나머지부분들은사용할수없도록하는것이바람직하다. strname = clearxss(strname, atag) stremail = clearxss(stremail, atag) strsubject = clearxss(strsubject, atag) strcontent = clearxss(strcontent, atag) Cross Site Script (XSS) 보안템플릿 %> <html> ' 줄넘김처리 strcontent = replace(strcontent, vblf, vblf & "<br>") <head> <meta http-equiv="content-type" content="text/html; charset=ks_c_5601-1987"> <title> 내용보기 </title> </head> www.krcert.or.kr 57

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <body> <div align=center> <table border=1> <td> 이름 </td> <td><%=strname%></td> <td> 등록일 </td> <td><%=dtmreg_date%></td> <td> 이메일 </td> <td><%=stremail%></td> <td> 조회 </td> <td><%=intcount%></td> <td> 제목 </td> <td colspan=3><%=strsubject%></td> <td> 내용 </td> <td colspan=3><%=strcontent%></td> <td colspan=4> <a href="list.asp"> 목록으로 </a> <a href="edit.asp?seq=<%=intseq%>"> 수정하기 </a> <a href="delete.asp?seq=<%=intseq%>"> 삭제하기 </a> </td> </table> </div> </body> </html> <% End If %> 58 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <PHP 보안템플릿 > /include/config.inc.php <? $avatag = "p,br"; //XSS 에서허용할태그리스트?> /include/secure.inc.php <? //XSS 필터함수 //$str - 필터링할출력값 //$avatag - 허용할태그리스트예 ) $avatag = "p,br" function clearxss($str,$avatag) { $str=str_replace("<","<", $str); $str=str_replace("\0","", $str); // 허용할태그를지정할경우 $str=str_replace(" ", "", $avatag); if ($avatag!= "") { $otag = explode (",", $avatag); 제 4 장 Cross Site Script (XSS) 보안템플릿 // 허용할태그를존재여부를검사하여원상태로변환 for ($i = 0;$i < count($otag);$i++) { $str = eregi_replace("<".$otag[$i]." ", "<".$otag[$i]." ", $str); $str = eregi_replace("<".$otag[$i].">", "<".$otag[$i].">", $str); $str = eregi_replace("</".$otag[$i], "</".$otag[$i], $str);?> return $str; www.krcert.or.kr 59

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 /view.php <? require "include/connect.inc.php"; //DB 연결헤더 require "include/config.inc.php"; // 전역변수리스트 require "include/secure.inc.php"; // 보안라이브러리 require "include/lib.php"; // 게시판라이브러리?> <? $no = gfilter($_request[no]); // SQL Injection 필터 $board = gfilter($_request[board]); // SQL Injection 필터 // 읽기횟수저장 $updok = mysql_query("update $board SET hit = hit + 1 WHERE no=$no", $connect); $query = sprintf("select * FROM %s WHERE no='%d'",$board,$no); $result = mysql_query($query); $view = @mysql_fetch_array($result); //@ 를이용하여에러메세지출력을하지않는다. //XSS 필터링 $view[usrname] = clearxss($view[usrname],$avatag); $view[usremail] = clearxss($view[usremail],$avatag); $view[usrtitle] = clearxss($view[usrtitle],$avatag); $view[contents] = clearxss($view[contents],$avatag); $dates = date ("Y-m-d, h:i:s", $view[filluptime]); $perpage = 10; $tlpn = get_pagenum(); $nowpage = get_page($view[idx]); if ($view[usremail]!= "") { $name = "<a href=\"mailto:$view[usremail]\">$view[usrname]</a>"; else { $name = "$view[usrname]"; 60 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 if ($view[usrhomepage]!= "") { $homeurl = "<a href=\"$view[usrhomepage]\" target=\"_blank\">[homepage]</a>"; else { $homeurl = ""; echo " <html> <head> <title> 글내용보기 </title> </head> <body> <center> <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td align=\"left\"><font size=\"2\"><b> <a href=\"list.php?board=$board&page=$nowpage\"> 게시물목록 </a> <a href=\"edit.php?board=$board&no=$no\"> 수정 </a> <a href=\"delete.php?board=$board&no=$no\"> 삭제 </a> </b></font></td> </table> 제 4 장 Cross Site Script (XSS) 보안템플릿 <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td colspan=\"2\" bgcolor=\"#a5a595\"><font color=\"white\" size=\"2\">$view[num] 번글 : <b>$view[usrtitle]</b></font></td> <td align=\"left\" bgcolor=\"#e5e5d5\"><font size=\"2\"> 조회수 : $view[hit]</font></td> www.krcert.or.kr 61

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <td align=\"right\" bgcolor=\"#e5e5d5\"><font size=\"2\">$name 님이 $homeurl $dates 에작성해주셨습니다.</font></td> </table>"; if ($view[filesize] > 0) { $view[contents].= "<p align=\"right\">"; $view[contents].= "<a href=\"dn.php?board=$board&no=$view[no]\">"; $view[contents].= $view[filename]; $view[contents].= "</a>"; echo " <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td><font size=\"2\">$view[contents]</font> </td> </table> <table width=\"550\" cellspacing=\"1\" border=\"0\" cellpadding=\"2\"> <td align=\"right\"><font size=\"2\"><b> <a href=\"list.php?board=$board&page=$nowpage\"> 게시물목록 </a> <a href=\"edit.php?board=$board&no=$no\"> 수정 </a> <a href=\"delete.php?board=$board&no=$no\"> 삭제 </a> </b></font></td> </table> </center> </body> </html> ";?> 62 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <JSP 보안템플릿 > /config.inc.jsp <% String avatag = "p,br"; %> // 허용할확장자리스트 /secure.inc.jsp <% //XSS 필터함수 //$str - 필터링할출력값 //$avatag - 허용할태그리스트예 ) $avatag = "p,br" String clearxss(string str, String avatag) { str = str.replaceall("<","<"); str = str.replaceall(" 0"," "); // 허용할태그를지정할경우 if (!avatag.equals("")) { avatag.replaceall(" ",""); 제 4 장 Cross Site Script (XSS) 보안템플릿 String [] st = avatag.split(","); // 허용할태그를존재여부를검사하여원상태로변환 for( int x = 0; x < st.length; x++ ) { str = str.replaceall("<"+str+" ", "<"+str+" "); str = str.replaceall("<"+str+">", "<"+str+">"); str = str.replaceall("</"+str, "</"+str); %> return (str); www.krcert.or.kr 63

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 /view.jsp <!-- www.itmembers.net의 JSP게시판만들기강좌에서손병목님이작성하신 view.jsp파일을 strip Tokonizer 사용을위해인용하였습니다. --> <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ include file="connection.inc.jsp" %> <%@ include file="config.inc.jsp" %> <%@ include file="secure.inc.jsp" %> <% String s_tablename = "bbs"; // 테이블이름 String s_sql, s_number, s_name="", s_email="", s_homepage="", s_subject="", s_memo="" ; String s_mail_addr=""; String s_page ; int i_number, i_count=0, i_page ; StringTokenizer st = null; // <br> 처리를위해서 String s_temp = ""; s_number = request.getparameter("number"); // view.jsp?number=10 과같이넘어온값 "10" 을받음. //i_number = Integer.parseInt(s_number); s_page = request.getparameter("page"); // view.jsp?page=3 과같이넘어온값 "3" 을넘겨받음. if(s_page==null) s_page="1"; //i_page = Integer.parseInt(s_page); s_number = gfilter(s_number); s_page = gfilter(s_page); //SQL Injection 필터 //SQL Injection 필터 //out.println(s_number); //out.println(s_page); try { s_sql = "select name,count,email,homepage,subject,memo from "+s_tablename+" where number='"+s_number+"'"; rs = stmt.executequery(s_sql); // 쿼리문실행결과값을담을객체 if(rs.next()) { 64 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 //XSS 필터 s_name = clearxss(rs.getstring(1),avatag); i_count = rs.getint(2); s_email = clearxss(rs.getstring(3),avatag); s_homepage = clearxss(rs.getstring(4),avatag); s_subject = clearxss(rs.getstring(5),avatag); s_memo = clearxss(rs.getstring(6),avatag); if(!s_email.equals("")) { s_mail_addr="<a href=mailto:"+s_email+">"+s_email+"</a>"; else { s_mail_addr=s_email; // Enter 를 <br> 로처리 st = new StringTokenizer(s_memo,"\n"); while(st.hasmoretokens()) { s_temp = s_temp + st.nexttoken()+"<br>"; s_memo = s_temp; s_sql = "update "+s_tablename+" set count = count + 1 where number = "+s_number; 제 4 장 Cross Site Script (XSS) 보안템플릿 stmt.executeupdate(s_sql); stmt.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 stmt 닫기 Conn.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 Conn 닫기 catch (Exception e) { out.println(e); %> <html> <head> <title>jsp 게시판프로젝트 - 보기 </title> <STYLE TYPE="text/css"> www.krcert.or.kr 65

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 BODY,TD,SELECT,input,DIV,form,TEXTAREA,center,option,pre,blockquote {font-family: 굴림 fontsize:9pt;color:#555555; A:link {color:black;text-decoration:none; A:visited {color:black;text-decoration:none; A:active {color:black;text-decoration:none; A:hover {color:gray;text-decoration:none; </STYLE> </head> <body bgcolor=white background=./images/body_bg.gif> <img src=./images/maintitle.gif> <table border=0 cellspacing=1 cellpadding="3" width=670> <td align=center> <font color=green><b> 내용보기화면입니다.</b></font> </td> <td bgcolor="#eac3ea"> <table border=0 cellspacing=1 cellpadding=0 width=670 bgcolor="white"> <td width="100"> <p align="right"><b> 이름 </b></p> </td> <td width="400"> <p><%= s_name %></p> </td> <td width="100"> <p align="right"><b> 조회수 </b></p> </td> <td> <p><%= i_count %></p> </td> <td width="100"> <p align="right"><b> 전자우편 </b></p> </td> <td colspan="3"> 66 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <p><%= s_mail_addr %></p> </td> <td width="100"> <p align="right"><b> 홈페이지 </b></p> </td> <td colspan="3"> <p><%= s_homepage %></p> </td> <td width="100"> <p align="right"><b> 제목 </b></p> </td> <td colspan="3"> <p><%= s_subject %></p> </td> <td width="100"> <p align="right"><b> 내용 </b></p> </td> <td colspan="3"> <p><%= s_memo %></p> </td> </table> <p align="center"><a href="list.jsp?page=<%= s_page %>">[ 목록 ]</a> <a href="write.html">[ 쓰기 ]</a> <a href="modify.jsp?number=<%= s_number %>&page=<%= s_page %>">[ 수정 ]</a> <a href="delete.jsp?number=<%= s_number %>&page=<%= s_page %>">[ 삭제 ]</a></p> </td> </table> </body> </html> 제 4 장 Cross Site Script (XSS) 보안템플릿 www.krcert.or.kr 67

................................................

................................................ 접근통제보안템플릿

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 제 5 장접근통제보안템플릿 접근통제취약점이란? 관리자페이지등특정사용자들에게만접근이허용되어야하는웹사이트에대해불특정다수가접근가능하여공격하는취약점이다. 관리자페이지는회원 DB 나웹컨텐츠를관리할수있는기능과권한을갖고있으므로, 관리자이외에는접근할수없도록 IP 접근통제, 추측하기어려운 URL 사용 (admin, manager 등사용금지 ) 등으로접근자체를차단하여야한다. 사례 많은홈페이지들은 http://www.xxx.com/admin 등과같이관리자페이지가쉽게추측가능하다. 관리자페이지에접근이가능할경우로그인을위한별도의인증절차를마련한다고하더라도, SQL Injection, 패스워드유출등의취약점을이용하여웹관리자권한을획득할수있다. 다음그림은쉽게유출가능한관리자페이지명으로웹관리자페이지에접근한화면이다. < 그림 5-1> 유출가능한관리자페이지명 70 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 각언어별보안템플릿 <ASP 보안템플릿 > /admin/auth.asp : 접근통제할페이지초기에 include 하여권한검사를수행하는페이지 <% ' 각디렉토리별로권한을설정할수있다. ' 권한은 admin, user, unknown 세가지권한으로나누며 admin은 IP Address과로그인인증, user는로그인인증, unknown은모두접근이가능하도록구분한다. ' 이페이지를각폴더별로넣고접근을통제할웹페이지초기부분에 include 한다. UserGrade = "admin" ' 해당웹페이지의통제레벨설정 admin의경우 IP Address, 사용자인증모두체크 ' 세션체크정상적으로로그인했는지조사 If UserGrade <> Session("user_grade") Then Response.Write "<script>alert(' 접근제한 ');history.go(-1);</script>" Response.End Else ' 사용자권한이관리자일경우 If UserGrade = "admin" Then ' 접근한사용자 IP Address와세션에설정된 IP Address에포함되는지조사 If (instr(request.servervariables("remote_addr"), Session("access_ip"))) Then ' 로그인하였는지여부조사 If Session("logged_in") = "" Then Response.Write "<script>alert('ip: 접근제한 ');history.go(- 1);</script>" Response.End End If Else 제 5 장 접근통제보안템플릿 www.krcert.or.kr 71

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 Response.Write "<script>alert(' 로그인 : 접근제한 ');history.go(- 1);</script>" Reponse.End End If ' 권한이사용자일경우 ElseIf UserGrade = "user" Then If Session("user_id") = "" Then Response.Write "<script>alert(' 레벨 : 접근제한 ');history.go(-1);</script>" Response.End End If End If End If %> /admin/index.asp : 로그인인증을거친후 auth.asp 에서사용할세션값을설정하는페이지 <!--#include virtual="/include/connection.inc"--> <% ' 사용되는 ID 값은유일해야한다. ' ID 에대한 PW 값을가져와서입력된패스워드와비교하는방식으로기존의로그인방식은 ID,PW 를모두확인하는방식으로 WHERE 구문의조작으로루틴을우회할수있으나해당방식은인젝션이성공한다하더라도임의의인젝션된값과입력된값을비교하게되어공격의성공율을낮출수있다. Dim strquery, strsql Dim strid, strpw strid = Request("Name") strpw = Request("Password") ' 입력값 NULL 체크 If Len(strID) = 0 OR Len(strPW) = 0 then ' 입력값체크실패 Else ' 입력되는 ID 값의존재여부파악 strsql = "SELECT count(*) FROM userinfo WHERE strid = '" & strid & "'" objrs.open strsql, objdbconn 72 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 ' 유일하게존재하는경우 If objrs(0) = 1 Then objrs.close ' 접근 ID 와일치하는패스워드값을 SELECT 함으로써 SQL 구문으로인증체크를하지않도록한다. ' 오류를이용한 SQL Injection 기법에는기존의 SQL Injection 필터링방법으로통제한다. strsql = "SELECT strpassword,strname FROM userinfo WHERE strid = '" & strid & "'" objrs.open strsql, objdbconn 'SELECT된패스워드와입력패스워드비교 If StrComp(trim(objRs(0)),strPW) = 0 Then ' 로그인성공후프로세스작성 Session("logged_in") = 1 ' 로그인여부 Session("user_id") = strid ' 로그인한사용자 ID Session("access_ip") = "192.168.100" ' 접근허용한 IP 주소 Session("user_grade") = "admin" ' 로그인한사용자권한 Else ' 입력된패스워드와 SELECT한패스워드가다를경우로그인실패 Response.Write strid & " Login Failed" End If Else 'ID가복수일경우로그인실패 Response.Write strid & " Login Failed" End If objrs.close End If %> <HTML> <HEAD> </HEAD> <BODY> <H3><P> 텍스트상자정보입력하기 </P></H3> <form action="login.asp" name=postform method=post> <table border=0> <td> 아이디 : </td> <td><input type=text name=name size=20 value=""></td> 제 5 장 접근통제보안템플릿 www.krcert.or.kr 73

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 <td> 패스워드 : </td> <td><input type=password name=password size=20 value=""></td> <td colspan= 2 align=center><input type="submit" value= " 로그인 " id=submit1 name=submit1> <input type="reset" value=" 취소하기 " id=reset name=reset></td> </table> </form> </BODY> </HTML> 사용예 ) /admin/admin.asp : auth.asp 를 include 하여사용자권한검사 <!--#include file="auth.asp"--> <!--#include virtual="/include/connection.inc"--> <% %> 관리자페이지입니다. <PHP 보안템플릿 > /admin/auth.php : 접근통제할페이지초기에 include 하여권한검사를수행하는페이지 <? // 각디렉토리별로권한을설정할수있다. // 권한은 admin, user, unknown 세가지권한으로나누며 admin은 IP Address과로그인인증, user는로그인인증, unknown은모두접근이가능하다. $UserGrade = "admin"; @session_start(); // 권한검사 if ($UserGrade!= $_SESSION["user_grade"]) { print " 권한없음 "; 74 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 else {?> if ($UserGrade == "admin") { //IP 주소검사 if (eregi($_session["access_ip"], $_SERVER["REMOTE_ADDR"] ) == false) { print "IP: 접근제한 "; exit else { // 로그인여부조사 if (isset($_session["logged_id"])) { print " 로그인 : 접근제한 "; exit; else if ($UserGrade == "user") { if ($_SESSION["user_id"] == "") { print " 권한없음 "; exit; 제 5 장 접근통제보안템플릿 /admin/login.php : 로그인인증을거친후 auth.php에서사용할세션값을설정하는페이지 <? require_once "../include/lib.php"; require_once "../include/secure.inc"; @session_start(); $connect=db_connect(); $mb_table = "userinfo"; $user_id = getfilter($user_id); $password = getfilter($user_pw); www.krcert.or.kr 75

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 if(!$user_id) print (" 아이디를입력하여주십시요 "); if(!$password) print (" 비밀번호를입력하여주십시요 "); // 회원로그인체크 $result = mysql_query("select id,user_id,password from $mb_table where user_id='$user_id'"); $mb_data = mysql_fetch_array($result); if($mb_data[password] == $password) { // 회원로그인이성공하였을경우세션을생성하고페이지를이동함 // 로그인후프로세스 $logged_in = 1; session_register("logged_in"); session_register("user_id"); $user_grade = "admin"; session_register("user_grade"); $access_ip = "222.234.226."; session_register("access_ip"); print " 로그인성공 "; else { // 회원로그인이실패하였을경우에러표시 print (" 로그인실패 "); db_close($connect);?> 사용예 ) /admin/admin.php : auth.php 를 include 하여사용자권한검사설정하고자하는디렉토리에 auth.php 생성해당디렉토리에있는접근설정이필요한페이지에아래내용을추가한다. <? include "auth.php";?> 76 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 <JSP 보안템플릿 > /admin/auth.jsp : 접근통제할페이지초기에 include 하여권한검사를수행하는페이지 <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ page import="java.util.*,java.lang.*,java.io.*,java.sql.*,java.text.*" %> <% HttpSession sess = request.getsession(true); String access_ip = request.getremoteaddr(); String admin_ip = (String)sess.getValue("admin_ip"); String UserGrade = "admin"; // 권한검사 if (UserGrade.equals(sess.getValue("user_grade"))) { if (UserGrade.equals("admin")) { //IP 검사 if (access_ip.indexof(admin_ip)!= -1) { if (sess.getvalue("logged_in").equals("")) { out.println(" 권한없음 "); return; else { out.println(" 권한없음 "); return else if (UserGrade.equals("user")) { if (sess.getvalue("user_id").equals("")) { out.println(" 권한없음 "); return; 제 5 장 접근통제보안템플릿 www.krcert.or.kr 77

제 1 장 SQL Injection 보안템플릿제 2 장업로드보안템플릿제 3 장다운로드보안템플릿 else { %> out.println(" 권한없음 "); return; /admin/login.jsp : 로그인인증을거친후 auth.jsp에서사용할세션값을설정하는페이지 <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ include file="conn_db.jsp" %> <%@ include file="secure.jsp" %> <% String s_tablename = "user"; // 테이블이름 String s_id, s_pw, s_name; //SQL 구문실행결과값저장 String g_id, g_pw; // 입력값저장 String s_sql, grade; g_id = getfilter(request.getparameter("id")); g_pw = getfilter(request.getparameter("pw")); HttpSession sess = request.getsession(true); try { s_sql = "SELECT * FROM " + s_tablename + " WHERE id='" + g_id + "'"; rs = stmt.executequery(s_sql); // 쿼리문실행결과값을담을객체 if (rs.next()) { s_id = rs.getstring(1); s_pw = rs.getstring(2); s_name = rs.getstring(3); if (s_pw.equals(g_pw)) { 78 www.kisa.or.kr

제 4 장 Cross Site Script (XSS) 보안템플릿 제 5 장접근통제보안템플릿 웹어플리케이션보안템플릿 // 로그인후처리프로세스 sess.putvalue("logged_in","1"); sess.putvalue("user_id",s_id); sess.putvalue("admin_ip", "222.234.226."); sess.putvalue("user_grade", "admin"); out.println(" 로그인성공 "); else { // 로그인실패시처리프로세스 out.println(" 로그인실패 : 패스워드오류 "); else { // 로그인실패시처리프로세스 out.println(" 로그인실패 : 사용자없음 "); //DB 처리 stmt.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 stmt 닫기 Conn.close(); // 인클루드파일 (db_conn.jsp) 에서생성한 Conn 닫기 제 5 장 접근통제보안템플릿 catch (Exception e) { out.println(e); %> 사용예 ) /admin/admin.jsp : auth.jsp 를 include 하여사용자권한검사설정하고자하는디렉토리에 auth.jsp 생성해당디렉토리에있는접근설정이필요한페이지에아래내용을추가한다. <%@ page language="java" import="java.sql.*,java.util.*" contenttype="text/html;charset=ksc5601" %> <%@ include file="auth.jsp" %> www.krcert.or.kr 79

참고문헌 [1] 한국정보보호진흥원, 홈페이지개발보안가이드, 2005 [2] http://www.kisa.or.kr/ [3] http://www.krcert.or.kr/ [4] http://www.innoboard.com/ [5] http://www.nzeo.com/ http://www.php.net/ [6] http://www.taeyo.pe.kr/ [7] http://www.okjsp.pe.kr/ [8] http://www.itmembers.net/ [9] http://www.php.net/ [10] http://www.owasp.org/ 80 www.kisa.or.kr