웹애플리케이션 취약점 대응 가이드

Similar documents
PowerPoint Template

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

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

<C0A5C0C0BFEBC7C1B7CEB1D7B7A5B0B3B9DFBAB8BEC8B0A1C0CCB5E528C3D6C1BE292E687770>

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

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

Windows 8에서 BioStar 1 설치하기

untitled

PowerPoint Template

Javascript

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

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

The Pocket Guide to TCP/IP Sockets: C Version

제목 레이아웃

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

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

10.ppt

Microsoft Word - src.doc

Microsoft PowerPoint 웹 연동 기술.pptx

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

3장

Secure Programming Lecture1 : Introduction

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

쉽게 풀어쓴 C 프로그래밊

untitled

로거 자료실

PowerPoint 프레젠테이션

SQL Developer Connect to TimesTen 유니원아이앤씨 DB 기술지원팀 2010 년 07 월 28 일 문서정보 프로젝트명 SQL Developer Connect to TimesTen 서브시스템명 버전 1.0 문서명 작성일 작성자

Microsoft Word - Windows_apahce_php_CUBRID2008

0. 들어가기 전

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

2009년 상반기 사업계획

Microsoft PowerPoint - [Practice #1] APM InstalI.ppt

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

< 목차 > Ⅰ. 개요 3 Ⅱ. 실시간스팸차단리스트 (RBL) ( 간편설정 ) 4 1. 메일서버 (Exchange Server 2007) 설정변경 4 2. 스팸차단테스트 10

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

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

< FC8A8C6E4C0CCC1F620B0B3B9DF20BAB8BEC8B0A1C0CCB5E5C3D6C1BE28C0FAC0DBB1C7BBE8C1A6292E687770>

슬라이드 1

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

1. Windows 설치 (Client 설치 ) 원하는위치에다운받은발송클라이언트압축파일을해제합니다. Step 2. /conf/config.xml 파일수정 conf 폴더에서 config.xml 파일을텍스트에디터를이용하여 Open 합니다. config.xml 파일에서, 아

chapter1,2.doc

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

<5BB5BFB8EDB4EB2D E4B5D C0A5BDA9C0C720BAD0BCAEB0FA20B4EBC0C020B9E6BEC82E687770>

LXR 설치 및 사용법.doc

슬라이드 1

MySQL-.. 1

DBMS & SQL Server Installation Database Laboratory

BEA_WebLogic.hwp

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

Observational Determinism for Concurrent Program Security

JDBC 소개및설치 Database Laboratory

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

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

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

Microsoft PowerPoint 세션.ppt

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

윈도우시스템프로그래밍

SKINFOSEC-CHR-028-ASP Mssql Cookie Sql Injection Tool 분석 보고서.doc

목차 1. 시스템요구사항 암호및힌트설정 ( 윈도우 ) JetFlash Vault 시작하기 ( 윈도우 ) JetFlash Vault 옵션 ( 윈도우 )... 9 JetFlash Vault 설정... 9 JetFlash Vault

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

Windows Server 2012

SAS9.2_SAS_Enterprise_Miner_install_guide_single_user_v2

Microsoft PowerPoint - 10Àå.ppt

SBR-100S User Manual

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

메일서버등록제(SPF) 인증기능적용안내서 (Exchange Windows 2000) OS Mail Server SPF 적용모듈 작성기준 Windows Server 2000 Exchange Server 2003 GFI MailEssentials 14 for

쉽게 풀어쓴 C 프로그래밍

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

VPN.hwp

PowerPoint 프레젠테이션

1. efolder 시스템구성 A. DB B. apache - mod-perl - PHP C. SphinxSearch ( 검색서비스 ) D. File Storage 2. efolder 설치순서 A. DB (MySQL) B. efolder Service - efolder

슬라이드 1

*2008년1월호진짜

취약점분석보고서 Simple Web Server 2.2 rc2 Remote Buffer Overflow Exploit RedAlert Team 안상환

uFOCS

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

Cloud Friendly System Architecture

NTD36HD Manual

3) MySQL data 백업백업방법 : dump 파일로저장저장위치 : /backup/mysqldump 백업주기 : 시간별 (/etc/cron.hourly) 또는일별 (/etc/cron.daily) 보관기간 : 7 일백업스크립트 : 아래예제 6-1). 참조 4) 웹데이

8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )

AhnLab_template

PowerPoint 프레젠테이션

untitled

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

Chapter 1

Splentec V-WORM Quick Installation Guide Version: 1.0 Contact Information 올리브텍 주소 : 경기도성남시분당구구미로 11 ( 포인트타운 701호 ) URL: E-M

메일서버등록제(SPF) 인증기능적용안내서 (Exchange Windows 2003) OS Mail Server SPF 적용모듈 작성기준 Windows Server 2003 Exchange Server 2003 GFI MailEssentials 2010 fo

<4D F736F F F696E74202D203130C0E52EBFA1B7AF20C3B3B8AE205BC8A3C8AF20B8F0B5E55D>

untitled

RHEV 2.2 인증서 만료 확인 및 갱신

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

5장. JSP와 Servlet 프로그래밍을 위한 기본 문법(완성-0421).hwp

PowerPoint Presentation

<4D F736F F F696E74202D20B5A5C0CCC5CDBAA3C0CCBDBA5F3130C1D6C2F75F31C2F7BDC32E >

PowerPoint 프레젠테이션

기술문서 작성 XXE Attacks 작성자 : 인천대학교 OneScore 김영성 I. 소개 2 II. 본문 2 가. XML external entities 2 나. XXE Attack 3 다. 점검방법 3 라.

Studuino소프트웨어 설치

슬라이드 1

ISP and CodeVisionAVR C Compiler.hwp

Transcription:

웹애플리케이션취약점 대응가이드

< 목차 > I. 취약점대응방안... 4 1. 입력값검증부재... 4 1.1. SQL Injection... 4 1.2. 업로드파일제한부재... 13 1.3. 코드실행... 24 1.4. XSS(Cross Side Scripting)... 26 1.5. 디렉터리이동... 35 1.6. 소스코드노출... 41 1.7. 사용자입력의길이제한... 42 2. 취약한접근제어... 43 2.1. 사용자인증부재... 43 2.2. 관리자페이지노출... 45 3. 취약한인증 / 세션관리... 50 3.1. 취약한기본계정존재... 50 3.2. 사용자측 Script를이용한인증... 51 3.3. GET/POST 인자를이용한인증... 52 3.4. Cookie를이용한인증... 53 3.5. 인증시비암호화채널사용... 54 4. 취약한정보저장... 59 4.1. 주석을통한민감정보노출... 56 5. 불필요한파일존재... 60 5.1. 백업 / 임시파일존재... 60 5.2. 기본파일존재... 62 5.3. 민감한파일존재... 61 5.4. 디렉터리인덱싱... 64 5.5. 부적절한오류처리... 68 5.6. 불필요한 Method 지원... 71 6. 서버관리... 74 5.1. Linux Patch 취약... 74 5.2. 취약 FTP서비스구동중지... 74 5.3. Apache 버전취약... 74 2 / 77

< 그림목차 > [ 그림 1] 악의적인 SQL Query문삽입... 5 [ 그림 2] having 구문입력으로반환되는에러메시지... 5 [ 그림 3] 게시판에악성스크립트파일업로드... 13 [ 그림 4] 웹서버권한으로시스템명령어실행... 14 [ 그림 5] IIS 실행권한설정... 15 [ 그림 6] 제3자의 Cookie 정보탈취... 26 [ 그림 7] 사용자입력부분에악성코드삽입... 27 [ 그림 8] 수집된 Cookie 인증정보... 27 [ 그림 9] 상대경로를이용한시스템설정파일다운로드... 36 [ 그림 10] 관리자페이지인증을우회한화면... 45 [ 그림 11] IP 주소접근제한... 47 [ 그림 12] 개인정보노출의예... 58 [ 그림 13] 백업파일로인한소스노출... 60 [ 그림 14] phpinfo() 정보노출... 62 [ 그림 18] IIS 디렉터리인덱싱설정... 66 [ 그림 16] 부적절한에러처리로인한정보노출... 68 [ 그림 17] 사용중인메소드확인... 71 [ 그림 18] WebDAV 중지설정... 72 3 / 77

I. 취약점대응방안 1. 입력값검증부재 1.1. SQL Injection 1.1.1 취약점설명 1) 개요 대부분의웹사이트들은사용자로부터입력받은값을이용해데이터베이스접근을위한 SQLQuery를만들고있다. 사용자로그인과정을예로들면, 사용자가유효한계정과패스워드를입력했는지확인하기위해사용자계정과패스워드에관한 SQL Query문을만든다. 이때 SQL injection 기법을통해서정상적인 SQL query를변조할수있도록조작된사용자이름과패스워드를보내정상적인동작을방해할수있다. 이러한비정상적인 SQL Query를이용해다음과같은공격이가능하다. 사용자인증을비정상적으로통과할수있다. 데이터베이스에저장된데이터를임의로열람할수있다. 데이터베이스의시스템명령을이용하여시스템조작이가능하다. 이러한취약점을 SQL Injection 취약점이라고하며, 사용자가데이터입력이가능한수많은웹페이지상에이러한취약점이존재할수있다. 2) 위협사례 사용자인증공격 아래의그림과같이인증을처리하는모듈이입력값에대해적절히검사하지않았을때공격자는비정 상적인 SQL Query 를삽입할수있고이를이용해사용중인데이터베이스에영향을줄수있다. 4 / 77

[ 그림 1] 악의적인 SQL Query 문삽입 다음은 SQL 구문을이용하여인증을처리하는일반적인웹페이지구조를나타낸다. $row = mysql_query (" SELECT 신청인명, 접수번호 from USER_TABLE where 신청인명 =' 첫번째입력값 ' and 접수번호 =' 두번째입력값 '"); if ( $row == 1) // 인증루틴성공 else // 인증루틴실패 이스크립트에공격자가 test 라는신청인명을입력하고인터넷접수번호대신 A' or 'A'='A 이란값을입력 하면아래와같은 SQL Query 가완성된다. SELECT 신청인명, 접수번호 FROM user_table WHERE 신청인명 ="test" AND 접수번호 = 'A' OR 'A'='A' 이경우구문의 WHERE 절은참 AND 거짓 OR 참의 WHERE 절이생성되며무조건참이되어 SQL 구 문은올바른입력값으로처리하게되며공격자는웹인증페이지를쉽게통과할수있게된다. SQL 에러메시지를이용한응용사례 DB서버에서반환되는에러메시지를이용하여테이블및열이름등모든정보를획득할수있다. 먼저공격자는테이블명과열의이름을얻기위해 having 절을이용할수있다. having 절은 select의 where절처럼조건을주는부분으로, where 절과다른점은결과에반드시 group by가와야한다는점이다. 만약 select list에 group by가없을경우특정열을지정하지않아에러가발생하게되며, 반환되는에러메시지에는테이블의첫번째열이름을포함하게된다. 테이블명과열의이름을얻기위해서계정에다음과같은구문을입력할수있다. having 1=1 -- 이러한구문입력으로반환되는메시지는다음과같다. [ 그림 2] having 구문입력으로반환되는에러메시지 5 / 77

