JSP

 

이글은 스프링 시큐리티가 아니다.

이글은 jsp 프로젝트에서 시큐리티 적용에 방법에 대한 내용이다.

그리고 앞선 글에서 OWASP 설치 및 설정 방법과 테스트에 대한 내용을 적었다.

 

OWASP - CSRFGuard 3.0

http://macaronics.net/index.php/m01/jsp/view/1351

 

위과정을 진행 하였고 이해를 하였다면  이글을 이해하는데는 아무런 문제가 없을 것이다.

 

 

owasp 특징중에 하나가  @WebServlet("/MacaronicsServlet") 과 같이 url 맵핑 적용에서

시큐리티 적용내로 이동을 하면 안된다.

아래 소스  join.jsp  에서 action ="/member/joinproc.jsp" 되어 있다.

이것을 매핑 처리해서 @WebServlet("/member/joinproc.jsp") 이렇게 하면 안된다는 것이다.

즉 , 직접 jsp 폴더와 파일  위치로 액션 처리해야 한다.

 

 

join.jsp

<%@page import="java.net.URLEncoder"%>
<%@page import="config.GetIpAddress"%>
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>  
<!DOCTYPE html >
<html>
<head>
<jsp:include page="../include/Header.jsp" />  
 </head> 
<body>
<jsp:include page="../include/HeaderMenu.jsp" />
<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
    function sample6_execDaumPostcode() {
        new daum.Postcode({
            oncomplete: function(data) {
                // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

                // 각 주소의 노출 규칙에 따라 주소를 조합한다.
                // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
                var fullAddr = ''; // 최종 주소 변수
                var extraAddr = ''; // 조합형 주소 변수

                // 사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
                if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
                    fullAddr = data.roadAddress;

                } else { // 사용자가 지번 주소를 선택했을 경우(J)
                    fullAddr = data.jibunAddress;
                }

                // 사용자가 선택한 주소가 도로명 타입일때 조합한다.
                if(data.userSelectedType === 'R'){
                    //법정동명이 있을 경우 추가한다.
                    if(data.bname !== ''){
                        extraAddr += data.bname;
                    }
                    // 건물명이 있을 경우 추가한다.
                    if(data.buildingName !== ''){
                        extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                    }
                    // 조합형주소의 유무에 따라 양쪽에 괄호를 추가하여 최종 주소를 만든다.
                    fullAddr += (extraAddr !== '' ? ' ('+ extraAddr +')' : '');
                }

                // 우편번호와 주소 정보를 해당 필드에 넣는다.
                document.getElementById('sample6_postcode').value = data.zonecode; //5자리 새우편번호 사용
                document.getElementById('sample6_address').value = fullAddr;

                // 커서를 상세주소 필드로 이동한다.
                document.getElementById('sample6_address2').focus();
            }
        }).open();
    }
</script> 


<div class="row">
	
	<div class="col-xs-12 col-sm-12">
	<h2>&nbsp;</h2>	
	<h2 class="text-center">회원가입</h2>
	</div>		
	
	<div class="col-xs-3 col-sm-3"></div>	
	<div class="col-xs-8 col-sm-8">
		
	  <div >		
	 	<p>&nbsp;</p>
		
		<form class="form-horizontal" action="/member/joinproc.jsp" method="post">
		 <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label for="id">아이디</label>
		 	</div>
		 	<div class="col-sm-6 text-left">
		 		<input type="text" class="form-control" name="id" id="id" value="macaronics">
		 	</div>
		 </div>
		 
		 <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="pwd">패스워드</label>
		 	</div>
		 	<div class="col-sm-6">
		 		<input type="password" class="form-control" name="pwd" id="pwd">
		 	</div>
		 </div>
		 
		 <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="pwdCheck">패스워드 체크</label>
		 	</div>
		 	<div class="col-sm-6">
		 		<input type="password" class="form-control" name="pwdCheck" id="pwdCheck">
		 	</div>
		 </div>
		
		 <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="name">이름</label>
		 	</div>
		 	<div class="col-sm-6">
		 		<input type="text" class="form-control" name="name" id="name" value="홍길동">
		 	</div>
		 </div>		 
		 
		 <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="email">이메일</label>
		 	</div>
		 	<div class="col-sm-6">
		 		<input type="email" class="form-control" name="email" id="email" value="macaronics@gmail.com">
		 	</div>
		 </div>	
	 
		 
		  <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="zip_num">우편번호</label>
		 	</div>
		 	<div class="col-sm-3">
		 	 <input type="text" id="sample6_postcode" placeholder="우편번호"  name="zip_num" class="form-control" value="06267">
			</div>
			<div class="col-sm-3">
			<input type="button" onclick="sample6_execDaumPostcode()" value="우편번호 찾기" class="btn btn-primary">
		 
		 	</div>
		 </div>	
		
			<div class="form-group" >
			 <div class="col-sm-2 control-label">
		 		<label id="address1">주소</label>
		 	 </div>
		 	 <div class="col-sm-6">
			    <input type="text" id="sample6_address" 
			    placeholder="주소"  name="address1"   class="form-control" value="서울 강남구 강남대로 238 (도곡동, 스카이쏠라빌딩)">
			 </div>   
		   </div>
	 
		  <div class="form-group"> 
		  	 <div class="col-sm-2 control-label">
		 		<label id="address1">상세주소</label>
		 	 </div>
		 	 <div class="col-sm-6"> 
		       <input type="text" id="sample6_address2" placeholder="상세주소" name="address2"   class="form-control" value="256-32">
		       </div>
		  </div>
		 
	

		  <div class="form-group">
		 	<div class="col-sm-2 control-label">
		 		<label id="phone">전화번호</label>
		 	</div>
		 	<div class="col-sm-6">
		 		<input type="text" class="form-control" name="phone" id="phone" value="010-256-3332">
		 	</div>
		 </div>
		 
		 
		 <input type="hidden" name="ip" value="${GetIpAddress.getIp()}">
		 <div class="form-group" >
		    <div class="col-sm-12  text-center">
		 	<input type="submit" value="회원가입" class="btn btn-success">
		 	<input type="reset" value="취소" class="btn btn-warning">
		 	</div>
		 </div>
		
		
		</form> 
	  </div>
	</div>