메시지를살펴보면 select list 에 group by 절이없어반환된에러메시지로여기에는 users.id 라는정보를 포함하고있다. 이는 users 테이블의 id 열을뜻하는것으로 users 테이블의첫번째열이 id 라는이름을 가지고있는것을확인할수있다. MS-SQL상에서의시스템명령어실행 MS-SQL 데이터베이스를사용하는경우를예를들어보자. 만약데이터베이스접근권한이시스템권한을사용하고있다면 MS-SQL에서기본적으로제공하고있는 xp_cmdshell이라는 Stored Procedure를이용하여시스템명령어를실행할수있다. 예로위의인증페이지에서신청인명에 test, 접수번호에 ; exec master..xp_cmdshell ping 10.10.1.2'-- 값 을입력했다고가정하면 SQL Query 는다음과같이완성될것이다. SELECT 신청인명, 접수번호 FROM user_table WHERE 신청인명 ="test" AND 접수번호 ='; exec master..xp_cmdshell 'ping 10.10.1.2' -- 이 SQL Query 는 SELECT Query 와 xp_cmdshell Query 를 SQL Query 가순차적으로실행되게되며, 마지막 의 -- 문자는이후의모든문자열을주석처리하여문장을완성시켜준다. 1.1.2 조치방안 1) 일반적조치방법 데이터베이스와연동을하는스크립트의모든파라미터들을점검하여사용자의입력값이 SQL injection을발생시키지않도록수정한다. 사용자입력이 SQL injection을발생시키지않도록사용자입력시특수문자 (' " / \ ; : Space -- + 등 ) 가포함되어있는지검사하여허용되지않은문자열이나문자가포함된경우에는에러로처리한다. SQL 서버의에러메시지를사용자에게보여주지않도록설정한다. 공격자는리턴되는에러메시지에대한분석을통하여공격에성공할수있는 SQL Injection 스트링을알아낼수있다. 따라서 SQL 서버의에러메시지를외부에제공하지않도록한다. 웹애플리케이션이사용하는데이터베이스사용자의권한을제한한다. 가능하면일반사용자권한으로는모든 system stored procedures에접근하지못하도록하여웹애플리케이션의 SQL Injection 취약점을이용하여데이터베이스전체에대한제어권을얻거나데이터베이스를운용중인서버에대한접근이불가능하도록한다. php.ini 설정변경 php.ini 설정중 magic_quotes_gpc 값을 On으로설정한다. 6 / 77

; Magic quotes ; ; Magic quotes for incoming GET/POST/Cookie data magic_quotes_gpc = ON ; Off 에서 On 으로변경한다. ; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc. magic_quotes_runtime = Off ;Use Sybase-style magic quotes (escape ' with " instead of \'). magic_quotes_sybase = Off 2) 개발언어별조치방법 (1) 사용자로부터입력받은변수로 SQL 쿼리구문을생성하는 CGI 는입력받은변수를체크하거나 변경하는로직을포함하고있어야한다. (2) 입력받은변수와데이터베이스필드의데이터형을일치시켜야하고, 사용중인 SQL 구문을변 경시킬수있는특수문자가포함되어있는지체크해야한다. (3) 검색부분과같이클라이언트로부터생성된 SQL 구문을받는부분이있다면이를제거해야한 다. ASP 취약한 SQL Injection 예제 7 / 77

prodid = Request.QueryString("productId") Set conn = server.createobject("adodb.connection") Set rs = server.createobject("adodb.recordset") query = "select prodname from products where id = " & prodid conn.open "Provider=SQLOLEDB; Data Source=(local); Initial Catalog=productDB; User Id=dbid; Password=" rs.activeconnection = conn rs.open query If not rs.eof Then response.write " 제품명 " & rs.fields("prodname").value Else response.write " 제품이없습니다 " End If 8 / 77

안전한 SQL Injection 예제 prodid = Request.QueryString("productId") prodid = replace(prodid, "'", "''")' 특수문자제거 prodid = replace(prodid, ";", "") set conn = server.createobject("adodb.connection") set rs = server.createobject("adodb.recordset") query = "select prodname from products where id = " & prodid conn.open "Provider=SQLOLEDB; Data Source=(local); Initial Catalog=productDB; User Id=dbid; Password=" rs.activeconnection = conn rs.open query If not rs.eof Then response.write " 제품명 " & rs.fields("prodname").value Else response.write " 제품이없습니다 " End If PHP addslashes() 함수사용 사용자가입력하는값들 ($_GET, $_POST) 을모두 addslashes() 함수를이용하여처리하여준다. addsishes() 용도 : DB Query와같이인용된부분앞에역슬래쉬를붙여서반환한다. 해당문자에는작은따옴표, 큰따옴표, 역슬래쉬, NULL이있다. SQL Injection 공격을위해서사용한다. - 적용가능한 PHP : PHP 3 이상 취약한 SQL Injection 예제 9 / 77

$query = "SELECT id, password, username FROM user_table WHERE id='$id'"; // 사용자로부터입력받은 id 값을사용자 table에서조회 $result = OCIParse($conn, $query); if (!OCIExecute($result)) echo "<META http-equiv=\"refresh\" content=\"0;url=http://victim.com\">"; // 메인페이지로 redirect OCIFetchInto($result, &$rows);... 중략... 안전한 SQL Injection 예제 $query = sprintf("select id,password, username FROM user_table WHERE id='%s';", addslashes($id)); // id 변수를문자형으로받고, id 변수의특수문자를일반문자로변환한다. // @ 로 php 에러메시지를막는다. $result = @OCIParse($conn, $query); if (!@OCIExecute($result)) error("sql 구문에러 "); exit; @OCIFetchInto($result,&$rows);... 중략... 10 / 77

JSP 취약한 SQL Injection 예제 String sql = "SELECT * FROM user_table" + " WHERE id = " + response.getparameter ("id") + " AND password = " + response.getparameter("password"); Class.forName("org.gjt.mm.mysql.Driver"); conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); stmt = conn.createstatement(); rs = stmt.executequery(query); while(rs.next()) 안전한 SQL Injection 예제 String sql = "SELECT * FROM user_table" + " WHERE id =?" + " AND password =?"; ResultSet rs = null; PreparedStatement pstmt = null; try conn = DBManager.getConnection(); pstmt = conn.preparestatement(sql); pstmt.setstring(1, request.getparameter("id")); pstmt.setstring(2, request.getparameter("password")); rs = pstmt.executequery(); 11 / 77

## 현재반영중인 SQL Injection 예제 ## String sqlpattern = "\\b(?i)(or UNION SELECT DELETE UPDATE INSERT AND FETCH INSERT DROP SHUT DOWN GROUP)([ ]+ [ = ])\\b"; // 사용자입력값에대해서 SQL 구문을변경시킬수있는부분을탐색하여체크 if(suserinput==null) return null; suserinput = suserinput.trim(); suserinput = suserinput.replaceall(sqlpattern,""); suserinput = suserinput.replaceall("--", ""); suserinput = suserinput.replaceall(";", ""); suserinput = suserinput.replaceall("'", "\""); return suserinput; 12 / 77

1.2. 업로드파일제한부재 1.2.1 취약점설명 1) 개요 대부분의홈페이지는사용자들을위하여여러가지종류의게시판을사용하고게시판들은파일을첨부하는기능등다양한기능을가지고있는데이런게시판의첨부파일업로드를기능을악용하여웹서버의권한이노출될수있다. 만일게시판에업로드되는파일의확장자에대한적합성여부를검증하는루틴이존재하지않으면공격자가조작한 Server Side Script 파일을업로드하고업로드된파일이서버상에저장된경로를유추한후이경로를통해 Server Side Script 파일을실행하여쉘을획득할수있고이러한과정을통해웹서버의권한이노출될수있다. 쉘권한획득후, 시스템의명령어를홈페이지를통해실행하고웹브라우저를통해그결과값을보며시스템관리자권한이나인근서버의침입을시도할수있다. 특히, 웹서버데몬의구동이 Unix의 root와같은시스템관리자의권한으로구동될경우, 시스템의관리자권한이공격자에게그대로노출될수있는상당히위험한보안취약점이다. 2) 위협사례 웹서버의게시판에조작된 Server Side Script 파일 Upload [ 그림 3] 게시판에악성스크립트파일업로드 13 / 77

[ 그림 4] 웹서버권한으로시스템명령어실행 1.2.2 조치방안 1) 일반적조치방법 첨부파일업로드기능을통한스크립트업로드및실행을금지시킨다. 게시판첨부파일업로드, 사진업로드모듈등사용자가임의의파일을서버로전송할수있는기능을이용해서공격자가작성한악의적인스크립트를서버에업로드한후, 이를실행시킬수있다면해당서버는물론해당 Application Server와신뢰관계를맺고있는서버들 ( 예, Web DB서버, 내부연동서버등 ) 들이공격당할수있는가능성이있다. 본취약점은게시판업로드모듈뿐아니라그림파일을올리는기능을통해서도발견되고있기때문에, 사용자가파일을업로드할수있는모든모듈에적용된다. - Upload 파일을위한디렉토리에는실행설정을제거 ( 웹서버 ) Upload 파일을위한전용디렉토리를별도생성하여 httpd.conf와같은웹서버데몬설정파일에서실행설정을제거함으로써, Server Side Script가 Upload되더라도웹엔진이실행하지않게환경을설정한다. - 첨부파일의확장자필터링처리사용자가첨부파일의 Upload 시도시, Upload되는파일의확장자를검토하여적합한파일인지를검사하는루틴을삽입하여, 적합한파일의확장자이외의파일에대해서는업로드되지않도록하며, 이런필터링규칙은서버에서구현해야한다. 시스템보안 14 / 77

웹서버구동은반드시관리자권한이아닌일반사용자권한으로구동하도록한다. 외부사용자가첨부 파일을이용하여권한을획득할지라도최소한의권한만을사용할수있도록한다. 업로드된디렉토리 에서실행권한을제거하는방법은임시적이기는하지만소스코드의수정없이간단히수행될수있다. IIS 보안설정 설정 제어판 관리도구 인터넷서비스관리자선택한다. 해당업로드폴더에오른쪽클릭을하고등 록정보 디렉토리 실행권한을 " 없음 " 으로설정한다 [ 그림 5] IIS 실행권한설정 Apache 설정 Apache 설정파일인 httpd.conf 에해당디렉토리에대한문서타입을컨트롤하기위해 Directory 섹션의 AllowOverride 지시자에서 FileInfo 또는 All 추가한다 <Directory "/usr/local/apache"> AllowOverride FileInfo ( 또는 All). <Directory> 파일업로드디렉토리에.htaccess 파일을만들고다음과같이 AddType 지시자를이용, 현재서버에서운영되는 Server Side Script 확장자를 text/html로 MIME Type을재조정하여업로드된 Server Side Script 가실행되지않도록설정한다. 또는 FileMatch 지시자를이용하여 *.ph, *.inc, *lib 등의 Server Side Script 파일에대해서직접 URL 호출을금지시킨다. 15 / 77

<.htaccess> <FilesMatch "\.(ph inc lib)"> Order allow, deny Deny from all </FilesMatch> AddType text/html.html.htm.php.php3.php4.phtml.phps.in.cgi.pl.shtml.jsp 주의사항 1. Apache 서버의경우 AllowOverride 지시자를변경시 apache restart가필요하다. 2. 파일업로드되는디렉토리에운영에필요한 Server Side Script가존재하는지확인한다. 3. 파일다운로드프로그램이아닌직접 URL 호출을통해파일을다운받는경우 FileMatch 지시자를사용하면차단설정한확장자의파일다운로드는거부된다. 2) 개발언어별조치방법 (1) 첨부파일에대한검사는반드시 Server Side Script에서구현해야한다. (2) 첨부파일을체크하여특정종류의파일들만첨부가능하도록하고에러코드를삽입하거나첨부파일을처리하는파일업로드프로그램 (php,php3, cgi, html, jsp 등 ) 에서모든실행가능한파일은첨부할수없도록한다 (3) 프로그램에서필터링을할경우단순히파일이름기준으로점검하지말고확장자명에대하여검사하되대소문자를모두검사하도록한다. (4) 너무작거나큰파일을처리하는로직을포함해야하고, 임시디렉토리에서업로드된파일을지우거나다른곳으로이동시켜야한다. 또한폼에서어떠한파일도선택되지않았다면, 파일업로드에사용되는변수를초기화시켜주어야한다. (5) 웹서버엔진설정시업로드된디렉토리의 Server Side Script 언어의실행권한을제거하고업로드된파일이름을임의로변경하여저장하는것도안전한방법이다. (6) 사용자정보가들어가는파일의경우에는 WEB ROOT 이외의디렉토리에저장하여, URI 호출로접근이되지않도록한다. ASP 취약한파일업로드예 16 / 77

<% Set Up = Server.CreateObject("SiteGalaxyUpload.Form") uploadpath = server.mappath(".") & "\upload\"' 업로드디렉토리 Fname = Up("file1") if Fname <> "" then' 파일첨부가되었으면 filename=mid(fname,instrrev(fname,"\")+1)' 파일이름부분추출 savepath = uploadpath & filename Set fso = CreateObject("Scripting.FileSystemObject") Up("file1").SaveAs(savePath) response.write(savepath & " 저장완료 ") else response.write("error") end if Set Up = nothing %> 안전한파일업로드예 <% Set Up = Server.CreateObject("SiteGalaxyUpload.Form") Path1 = server.mappath(".") & "\upload\" Fname = Up("file1") if Fname <> "" then' 파일첨부가되었으면 if Up("file1").Size > 10240 then' 용량제한 Response.Write " 용량초과 " Response.End end if 17 / 77

if Up("file1").MimeType <> "image" then' 이미지만업로드허용 Response.Write " 이미지파일이아닙니다." Response.End end if Filename=Mid(Fname,InstrRev(Fname,"\")+1)' 파일이름부분추출 ' 중복시에파일이름부분을변경하기위해분리를한다 Farry=split(Filename,".")'. 을기준으로분리 prefname=farry(0)' 파일이름앞부분 extfname=farry(1)' 파일의확장자 ' 저장할전체 path 를만든다, 파일이름을구한다 Path2 = Path1 & Filename savefname=prefname & "." & extfname Set fso = CreateObject("Scripting.FileSystemObject") countno = 0' 파일중복될경우셋팅값 fexist=0' 같은이름의파일존재체크 Do until fexist = 1 If(fso.FileExists(Path2)) Then countno = countno + 1 Path2 = Path1 & prefname & countno & "." & extfname savefname=prefname & countno & "." & extfname else fexist=1 End If Loop Up("file1").SaveAs(Path2) response.write(savefname & " 저장완료 ") else response.write("error") end if Set Up = nothing %> 18 / 77

PHP 취약한파일업로드예 <?php $uploaddir = '/var/www/uploads/'; $uploadfile = $uploaddir. $_FILES['userfile']['name']; if(copy($_files['userfile']['tmp_name'], $uploadfile)) print " 성공적으로업로드되었습니다."; print_r($_files); else print " 파일업로드실패 "; print_r($_files);?> 안전한파일업로드예 <?php $uploaddir = '/var/www/uploads/'; // 파일사이즈가 0byte 보다작거나최대업로드사이즈보다크면업로드를금지시킨다. if($_files['userfile']['name']) if($_files['userfile']['size'] <= 0) // 최대업로드사이즈체크삽입 print " 파일업로드에러 "; exit; // 파일이름의특수문자가있을경우업로드를금지시킨다. if (eregi("[^a-z0-9\._\-]",$_files['userfile']['name'])) print " 파일이름의특수문자체크 "; exit; // 파일확장자중업로드를허용할확장자를정의한다. $full_filename = explode(".", $_FILES['userfile']['name']); $extension = $full_filename[sizeof($full_filename)-1]; 19 / 77

/* PHP의경우확장자체크를할때 strcmp( 확장자,"php3"); 로체크를하게되면 php3 이나 php3는구별을하지못하게되므로 strcasecmp처럼대소문자구별을하지않고비교하는함수를사용한다. 또한. 를기준으로하여확장자가하나로간주하고프로그램을할경우 file.zip.php3 이라고올린다면 zip파일로인식하고그냥첨부가되므로아래와같이제일끝에존재하는확장자를기준으로점검하도록한다. */ $extension= strtolower($extension); if (!( ereg($extension","hwp") ereg($extension","pdf") ereg($extension","jpg")) ) print " 업로드금지파일입니다 "; exit; $uploadfile = $uploaddir. $_FILES['userfile']['name']; if (move_uploaded_file($_files['userfile']['tmp_name'], $uploadfile)) print " 파일이존재하고, 성공적으로업로드되었습니다."; print_r($_files); else print " 파일업로드공격의가능성이있습니다! 디버깅정보입니다 :\n"; print_r($_files);?> 20 / 77

JSP 취약한파일업로드예 <%@ page contenttype="text/html;charset=euc-kr" %> <%@ page import="com.oreilly.servlet.multipartrequest,com.oreilly.servlet.multipart.defaultfilere namepolicy, java.util.*"%> <% String savepath="/var/www/uploads";// 업로드디렉토리 int sizelimit = 5 * 1024 * 1024 ;// 업로드파일사이즈제한 try MultipartRequest multi=new MultipartRequest(request, savepath, sizelimit, new DefaultFileRenamePolicy()); Enumeration formnames=multi.getfilenames();// 폼의이름반환 String formname=(string)formnames.nextelement(); String filename=multi.getfilesystemname(formname);// 파일의이름얻기 if(filename == null) out.print("error"); else filename=new String(fileName.getBytes("8859_1"),"euc-kr"); out.print("user Name : " + multi.getparameter("username") + "<BR>"); out.print("form Name : " + formname + "<BR>"); out.print("file Name : " + filename); catch(exception e) out.print("error"); %> 21 / 77

안전한파일업로드예 <%@ page contenttype="text/html;charset=euc-kr" %> <%@ page import="com.oreilly.servlet.multipartrequest,com.oreilly.servlet.multipart. DefaultFileRenamePolicy, java.util.*"%> <% String savepath="/var/www/uploads";// 업로드디렉토리 int sizelimit = 5 * 1024 * 1024 ; // 업로드파일사이즈제한 try MultipartRequest multi=new MultipartRequest(request, savepath, sizelimit, "euc-kr", new DefaultFileRenamePolicy()); Enumeration formnames=multi.getfilenames(); // 폼의이름반환 String formname=(string)formnames.nextelement(); String filename=multi.getfilesystemname(formname); // 파일의이름얻기 String file_ext = filename.substring(filename.lastindexof('.') + 1); if(!( file_ext.equalsignorecase("hwp") file_ext.equalsignorecase("pdf") file_ext.equalsignorecase("jpg")) ) out.print(" 업로드금지파일 "); if(filename == null) out.print(" 파일업로드실패 "); else filename=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩 out.print("file Name : " + filename); catch(exception e) 22 / 77

## 반영중인파일체크예제 ## // 파일확장자명체크 String FileNamePattern = "(?i)^[ \\w\uac00-\ud7a3]+\\.(jpg gif bmp doc pdf ppt txt xls zip)$"; public static boolean validatefilename(string suserinput) { boolean bvalidcheck = false; if(suserinput==null) return false; suserinput = suserinput.trim(); if ( suserinput.matches(filenamepattern) ) { bvalidcheck = true; } return bvalidcheck; } 23 / 77

1.3. 코드실행 1.3.1 취약점설명 1) 개요 내부적으로시스템명령어를호출하여데이터를처리하거나직접적으로시스템명령어를실행하는애플리케이션에전달되는명령어또는명령어의인자로사용되는입력값을검증하지않아서발생하는것이다. 공격자는시스템명령어를정상적인처리를방해할수있는예외발생특수문자를삽입하여임의적인시스템명령어를실행시킬수있다. 이를통해서특정한파일의정보가노출되거나시스템전체의보안을위협할수있다. 1.3.2 조치방안 1) 일반적인조치방법 - 시스템명령을직접실행시켜데이터를처리하기보다는애플리케이션언어에서지원하는함수들을이용하여필요한기능을구현하는것이권장된다. - 불가피한경우시스템명령을호출하여실행하기위해서전달되는인자에대해서는 허용방식 의입력값검증을반드시실시하여야한다. - 각애플리케이션언어별로코드실행에취약한함수는아래와같다. 구분취약한함수 PHP require() include() eval() preg_replace() (with /e modifier) exec() passthru() `` (backticks) system() popen() Perl open() sysopen() glob() system() '' (backticks) eval() 24 / 77

JAVA System.* ( 특히 System.Runtime) C&C++ system() exec**() strcpy strcat sprintf vsprintf gets strlen scanf fscanf sscanf vscanf vsscanf vfscanf realpath getopt getpass streadd strecpy strtrns [ 표 1] 코드실행에취약한함수 25 / 77

1.4. XSS(Cross Side Scripting) 1.4.1 취약점설명 1) 개요 Cross-Site scripting( 이하 XSS) 취약점은웹페이지가사용자에게입력받은데이터를필터링서버측에서아이디와비밀번호의입력값을검증할때입력된길이값을제한하도록한다. 하지않고그대로동적으로생성된웹페이지에포함하여사용자에게재전송할때발생한다. 자바스크립트처럼클라이언트측에서실행되는언어로작성된악성스크립트코드를웹페이지, 웹게시판또는이메일에포함시켜사용자에게전달하면, 해당웹페이지나이메일을사용자가클릭하거나읽을경우악성스크립트코드가웹브라우저에서실행이된다. [ 그림 6] 제 3 자의 Cookie 정보탈취 이와같이공격자는 XSS 취약점이존재하는웹사이트를이용하여자신이만든악의적인스크립트를 일반사용자의컴퓨터에전달하여실행시킬수있는데, 이러한공격방법을통해사용자쿠키를훔쳐서 해당사용자권한으로로그인하거나브라우저를제어할수있다. 2) 위협사례 JavaScript 를이용한공격 26 / 77