</div>





<jsp:include page="../include/Footer.jsp" />



   

 

joinproc.jsp

<%@page import="java.net.URLDecoder"%>
<%@page import="java.net.URLEncoder"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JoinProc</title>
</head>
<body>
<%
	request.setCharacterEncoding("UTF-8");
%>
<jsp:useBean id="member" class="net.macaronics.web.dto.MemberVO">
	<jsp:setProperty name="member"  property="*"/>
	
</jsp:useBean>


CSRF attacks 공격에 대한 보안유지 되어할 페이지.<br>

이 페이지에 넘어 오면 CSRF 정상 작동.


<br>

<%
String name=request.getParameter("name");
String address1=request.getParameter("address1");
String address2=request.getParameter("address2");

String address=new String(address1.getBytes("ISO_8859_1"), "utf-8");
address += " " +new String(address2.getBytes("ISO_8859_1"), "utf-8");

/* String charset[] = {"euc-kr", "ksc5601", "iso-8859-1", "8859_1", "ascii", "UTF-8"}; 
System.out.println("넘어온 값 :" +name);

for(int i=0; i<charset.length ; i++){
    System.out.println(charset[i] + " URLEncoder : " + URLEncoder.encode(name, charset[i]));
    System.out.println(charset[i] + " URLDecoder : " + URLDecoder.decode(name, charset[i]));
 }
 */


%>

<!-- 한글필터 적용이 안 되어서  한글 깨짐 처리-->
<jsp:setProperty property="name" name="member" value='<%= new String(name.getBytes("ISO_8859_1"), "UTF-8") %>' />
<jsp:setProperty property="address1" name="member" value='<%= new String(address1.getBytes("ISO_8859_1"), "UTF-8") %>' />
<jsp:setProperty property="address2" name="member" value='<%= new String(address2.getBytes("ISO_8859_1"), "UTF-8") %>' />
<jsp:setProperty property="address" name="member" value='<%= address %>' />


${member.toString() }
</body>
</html>

 

 

정상적으로 시큐리티가 적용된 경우의 결과 페이지 모습이다.

 

 

csrf:form 을  제거 하고 실행해 보면  csrf 공격으로 인해  차단되어서 에러 페이지로 이동하게 된다.

 

 

 

또한, 직접 http://localhost:8090/member/joinproc.jsp  로 직접이동해도 시큐리티가 적용 되어서 다음과 같이

에러 페이지로 이동 하게 된다.

스프링에서는 WEB-INF  내에서 다이렉트로  접근 불과 페이지에서 개발하게 되는데, jsp 프로젝트에서 는 WEB-INF 폴더 외에서

작업폴더를 만들어 일반적으로  url 로 파일명만 적으면 접근할 수 있어 보안에 문제가 있다. 그러나 owasp 시큐리티를 

적용하면 csrfguard.properties 에서 허용된 페이지 및 파일 등 기타  모든 파일들은 다이렉트로  접근 불과 처리 된다.

 

시큐리티 적용시 다음과 같이 hidden 으로 토큰이 형성된 것을 볼 수 있다.

 

 

 

 

제작 : macaronics.net - Developer  Jun Ho Choi

소스 :  https://github.com/braverokmc79/jsp_sin

루트 설정( http://macaronics.net/index.php/m01/jsp/view/1352)    및 server.xml  에서 DB 컨넥션 설정은 필수 설정이다.

 

 

about author

PHRASE

Level 60  라이트

사람을 사귀는 데 자기가 가난하다고 부끄러워해서는 안되는 것이다. 가난을 부끄러워한다면 참된 우정은 생겨나지 않는 것이다. 참된 우정은 마음과 마음의 결합에 있다. -고시원

댓글 ( 4)

댓글 남기기

작성