[ 그림 7] 사용자입력부분에악성코드삽입 개인소개와같은많은양의글을작성할수있는부분에 XSS 취약점이존재하여 JavaScript 를이용하여 자신의정보를열람하는사용자의인증정보 (Cookie 정보등 ) 를탈취한다. 위의그림처럼취약점이존재하는부분에적절한악성코드를삽입한후에는다른사용자가해당사용자 의프로필을검색할때아래그림과같이인증정보수집서버에 Cookie 정보가저장되며이를이용하 여다른사용자로접근이가능하다 [ 그림 8] 수집된 Cookie 인증정보 XSS 취약점이특정한유형이있는것은아니지만에러메시지출력부분이나게시판또는사용자의정보를입력해다시보여주는부분등이주로취약한부분이될경우가많다. 특히사용자등이웹사이트의고객불만센터등을이용할수있게해두었을경우 XSS를바로관리자에게보낼수있는경우를종종볼수있다. 27 / 77

<XSS 취약점공격부분 > - CGI 스크립트 - 검색엔진 - HTML Tag가입력가능한게시판 - 사용자에러페이지 이러한코드의다음과같은입력부분에서 XSS 가주로발생한다. 웹사이트를검색할때공격자들이눈 여겨보는부분이다. - URL 파라미터 - Form 인수값들 - 쿠키 - 데이터베이스쿼리 1.4.2 조치방안 1) 사용자입력값에대한 Positive 필터링 XSS 공격으로부터웹응용시스템을방어하는최선의방법은응용시스템차원에서 HTTP 헤더, 쿠키, 쿼리스트링, 폼필드, 히든필드등의모든인자들에대해허용된유형의데이터만을받아들이도록입력값검증을실시하는방법이다. 해당검증방법은현재의컨텐츠를파악하여필터링을수행하려고해서는안된다. 컨텐츠의종류는상당히많으며필터링을우회하기위해인코딩하는방식에도여러가지가있다. 일반적으로공격자는 <script> 태그를이용해공격하므로 <script> 문자열이들어오면 <xxscript> 나다른문자로변환해스크립트태그가실행되지않도록설정해야한다. 공격자는 <script> 태그외에다양한기법을이용해공격하기때문에아래표와같이필터링을할것들을정해서막는 negative defence 가아닌입력가능한문자만정한뒤다른문자가들어왔을때전부막는 positive defence 를하는것이좋다. 입력값의필터링은명시적으로허용되는것을지정하여받아들이는방식 (positive Filtering) 의보안정책을강하게권고한다. 허용되지않는것을지정하는방식 (negative Filtering) 의보안정책이나공격패턴 ( 시그너처 ) 에기반한보안정책은유지보수가힘들며불완전하다. HTML 태그 <object> <iframe> <link> 28 / 77

<applet> <embed> <script> <form> <div> <a href= javascript:[code] > <img src= javascript:[code] > <img dynsrc="javascript:[code]"> <img lowsrc="javascript:[code]"> <input type="image" src="javascript:[code]"> <xml src= javascript:[code] > <body background="javascript:[code]"> <meta http-equiv="refresh" content="0;url=javascript:[code]"> javascript:, vbscript: urn:schemas-microsoft-com:time onabort=, onblur=, onchange=, onclick=, ondblclick=, ondragdrop=, onerror=, onfocus=, onkeydown=, onkeypress=, onkeyup=, onload=, onmousedown=, onmouseout=, onmouseover=, onmouseup=, onmove=, onreset=, onresize=, onsubmit=, onunload= 등의이벤트 [ 표 2] XSS 공격에사용되는태그 2) 개발언어별유용한함수들 ASP Server.HTMLEncode() 메소드를이용하여특수문자를 Entity 형태로변경한다. - 용도특정문자열에대한 HTML encoding을수행한다. 사용자가입력한값으로 HTML 페이지를구성하기전에사용하면 Cross-Site Scripting 공격에효과적이다. - 적용가능한 IIS IIS 5.0이상 - 사용법 <%= Server.HTMLEncode("<script>alert(document.cookie);</script>") %> - 결과 <script>alert(document.cookie);</script> 29 / 77

PHP strip_tags() 함수를이용하여문자열로부터 HTML 태그와 PHP 태그를제거한다. - 용도사용자가입력한값을 HTML 화면에출력할경우사용하여 Cross-Site Scripting 공격에대비할수있다. - 적용가능한 PHP 버전 PHP 3.0.8 이상 - 사용법 A. strip_tags('<script>'); : 모든 HTML에서 <script> 태그를제거한다. htmlspecialchars() 함수를사용하는것보다 strip_tags() 나 strip_replace() 함수를사용하여처리하는것이보다바람직하다. 3) 개발언어별조치방법 사용자입력으로사용가능한문자들을정해놓고, 그문자들을제외한나머지모든문자들을필터링한 다. 필터링해야하는대상은 GET 질의문자열, POST 데이터, 쿠키, URL, 그리고일반적으로브라우저와 웹서버가주고받는모든데이터를포함한다. 아래는특수문자에대한 Entity 형태를표시한것이다. 변경전 < > ( ) # & 변경후 < > &#40 &#41 &#35 &#38 [ 표 1] 특수문자변경 - 게시판에서 HTML 포맷을사용할수없도록설정한다. - 필요한경우모든 HTML 을사용하지못하게설정후필요한 HTML tag 만쓸수있도록설정한 다. 30 / 77

ASP 취약한프로그래밍예 <% Set objdbconn = Server.CreateObject("ADODB.Connection")' 게시물읽기 Set objrs = Server.CreateObject("ADODB.RecordSet") objdbconn.open "board", "user", "passwd" query = "SELECT id, name, memo FROM board_tbl WHERE id=1" objrs.open query, objdbconn memo = objrs("memo") Response.write " 게시물내용 -" & memo & "<BR>"' DB 에서게시판의내용출력 안전한프로그래밍예 If use_html Then' HTML tag 를사용하게할경우부분허용 memo = Server.HTMLEncode(memo) 'HTML tag 를모두제거 ' 허용할 HTML tag만변경 memo = replace(memo, "<p>", "<p>") memo = replace(memo, "<P>", "<P>") memo = replace(memo, "<br>", "<br>") memo = replace(memo, "<BR>", "<BR>") Else' HTML tag를사용하지못하게할경우 memo = Server.HTMLEncode(memo)' HTML encoding 수행 memo = replace(memo, "<", "<") memo = replace(memo, ">", ">") End If Response.write " 게시물내용 -" & memo & "<BR>" 31 / 77

PHP 취약한프로그래밍예 $query = "SELECT id, name, memo FROM board_tbl WHERE id=1";// 게시물읽기 $result = mysql_query($query, $connect); while($row = mysql_fetch_array($result)) $name = $row[name]; $memo = $row[memo]; echo " 게시물내용-". $memo. "<BR>\n";// DB에서게시판의내용을출력 안전한프로그래밍예 $use_tag = "img,font,p,br";// 허용할 HTML tag if($use_html == 1) // HTML tag 를사용하게할경우부분허용 $memo = str_replace("<", "<", $memo);// HTML TAG 를모두제거 $tag = explode(",", $use_tag); for($i=0; $i<count($tag); $i++) // 허용할 TAG만사용가능하게변경 $memo = eregi_replace("<".$tag[$i]." ", "<".$tag[$i]." ", $memo); $memo = eregi_replace("<".$tag[$i].">", "<".$tag[$i].">", $memo); $memo = eregi_replace("</".$tag[$i], "</".$tag[$i], $memo); else // HTML tag 를사용하지못하게할경우 // $memo = htmlspecialchars($memo); // htmlspecialchars() 사용시일부한글이깨어지는현상이발생할수있음 $memo = str_replace("<", "<", $memo); $memo = str_replace(">", ">", $memo); echo " 게시물내용 -". $memo. "<BR>\n"; 32 / 77

JSP 취약한프로그래밍예 Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); Statement stmt = conn.createstatement(); ResultSet rs=null; String query = "SELECT memo FROM board_tbl WHERE id=1"; rs = stmt.executequery(query); String memo = rs.getstring(1); out.print(" 게시물내용-" + memo + "<BR>"); 안전한프로그래밍예 if(use_html) // HTML tag 를사용하게할경우부분허용 memo = memo.replaceall("<","<");//html tag 를모두제거 memo = memo.replaceall(">",">"); // 허용할 HTML tag만변경 memo = memo.replaceall("<p>", "<p>"); memo = memo.replaceall("<p>", "<P>"); memo = memo.replaceall("<br>", "<br>"); memo = memo.replaceall("<br>", "<BR>"); else // HTML tag 를사용하지못하게할경우 memo = memo.replaceall("<","<"); memo = memo.replaceall(">",">"); out.print(" 게시물내용 -" + memo + "<BR>"); 33 / 77

String xsspattern = "<(/)?([a-za-z]*)(\\s[a-za-z]*=[^>]*)?(\\s)*(/)?>"; public static String validatexss(string suserinput){ if(suserinput==null) return null; suserinput = suserinput.trim(); suserinput = suserinput.replaceall(xsspattern,""); suserinput = suserinput.replaceall("\\\"", ""); suserinput = suserinput.replaceall("\\\'", ""); suserinput = suserinput.replaceall("<", "<"); suserinput = suserinput.replaceall(">", ">"); suserinput = suserinput.replaceall("set-cookie",""); return suserinput; } public static String scriptreplace(string htmlstr) { if(htmlstr == null) return ""; Pattern p = Pattern.compile("(?i)<script"); Matcher m = p.matcher(htmlstr); return m.replaceall("<x-script"); } public static String iframereplace(string htmlstr) { if(htmlstr == null) return ""; Pattern p = Pattern.compile("(?i)<iframe"); Matcher m = p.matcher(htmlstr); return m.replaceall("<x-iframe"); } public static String embedreplace(string htmlstr) { if(htmlstr == null) return ""; Pattern p = Pattern.compile("(?i)<embed"); Matcher m = p.matcher(htmlstr); return m.replaceall("<x-embed"); } public static String inputreplace(string htmlstr) { if(htmlstr == null) return ""; Pattern p = Pattern.compile("(?i)<input"); Matcher m = p.matcher(htmlstr); return m.replaceall("<x-input"); } 34 / 77

1.5. 디렉터리이동 1.5.1 취약점설명 1) 개요 홈페이지상에서파일을다운받거나업로드시키는경우 cgi, jsp, php, php3 등의프로그램들을사용한다. 만일이러한 cgi, jsp, php, php3 등의프로그램에서입력되는경로를체크하지않는경우, 임의의문자 (../.. 등 ) 나주요파일명의입력을통해웹서버의홈디렉토리를벗어나서임의의위치에있는파일을열람하거나다운받는것이가능할수있다. 2) 위협사례 상대경로를이용한파일접근상대경로란./,../ 와같이논리적단위로이루어진디렉토리경로를말한다. 파일의이름이나경로를다루는웹애플리케이션에서이러한논리적인경로를적절히처리하지못하여웹애플리케이션이설치된디렉토리를상회하여시스템파일이나지정하지않은다른파일에접근할수있다. http://test.site.com/board/download.jsp?num=203&filename=upload/azip.exe 다운 로드파일위치및파일이름 위와같이파일을다운로드받아야하는 URL 의경우공격자는 filename 변수 를../../../../../../../winnt/win.ini 와같이상대경로를이용, 치환해서시스템내부의파일을불법으로획득 할수있다. http://test.site.com/board/download.jsp?num=203&filename=../../../../../../../winnt/w in.ini c:\winnt\win.ini 파일을다운로드 35 / 77

[ 그림 9] 상대경로를이용한시스템설정파일다운로드 파일을다루는웹애플리케이션은특히파일의이름을변수로주거나, 이에대한입력값을사용자로부터입력받을때혹은관련웹애플리케이션으로부터파일이름변수를넘겨받을때해당변수에상대경로가포함되어있는지소스레벨에서검사를해야한다. 이를테면파일의이름에../../../../../../../ 혹은.\..\..\..\..\..\ 등의상대경로가포함되어있을때에는실행을중단하여주요파일로의불법적인접근을차단해야한다. 1.5.2 조치방안 1) 서버별조치방법 (1) 파일다운로드의취약성은주로파일의이름을조작하는데서비롯한다. 다운로드파일의이름을데이터베이스에저장하고다운로드수행시요청파일이름과비교하여적절한지확인하여사용자가조작할수있는변수를제거하는것이바람직하다. 또한다운로드위치는지정된데이터저장소를고정하여사용하는것이바람직하다. (2) 프로그램내에서파일을다운받을수있는디렉토리를특정디렉토리로한정하고이외의다른디렉토리에서는파일을다운받을수없도록프로그램을수정한다. (3) PHP를사용하는경우 php.ini 에서 magic_quotes_gpc 를 On으로설정하여.\./ 와같은역슬래시문자에대해대응도가능하다. 2) 개발언어별조치방법 36 / 77

(1) 파일다운로드를할수있는지권한체크를다운로드하기직전에체크한다. (2) 중요파일의경우파일자체를 URI 를통해직접접근할수없는곳에파일을두고, 스트림을 읽어다운로드받을수있도록한다. ASP 취약한디렉터리이동예 <% file = Request.Form ("file")' 파일이름 Response.ContentType = "application/unknown"'contenttype 선언 Response.AddHeader "Content-Disposition","attachment; filename=" & file Set objstream = Server.CreateObject("ADODB.Stream")'Stream 이용 objstream.open objstream.type = 1 objstream.loadfromfile Server.MapPath("./upfiles/")&"\"& file ' 서버절대경로 download = objstream.read Response.BinaryWrite download Set objstream = nothing' 객체초기화 37 / 77

안전한디렉터리이동예 <% file = Request.Form ("file")' 파일이름 Response.ContentType = "application/unknown"'contenttype 선언 Response.AddHeader "Content-Disposition","attachment; filename=" & file Set objstream = Server.CreateObject("ADODB.Stream")'Stream 이용 strfile = Server.MapPath("./upfiles/") & "\" & file ' 서버절대경로 strfname=mid(fname,instrrev(file,"\")+1) ' 파일이름추출,..\ 등의하위경로탐색은제거됨 strfpath = Server.MapPath("./upfiles/") & "\" & strfname ' 웹서버의파일다운로드절대경로 If strfile = strfpath Then' 사용자가다운받는파일과웹서버의파일다운로드경로가맞는지비교 objstream.open objstream.type = 1 objstream.loadfromfile strfile download = objstream.read Response.BinaryWrite download End If Set objstream = nothing' 객체초기화 %> 38 / 77

PHP 취약한디렉터리이동예 $dn_path = "/var/www/data/$up_dir/$dn_file_name"; // 파일전송루틴 header("content-type: doesn/matter"); header("content-length: ".filesize("$dn_path")); header("content-disposition: filename=".$dn_file_name]); header("content-transfer-encoding: binary\r\n"); header("pragma: no-cache"); header("expires: 0"); 안전한디렉터리이동예 if (preg_match("/[^a-z0-9_-]/i",$up_dir)) print " 디렉토리에특수문자체크 "; exit; if (preg_match("/[^\xa1-\xfea-z0-9._-] \.\./i",urldecode($dn_file_name))) print " 파일이름에특수문자체크 "; exit; $dn_path = "/var/www/data/$up_dir/$dn_file_name"; if (!file_exists($dn_path)) print " 파일이존재여부체크 "; exit; // 파일전송루틴 header("content-type: doesn/matter"); header("content-length: ".filesize("$dn_path")); header("content-disposition: filename=".$dn_file_name]); header("content-transfer-encoding: binary\r\n"); header("pragma: no-cache"); header("expires: 0"); 39 / 77

JSP 취약한디렉터리이동예 String UPLOAD_PATH= "/var/www/upload/"; String filename= response.getparameter("filename"); String filepathname = UPLOAD_PATH + filename; // 파일전송루틴 response.setcontenttype("application/unknown; charset=euc-kr"); response.setheader("content-disposition","attachment;filename=" + filename + ";"); response.setheader("content-transfer-encoding:", "base64"); BufferedInputStream in = new BufferedInputStream(new FileInputStream(filepathname)); 안전한디렉터리이동예 String UPLOAD_PATH= "/var/www/upload/"; String filename= response.getparameter("filename"); String filepathname = UPLOAD_PATH + filename; if(filename.equalsignorecase("..") filename.equalsignorecase("/")) // 파일이름체크 return 0; // 파일전송루틴 response.setcontenttype("application/unknown; charset=euc-kr"); response.setheader("content-disposition","attachment;filename=" + filename + ";"); response.setheader("content-transfer-encoding:", "base64"); try BufferedInputStream in = new BufferedInputStream(new FileInputStream(filepathname));... catch(exception e) // 에러체크 [ 파일존재유무등 ] 40 / 77

1.6. 소스코드노출 1.6.1 취약점설명 1) 개요 파일을처리하는애플리케이션이사용자측에서전송되어오는입력값을신뢰하기때문에발생하는 것이다. 공격자는애플리케이션의입력값으로애플리케이션자신을파일명으로요청, 해당파일의소 스정보를볼수있다. 1.6.2 조치방안 1) 일반적인조치방법 - 파일명이없거나요청이자기자신일때를대비하여예외처리를수행하여임의적인파일의다운로드 를차단한다. 41 / 77

1.7. 사용자입력의길이제한 1.7.1 취약점설명 1) 개요 사용자를통해입력받은값의길이에제한을두지않으면, 다양한공격을시도할수있다. 따라서 공격의시도를줄이기위해사용자가입력하는값에길이의제한을두도록한다. 1.7.2 조치방안 1) 일반적인조치방법 - HTML 의태그속성중 MaxLength 를통해사용자의입력을제한한다. - 서버로전송하기바로직전에, 사용자입력값에대해검증 ( 길이제한, 유효성 ) 을한다. 42 / 77

2. 취약한접근제어 2.1. 사용자인증부재 2.1.1 취약점설명 1) 개요 인증과권한이필요한애플리케이션에서이를요청한사용자에대해인증여부와적정한권한의소유여부를검증하지않아발생하는것이다. 공격자는유추또는애플리케이션의분석을통해획득한정보를바탕으로인증과권한검증이부재한애플리케이션에접근할수있다. 이를통해 공지사항 과같은특정권한이필요한게시판에임의적인글을게시하거나, 회원정보와같은민감한정보들이노출될수있다. 2.1.2 조치방안 1) 일반적인조치방법 - 회원게시판, 관리자페이지등로그인후에접근가능한애플리케이션은실행시에해당요청이정상적인인증을받은사용자에의한것인지와인증된사용자가요청한작업을수행할수있는권한자인지를반드시검사해야한다. - 해당애플리케이션에대하여 접근통제표 (Access Control Matrix) 를작성하고비정상적인사용자가할당되지않은권한을사용할있는지를검증한다. 이때접근통제와관련된주제들은아래와같은것들이존재한다. - 고객서비스의경우사용자인증을통해특정페이지를볼수있다면, 인증을위해넣은입력값을넣어체크하였는데몇회이상실패가난경우지속적인 Brute Force 공격을방어하기위해연속입력을제한해야한다. ( 그림문자등을도입 ) [ 그림문자예시 ] - 관리자페이지의경우사용자인증시연속적으로몇회실패시에는계정을잠금으로써무제한 Brute Force 공격을방어한다. 43 / 77

구분설명취약한 ID 입력받은값들이현재사용자에게허용된적절한값인지를검증해야한다. 강제접근내부 URL을접속하기위해실시하는보안검사가단순히페이지우회로통과가능해서는안된다. 디렉터리이동상대경로와같이특정 URL이나파일에액세스하는데사용되는값들을허용해서는안된다. 파일허가권환경설정파일, 디폴트예제파일등과같은파일에대해서는접근을금지해야하며, 불필요한허가권을부여해서는안된다. 사용자측 HTTP 헤더, 메타태그등을사용하여민감한정보가담긴페이지가사용자의캐쉬브라우저에캐쉬되지않도록한다. 44 / 77

2.2. 관리자페이지노출 2.2.1 취약점설명 1) 개요 접근통제는특정사용자들에게만웹콘텐츠나기능들에접근할수있도록허가해주는것으로일반적으로관리자페이지에대한접근통제가필요하다. 관리자페이지는웹서비스의사용자나데이터, 콘텐츠를손쉽게관리하기위한목적으로다양한기능과권한을갖고있고이는홈페이지의운영에매우중요한역할을하고있으므로일반사용자는인증을통과하지못하도록할뿐아니라일반사용자가관리자페이지를볼수없도록해야한다. 그러나일반적으로추측하기쉬운 URL(ex: /admin, /manager) 을사용하고있어, ID/ 패스워드에대한크랙또는접근허가정책에대해요청하는부분의정보를변경함으로써접근이가능한경우가많다. 웹관리자의권한이노출될경우홈페이지의변조뿐만아니라취약성정도에따라서웹서버의권한까지도노출될위험성이존재한다. 2) 위협사례 관리자페이지인증우회대부분의관리자페이지는 http://www.test.com/admin 등과같이쉽게추측이가능하다. 또인증과정이존재하더라도 SQL Injection, JavaScript 변조등의취약점을이용하여인증과정을우회하여웹관리자권한을획득할수있다. [ 그림 10] 관리자페이지인증을우회한화면 2.2.2 조치방안 45 / 77

일반사용자의접근이불필요한관리자로그인페이지주소를유추하기어려운이름으로변경한다. 중요한정보를가진웹서버의특정페이지들은관리자또는특정사용자만접근할필요가있다. 이러한주요페이지들은웹서버에서적절한설정을통하여특정사용자만접근이가능하도록사용자접근제한을할수있다. 1) 웹서버조치방법 별도의네트워크범위로 IP 레벨의접근권한을설정하고웹관리자메뉴의접근을제한하며웹관리자 의인터페이스는특히, SSL 기술을이용하여 HTTP over SSL 과같은 Data Transaction 암호화를반드시적 용해야한다. 가능하다면, VPN 과같은네트워크차원의별도보안시스템의설치도고려할필요가있다. 또한, 관리자계정으로는외부사이트에서접근하는것을허용하지않는것이바람직하다. 대부분의홈페이지에서관리자계정에많은권한을부여하고있는경우가많고, 일반사용자용게시판과는달리관리자용게시판의경우에는별도관리가안되고있는경우가많아관리자계정권한획득시홈페이지시스템의권한획득으로이루어지기쉽기때문이다. 따라서관리자페이지의경우, 사내 IP에서만접근이가능하도록설정하고, 만일외부관리자의접근이반드시필요한경우라면, 사이트관리권한을외부로열어주지않고도가능한 VPN 기술을사용하면외부관리자가회사내부 ( 혹은사이트 ) 네트워크로접근할수있으며, 관리자는보호된백엔드연결을통해사이트에접근할수있다. (1) admin, manager 등과같이추측하기쉬운디렉토리명이나파일명을사용하지않는다 http://www.abc.com/admin.html http://www.abc.com/admin_main.html http://www.abc.com/admin/index.html http://www.abc.com/admin/login.html http://www.abc.com/master.html http://www.abc.com/master/index.html (2) 관리자페이지의경우, 관리자호스트 IP 만접근가능하도록설정한다 IIS 웹서버아래의방법으로 [ 관리자페이지 ] 접근을제한한다. (1) 설정 제어판 관리도구 인터넷서비스관리자선택한다. (2) 해당관리자페이지폴더에오른쪽클릭을하고등록정보 디렉토리보안 IP 주소및도메인이름제한 편집버튼을클릭한다. (3) 액세스거부를선택하고추가버튼을클릭하여관리자호스트IP 또는서브넷을등록한다. 46 / 77

[ 그림 11] IP 주소접근제한 Apache 웹서버 Apache 웹서버의환경설정파일인 httpd.conf 파일의 Directory 섹션의 AllowOverride 지시자에서 AuthConfig 또는 All 추가하여.htaccess를통하여사용자계정, 사용자패스워드를등록한사용자만접근이가능하도록하고관리자디렉토리 (admin) 에대해특정 IP에대해서만접근이가능하도록하기위해서다음과같이설정한다. 47 / 77

<Directory /home/www/admin/> AllowOverride AuthConfig ( 또는 All) Order deny, allow Deny from all Allow from 10.10.100.7 10.10.2.1/24 </Directory> # 먼저접근을제어하고자하는디렉토리에대한상위디렉토리정의에 # AllowOverride 부분이 'All', 'AuthConfig', 'FileInfo' 등으로설정되어있어야한다. <Directory " 접근을제어하고자하는디렉토리 ">.. AllowOverride FileInfo AuthConfig Limit.. </Directory>.. AccessFileName.htaccess <Files ~ "^\ht"> Order Allow, deny Deny from all </Files> <.htaccess> AuthName " 인증이필요한관리자페이지입니다." AuthType Basic AuthUserFile /home/www/admin/.htaccess AuthGroupFile /dev/null require valid-user Order deny,allow Deny from all Allow from 10.10.100.7 10.10.2.1/24 관리자페이지와같이인증이필요한디렉토리에.htaccess 파일을만들고 admin 계정의패스워드를다 음과같이설정한다. 위와같이설정후 apache/bin/htpasswd 를이용하여사용자정보파일 (.htpasswd) 을 생성한다. 48 / 77

# ~apache/bin/htpasswd c /home/www/admin/.htpasswd [ 사용자명 ] New password: ******* Re-type new password: ******** Adding password for user [ 사용자명 ] # 주의사항 1 Apache 서버의경우 AllowOverride 지시자를변경시 apache restart가필요하다. 2 관리자페이지의디렉토리명을변경시웹프로그램에서관리자디렉토리의경로명을지정하고있는경우웹프로그램또한수정해야한다 3 관리자페이지웹서버인증설정시관리자디렉토리에는일반사용자의접근이필요한파일이존재하지않아야한다. 2) 개발언어별조치방법 웹관리자메뉴의접근을특정네트워크대역으로제한하여, IP Address까지도인증요소로체크하도록웹관리자사용자인터페이스를개발하고, 관리자인증후접속할수있는페이지의경우해당페이지주소를직접입력하여들어가지못하도록관리자페이지각각에대하여관리자인증을위한세션관리를해야한다. (1) 접근통제정책을구현하고있는코드는구조화, 모듈화가되어있어야한다. (2) 접근제어가필요한모든페이지에통제수단 ( 로그인체크및권한체크 ) 을구현해야한다. 특히, 하나의프로세스가여러개의페이지또는모듈로이루어져있을때권한체크가누락되는경우를방지하기위해서공통모듈을사용하는것을권장한다. (3) 인증과정을처리하는부분에 Client Side Script(Javascript, VBScript 등 ) 을사용하면사용자가임의로수정할수있으므로 Server Side Script(PHP, ASP, JSP 등 ) 를통하여인증및필터링과정이수행되어야한다. (4) 권한이없는페이지의경우 URL을직접치고들어가더라도접근이되지않도록권한여부를서버에서확인해야한다. 49 / 77

취약한프로그래밍예 <HTML> <HEAD><TITLE> 관리자페이지 </TITLE> <SCRIPT language="javascript > function getcookie(name) var cname = name +"="; var dc = document.cookie; if(dc.length > 0) begin = dc.indexof(cname); if(begin!= -1) begin += cname.length; end = dc.indexof(";", begin); if(end == -1) end = dc.length; retrun unescape(dc.substring(begin, end)); return null; function getvalue(element) var value = getcookie(element.name); if(value!= null) element.value = value; </SCRIPT> </HEAD> <BODY> <SCRIPT language="javascript > var auth; auth = getcookie("logged_in"); if(auth!= 1) // 인증성공쿠키가없을경우 Main Page 로이동 window.location = "http://victim.com/login.html"; </SCRIPT> 50 / 77

ASP 안전한프로그래밍예 <% If myfunc_userauth(userid, userpw) <> 1 Then 'DB에서사용자인증을처리 Response.write " 인증실패 " Else If Request.ServerVariables("REMOTE_ADDR") <> "10.10.1.1" Then' 관리자 IP 확인 Response.write " 관리자 IP가아닙니다." Response.write " 인증실패 LogSave(userid, user_ip, 0)' 접속에실패한 ID 및 IP 기록 Else Session("logged_in") = 1' 인증에성공했을경우 logged_in 에 1의값을셋팅 Session("userid") = userid Session("user_ip") = Request.ServerVariables("REMOTE_ADDR") LogSave($userid, $user_ip)' 접속에사용한 ID 및 IP 기록... 중략... End If End If %> 51 / 77

PHP 안전한프로그래밍예 <?PHP @session_start(); // 세션데이터를초기화 if(!myfunc_userauth($userid, $userpw) $_SERVER["REMOTE_ADDR']!= "10.10.1.1") //DB 에서사용자인증을처리, 관리자 IP인지확인 print " 인증실패 "; LogSave(userid, user_ip, 0)' 접속에실패한 ID 및 IP 기록 exit;// 인증실패시종료 // 인증에성공한경우처리해야되는부분 if (!session_is_registered("logged_in")) $logged_in = 1;// 인증에성공했을경우 logged_in 에 1의값을셋팅 $user_ip = $_SERVER["REMOTE_ADDR"]; session_register("logged_in");// 인증결과저장 session_register("userid");// 사용자 ID를저장 session_register("user_ip");// 사용자 IP를저장 LogSave($userid, $user_ip);// 접속한사용자 ID 및 IP 기록... 중략... 52 / 77

JSP 안전한프로그래밍예 <%@ page contenttype="text/html;charset=euc-kr" %> <%@ page import="java.util.* " %> <%@ page import="java.sql.* " %> <% //HttpSession session = request.getsession(true); String user_ip = request.getremoteaddr(); // form 에서사용자 id와사용자 password를아래변수로전달 if(!myfunc_userauth(userid, userpw)!user_ip.equals("10.10.1.1")) //DB 에서사용자인증을처리, 관리자 IP인지확인 out.println " 인증실패 "; LogSave(userid, user_ip, 0)' 접속에실패한 ID 및 IP 기록 else // 인증에성공한경우처리해야되는부분 session.putvalue("logged_in","logok"); session.putvalue("userid",userid); session.putvalue("user_ip", user_ip); LogSave(userid, user_ip);// 접속한사용자 ID 및 IP 기록... 53 / 77

3. 취약한인증 / 세션관리 3.1. 취약한기본계정존재 3.1.1 취약점설명 1) 개요 admin, administrator, manager, guest, test, scott 와같이디폴트계정을재설정없이사용하거나추측이용이한계정의사용또는테스트목적의임시계정에대해사용후미삭제등으로인하여공격자는관리자권한을획득할수있으며패스워드가숫자, 단어와같이취약하게운영될경우악의적공격의목표가될수있다. 테스트계정의경우관리자계정의권한을갖고있는경우가많으므로, 취약한패스워드를사용중이라면매우심각한상태라고할수있다 3.1.2 조치방안 1) 일반적인조치방법 다음과같은취약한아이디및패스워드는사용하여서는안되며시스템및어플리케이션에설치시존 재하는디폴트계정및임시계정은삭제하거나패스워드를변경하여야한다. 취약한계정명 취약한패스워드 admin, administrator, manager, guest, test, scott 등 Abcd, 1234, 1111, test, password, blank 패스워드, ID와동일한패스워드, 디폴트패스워드등 [ 표 3] 취약한계정및패스워드 54 / 77

3.2. 사용자측 Script 를이용한인증 3.2.1 취약점설명 1) 개요 인증절차의일부분을사용자측에서 JavaScript 등을이용하여수행함으로써발생하는것이다. 공격자 는서버측에서전송되어오는 JavaScript 를제거하거나반환값을변경하여인증을우회할수있다. 이 를통해서사용자또는애플리케이션의주요정보가노출되거나권한이노출될수있다. 3.2.2 조치방안 1) 일반적인조치방법 - JavaScript 를이용하여사용자측에서검증하는것은서버측의부하를줄이기위한수단으로사용될 수있을뿐그이상으로사용되어서는안된다. - 인증처리와검증은서버측에서반드시실시해야한다. 55 / 77

3.3. GET/POST 인자를이용한인증 3.3.1 취약점설명 1) 개요 사용자세션정보를유지하지않는 HTML의프로토콜의한계점을보완하기위한방법으로애플리케이션의 GET/POST 인자를인증토큰으로신뢰하기때문에발생하는것이다. 공격자는 GET이나 POST로서버측에전달되는인증토큰을조작하여인증을우회할수있다. 이를통해서사용자또는애플리케이션에포함되어있는사업정보가노출되거나사용자또는관리자의권한이노출될수있다. 3.3.2 조치방안 1) 일반적인조치방법 - 사용자정보, 콘텐츠의가격등인증또는애플리케이션의주요한연산을처리하기위해사용되는중요한값은클라이언트에서전송되어오는값을신뢰해서는안된다. - GET과 POST 인자의입력값은다양한공격에대해서입력값검증을반드시실시하여야한다. - GET/POST를통해중요한개인정보가전달된다고하면 SSL 적용및암호화를통해사용자의입력값을보호해야한다. 56 / 77

3.4. Cookie 를이용한인증 3.4.1 취약점설명 1) 개요 Cookie는사용자의정보가유지되지않는 HTTP 프로토콜의단점을해결하기위해서사용되는기법이다. 하지만애플리케이션에서주요한정보를클라이언트측의 Cookie 값으로저장하거나클라이언트측에서전송되어오는데이터를신뢰하는것은보안의위험요소가된다. 공격자는웹브라우저와애플리케이션간에오가는데이터를수정할수있다. 이를통해사용자의 Cookie 정보를수정, 타사용자또는관리자의정보또는권한이도용될수있다. 3.4.2 조치방안 1) 일반적인조치방법 - 인증과권한에사용되는주요한정보는사용자측에해당정보가저장되는 Cookie가아닌서버측에해당정보가저장이되는 SessionID로저장한다. - Cookie로클라이언트측에저장되는정보는암호화등을통하여해당정보를사용자측에서열람할수없도록차단한다. 57 / 77

3.5. 인증시비암호화채널사용 3.5.1 취약점설명 1) 개요 개인정보를암호화하지않고평문으로전송처리하여도청을통해노출되는취약점으로암호화를통해 위험을최소화할수있다. 웹상의데이터통신은대부분텍스트기반으로이루어지고있으며이는간 단한도청을통해쉽게개인정보의절취및도용이가능해진다. [ 그림 12] 개인정보노출의예 [ 그림 23] 와같이평문으로전송되는페이지에계정 / 패스워드와같은중요정보가포함되어있을경우 공격자는손쉽게사용자의중요정보를획득할수있게된다. 3.5.2 조치방안 웹상에서의전송정보를제한하여불필요한비밀번호, 주민등록번호, 계좌정보와같은중요정보의전송을최소화해야하며, 중요정보에대해서는반듯이 SSL 등의암호화를사용하여도청으로부터의위험을없애야한다. 또한쿠키와같이조작이가능한방식이아닌세션을사용하여공격자에의한데이터위 / 변조를차단해야한다. 58 / 77

4. 취약한정보저장 4.1. 주석을통한민감정보노출 4.1.1 취약점설명 1) 개요 잘못된주석처리나과도한주석처리도인해서민감한정보가노출된다. 공격자는자동화된도구또는 HTML 소스보기 를통해서이를획득할수있으며, 이를통해서애플리케이션의작동원리나주요한 정보가노출될수있다. 4.1.2 조치방안 1) 일반적인조치방법 - 애플리케이션을개발할때주석을통해서주요한정보를남겨놓는것은디버깅, 추후업데이트등을고려하여바람직한것이다. - 애플리케이션의역할, 수행과정, 디버깅정보, 애플리케이션소스가주석을통해서노출될경우이를통해서중요한정보가노출될수있다. 따라서주석정보는 HTML 페이지를통해서사용자에게전달되지않도록애플리케이션개발언어에남기도록한다. 59 / 77

5. 불필요한파일존재 5.1. 백업 / 임시파일존재 5.1.1 취약점설명 1) 개요 개발과정에서생긴백업파일은웹상에쉽게노출될수있으며.bak,.org,.old,.zip,.log 등사용자임의의파일명을사용하게된다. 이러한파일명은웹서버설정에서 php, asp, jsp등해당스크립트를해석하도록설정이되있지않은경우가많아웹상에서소스가그대로노출될수있다. 윈도우에서웹파일을수정하였을경우백업파일이자동적으로생성되는경우가있으며이때관리자가 이러한파일의삭제를잊거나인지하지못할수있다. [ 그림 13] 백업파일로인한소스노출 이러한백업파일의노출은웹서버 / 웹어플리케이션 / DB 설정정보등핵심정보를외부로유출하여 보안에치명적일수있으므로반듯이삭제해야한다. 5.1.1 조치방안 60 / 77

웹디렉터리를조사하여다음과같은백업파일을모두삭제하고, *.txt 같이작업중생성된일반텍스 트파일이나이미지파일등도제거한다. 삭제해야할파일확장자 *.bak *.backup *.org *.old *.zip *.log *.! *.sql *.new *.txt *.tmp *.temp [ 표 4] 서비스에불필요한확장자 백업파일은백업계획을수립하여안전한곳에정기적으로백업을해야하며웹서버상에는웹서버상에 는운영에필요한최소한의파일만을생성하도록해야한다. 61 / 77

5.2. 기본파일존재 5.2.1 취약점설명 1) 개요 Apache, Tomcat, IIS 와같이웹서버설치시에기본적으로설치되는파일들은외부공격자에게해당 응용시스템에대한정보를제공해줄뿐만아니라디폴트페이지에대한취약성이공개되어있으므로 반드시삭제해야한다. 예를들어 APM(Apache, Php, MySql) 설정후 <?phpinfo();?> 라는임시파일을만들어시스템설정정보 를확인하게되는데이런파일을삭제하지않으면웹서버의중요정보가외부로노출될수있으므로 반듯이삭제해야한다. [ 그림 14] phpinfo() 정보노출 5.2.2 조치방안 62 / 77

웹서버설정후 Default Page 와 Default Directory 및 Banner 를삭제하여 Banner Grab 에의한시스템 정보유출을차단한다. Apache, IIS, Tomcat 등각웹서버설정시함께제공되는 Sample 디렉터리및 Manual 디렉터리, Sample Application 을삭제하여보안위험을최소화한다. 63 / 77

5.3. 민감한파일존재 고객의민감한개인정보파일의경우 WEB ROOT 이외의디렉토리에저장하여, URL 호출로접근이 되지않도록한다. 64 / 77

5.4. 디렉터리인덱싱 5.4.1 취약점설명 1) 개요 웹서버운영시특정디렉터리에초기화파일이없을경우 (index.html, default.html 등 ) 해당디렉터리의파일리스트를브라우저에보여주게되며이는공격자에게웹응용시스템의구조를파악할수있도록하며민감한정보가포함된설정파일을노출하여보안상심각한위험을초래할수있으므로반듯이해당기능을중지시켜야한다. 5.4.2 조치방안 웹서버환경설정에서디렉터리인덱싱기능을제거한다. 각웹서버에따른설정방법은다음과같다. APACHE 설정 Httpd.conf 파일에서 DocumentRoot 항목의 Options 에서 Indexes 를제거한다. Indexes 가해당디렉터리의파일목록을보여주는지시자이다. <Directory /var/www/html > Options Indexes </Directory> IIS 설정 65 / 77

설정 > 제어판 > 관리도구 > 인터넷서비스관리자 선택후해당웹사이트에오른쪽클릭을하 고등록정보의 [ 홈디렉토리 ] 탭에서 [ 디렉토리검색 ] 체크를해제한다. [ 그림 15] IIS 디렉터리인덱싱설정 66 / 77

%3f.jsp 취약점 웹서버를아파치를사용한다면아래와같이설정하여 %3f.jsp 문자를필터링해야하며 resin 이나 tomcat 을사용한다면최신버전으로업그레이드해야한다. <LocationMatch "/(%3f \?)\.jsp"> AllowOverride None Deny from all </LocationMatch> Resin 2.1.x 에서는최신버전으로업그레이드하거나아래와같이설정할수있다. Resin 환경설정파일 (resin.conf) 에서가상디렉터리설정부분인 web-app id 를찾아서 아래내용을추가한다. <directory-servlet>none</directory-servlet> 주의 : 모든가상디렉터리에전부적용해야한다. 67 / 77

5.5. 부적절한오류처리 5.5.1 취약점설명 1) 개요 고의적으로예외오류메세지를발생시켜공격에필요한정보획득에악의적으로사용될수있다. 때문 에웹서버상에서발생하는오류메시지를적절히처리하는설정이반듯이필요하다. [ 그림 16] 부적절한에러처리로인한정보노출 위그림과같이어플리케이션경로를획득할수있다 5.5.2 조치방안 일반적으로웹에서발생하는에러메시지는 400,500 번대의에러코드를 return 하게되는데이러한에 러코드에대해별도의에러페이지로 Redirect 하거나적절한에러처리루틴을설정하여처리되도록 한다. Apache 68 / 77

ErrorDocument 500 "Error Message ErrorDocument 404 /your web root/error.html ErrorDocument 404 /your web root/error.html ErrorDocument 402 http:/xxx.com/error.html 위와같이특정에러코드에대해에러메시지를출력할수도있고특정웹페이지로 redirect 시킬수 도있다. 위설정은 httpd.conf 의전역설정에추가하거나원하는가상호스트의 <VirtualHost> </VirtualHost> 사이에추가하면된다. 69 / 77

IIS (1) IIS 관리자에서로컬컴퓨터를두번클릭하고웹사이트폴더, 개별웹사이트폴더, 가상디렉터리또는파일을마우스오른쪽단추로클릭한다음속성을클릭한다. 참고 : 웹사이트수준에서만든구성설정은서버에있는모든웹사이트로상속됩니다. 개별사이트또는사이트요소를구성하여상속을무시할수있다. (2) 사용자지정오류탭을클릭한다. (3) HTTP 오류에대한오류메시지목록에서변경하려는 HTTP 오류를클릭한다음편집을클릭한다. 참고 : 오류 400, 403.9, 411, 414, 500, 500.11, 500.14, 500.15, 501, 503 및 505는사용자지정할수없다. (4) 메시지유형목록상자에서파일을클릭하여사용자지정오류파일을반환하거나 URL을클릭하여로컬컴퓨터의사용자지정오류 URL로요청을보낼수있다. 중요 : 사용자지정오류가.asp 페이지라면 URL을선택해야합니다. URL을선택하지않으면클라이언트로.asp 소스코드가반환될위험이있다. (5) 파일을선택했다면파일에대한경로를입력하거나찾아보기를클릭하여파일을찾습니다. 사용자지정오류메시지는기본적으로 systemroot\help\iishelp\common 폴더에설치됩니다. 파일이름은특정 HTTP 오류에해당되는번호즉 400.htm, 401-1.htm 등이된다. 또는 URL을선택했다면웹사이트나가상디렉터리에대한경로를입력합니다. URL은로컬컴퓨터에있는웹사이트나가상디렉터리여야하며, 사용자지정오류 URL은요청을사용자지정오류 URL로보내는응용프로그램풀에있어야한다. 사용자지정오류페이지를가상디렉터리에저장한경우해당가상디렉터리는웹사이트의다른부분과동일한응용프로그램풀에서실행되어야합니다. 그렇지않으면작업자프로세스가요청된사용자지정오류페이지를처리할수없다. (6) 확인을클릭하고다시확인을클릭한다. 70 / 77

5.6. 불필요한 Method 지원 5.6.1 취약점설명 1) 개요 불필요한메소드가허용되어있을경우악의적인사용자가이를이용해웹서버변조및시스템권한을 획득할수있는취약점이다. 사용자로부터중요한정보를받을때는 POST 메소드를사용해야하며그중 요도에따라 SSL 을사용한암호화통신을해야한다. 아래와같은명령어를사용하여웹서버에허용되어있는 HTTP 메소드의확인이가능하며 PUT 메소드를 사용할경우 asp 파일의업로드도가능하다. 만약웹쉘 (webshell) 을업로드하면웹서버의임의의명령어 실행이가능하다. [ 그림 17] 사용중인메소드확인 5.6.2 조치방안 HTTP메소드중필요한메소드 (GET, POST) 이외에는모두제거해야한다. 1) IIS서버웹홈디렉토리의쓰기권한을제거하고 PUT, DELETE 등의불필요한메소드제거를위해 WebDAV를중지시켜야한다. 원격지에서웹서버의컨텐츠를추가하고관리하는 WebDAV는다음과같이 regedit를이용하여레지스트리값을추가해야한다. 레지스트리추가후에는반드시시스템을재시작하여해당값이적용되도록해야한다. 레지스트리경로 : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3svc \Parameter 레지스트리값 : DisableWebDAV=1(DWORD) ( 대소문자주의 ) 71 / 77

[ 그림 18] WebDAV 중지설정 XST 취약성해결방안 IIS Lockdown툴에포함되어있는 URLScan을사용한다. 1. IIS Lockdown Tool을설치한다. 2. IIS Lockdown Tool에포함되어있는 URLScan을설치한다. 3. urlscan.ini에다음의내용을추가한다. - UseAllowVerbs=1을지정한경우 [options] UseAllowVerbs=1 [AllowVerbs] GET HEAD POST - UseAllowVerbs=0을지정한경우 [options] UseAllowVerbs=0 [DenyVerbs] TRACE TRACK IIS Lockdown Wizard 툴 72 / 77

http://www.microsoft.com/korea/technet/security/tools/locktool.asp URLScan 보안툴 http://www.microsoft.com/korea/technet/security/urlscan.asp KB326444 - URLScan 툴의구성방법 http://support.microsoft.com/kb/326444/ko 2) Apache 서버웹서버의 DocumentRoot로사용되는디렉터리에일반사용자에대한접근권한을제거하고 httpd.conf 파일에다음과같은내용을추가한후 Apache 서비스를재시작한다. <Directory /home/*/public_html > <Limit POST PUT DELETE> </Limit> </Directory> XST 취약성해결방안 1. Apache 1.3.34 과 2.0.55 이후버전 httpd.conf 의적당한부분에다음을기술하고 Apache 를재기동한다. TraceEnable Off TraceEnable Off 를기술하기전과후의 Apache 반응을 OPTIONS 메소드를사용하여비교 적용전 telnet 192.168.0.201 80 OPTIONS / HTTP/1.0 HTTP/1.1 200 OK Date: Sun, 12 Mar 2006 17:27:26 GMT Server: Apache/1.3.34 (Unix) Content-Length: 0 Allow: GET, HEAD, OPTIONS, TRACE Connection: close 적용후 telnet 192.168.0.201 80 73 / 77

OPTIONS / HTTP/1.0 HTTP/1.1 200 OK Date: Sun, 12 Mar 2006 17:28:28 GMT Server: Apache/1.3.34 (Unix) Content-Length: 0 Allow: GET, HEAD, OPTIONS Connection: close 적용후 에는 Allow 부분에 TRACE 가삭제되어있다. 2. apache 1.3.33과 2.0.54 이전버전 Apache 1.3.34과 2.0.55 이후버전에는 TraceEnable 가서포트되고있어상기와같이간단히 TRACE 메소드를무효로할수있지만, 이전버전 (1.3.33과 2.0.54) 을사용하고있는경우에는 mod_rewire 를사용하는방법이있다. 이방법은 TraceEnable 과는달리 TRACE메소드가허가되고있는것처럼보이지만, 내부처리에의해무효화하는방법이다. 우선, mod_rewrite 가유효하게되어있는지확인한다. 무효로되어있다면유효하게할것. 다음의항목이 httpd.conf에들어있으면된다. LoadModule rewrite_module libexec/mod_rewrite.so AddModule mod_rewrite.c 위의부분이확인되었다면, 적당한부분에 <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_METHOD} ^TRACE RewriteRule.* - [F] </IfModule> 과같이기술하고, Apache를재기동한다. 이것으로 TRACE메소드는유효하게되어있지만, 클라이언트로부터송신할수없게된다. 예를들어 TRACE 메소드를송신한경우 적용전 telnet 192.168.0.201 80 TRACE / HTTP/1.1 Host:localhost 74 / 77

HTTP/1.1 200 OK Date: Tue, 11 Jul 2006 10:57:30 GMT Server: Apache/1.3.12 (Unix) Transfer-Encoding: chunked Content-Type: message/http TRACE / HTTP/1.1 Host: localhost 적용후 telnet 192.168.0.201 80 TRACE / HTTP/1.1 Host: localhost HTTP/1.1 403 Forbidden Date: Tue, 11 Jul 2006 10:55:04 GMT Server: Apache/1.3.12 (Unix) Transfer-Encoding: chunked Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML><HEAD> <TITLE>403 Forbidden</TITLE> </HEAD><BODY> <H1>Forbidden</H1> You don't have permission to access / on this server.<p> <HR> <ADDRESS>Apache/1.3.12 Server at localhost.localdomain Port 80</ADDRESS> </BODY></HTML> 적용후 를보면알수있듯이 TRACE 메소드를송신할수없게되어있다. 3) Sun One WebServer (iplanet6.0sp2 이후버전 ) XST 취약성해결방안 1. /config/obj.conf 의 Default 오브젝트안에다음의기술을추가한다. 75 / 77

<Client method=""trace""> AuthTrans fn=""set-variable"" remove-headers=""transfer-encoding"" set-headers=""content-length: -1"" error=""501"" </Client> 2. 웹서버를재기동한다. Sun ONE/iPlanet Web Server Enable HTTP TRACE Method by Default to Emulate the CERT VU http://sunsolve.sun.com/search/document.do?assetkey=1-26-50603-1 76 / 77

6. 서버관리 6.1. Linux Patch 취약 6.1.1 취약점설명 1) 개요 CentOS 2.6.18 이하모든버전이 Local BoF Exploit 가능한상태이며, 다수의취약점에노출이가능이가 능하다. 6.1.2 조치방안 Kernel 의 Version 을최신상태로올리는것을권고한다. 6.2. 취약한 FTP 서비스구동중지 6.2.1 취약점설명 1) 개요 6.2.2 조치방안 가급적 Ftp Service 는 Disable 하고, SFTP 로통일하여사용하는것을권장한다. 6.3. Apache 버전취약 6.3.1 취약점설명 1) 개요 버전이낮으면다수의 DDOS 및 Heap BoF 취약점에노출될가능성이있다. 6.3.2 조치방안 Apache 2.2.4 버전이상을이용할것을권고한다. 77 / 77