framwork/Spring

Spring Security 설정 (표준 프레임워크 3.9v, Spring Security 4.2.11 v)

닉네임없음ㅎ 2023. 10. 25. 17:44

맡고있던 프로젝트를 OWASP ZAP을 사용하여 웹 취약점 분석을 진행 하였다

 

https://ko.wikipedia.org/wiki/OWASP_ZAP

 

OWASP ZAP은 가장 유명한 무료 보안 툴 중 하나라고 한다. 

이 툴을 사용해 보안 테스트를 실시하여 웹 어플리케이션의 보안 취약점을 파악할 수 있다.

(이번에 처음 써봤음..ㅎㅎ)

 

툴을 사용하여 스캐너를 돌려본 결과

X-Content-Type-Options Header Missing

Missing Anti-clickjacking Header

X-Frame-options Http header

Absence of Anti-CSRF Tokens

Buffer overflow 등의 취약점을 알게 되었다. 

 

Spring Security 설정을 하여 

response header 안에 저런 부분들을 다 추가해주어야 한다. 

(Buffer overflow 해결은 따로 포스팅 예정..)

 

 

Spring-Security는 기본적인 보안 값을 제공하기 위해 보안 관련 HTTP 응답 헤더의 기본집합을 제공한다.

 

 

header에 다음 항목을 포함한다 ! 

Cache-Control

X-Content-Type-Options : nosniff

X-Frame-Options : DENY

X-XSS-Protection: 1; mode=block  등 

(이 항목들 외에도 몇가지가 더 있음.. )

 

* Spring Security 설정

 

개발환경 

표준프레임워크 3.9v

spring-security 4.2.11 v 

(스프링 시큐리티는 스프링 버전에 의존도를 가지기 때문에 버전을 꼭 확인 해야한다.)

 

Error

org.springframework.beans.factory.BeanCreationException

bean with name ‘DAO’ 

bean with name ‘sqlMapper’

-> 스프링 시큐리티 4.1.3을 처음에 사용했더니 서버 시작했을 때 bean 생성 오류가 계속 발생했었다.

=> 버전을 4.2.11로 변경하고 해결함. 

 

 

1.  pom.xml의 properties에 spring-security를 추가한다.

<pom.xml>

<spring.security.version>4.2.11.RELEASE</spring.security.version>

 

2.  pom.xml에 dependency를 추가한다.

<!-- Spring Security -->
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-core</artifactId>
  <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${spring.security.version}</version>
</dependency>

dependency를 추가하고 프로젝트 우클릭 -> maven -> update project를 실행해준다. 

Maven Dependencies에 추가된 jar들을 확인할 수 있다.

 

 

3.  web.xml 에 Spring Security Filter를 추가한다.

<!-- Spring Security Filter -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

스프링 시큐리티를 적용하기 위한 필터이다. 

필터의 이름은 반드시 springSecurityFilterChain 이어야 한다.

그리고 필터가 적용될 url 패턴은 모든 패턴을 의미하는 ' /* ' 를 쓰도록한다!

주소 호출할 때 쓰던 *.do 사용하면 안됨. 

 

그리고 web.xml에서 context를 불러오는 경로를 한번 더 확인한다. 

 

4.  context-security.xml 파일을 생성한다.

(스프링 시큐리티 설정파일임)

 

-> CSRF만 사용할 것이기 때문에 간단하게 필요 부분만 작성한다. 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/security
                                 http://www.springframework.org/schema/security/spring-security.xsd">
        
        <authentication-manager />
    	<http pattern="/**" security="none"/>
		<http create-session="never" use-expressions="true">
			<csrf />
		<intercept-url pattern="/**" access="permitAll" />
		<headers>
     	   <frame-options policy="SAMEORIGIN"/>
 	   	 </headers>
		<http-basic />
		</http>    
</beans:beans>

스프링에서 bean설정하는 방법은 다양하다.

(properties 파일 사용,  xml 파일 사용,  class로 정의 => 나는 xml파일을 사용했다.)

주의할 점은 pom.xml에 적어놓은 security jar 버전과 

xml파일에서의 configuration 스키마 링크가 같아야한다. 

 

여기서 에러 발생함. 

context-security의 스키마 로케이션에 

http://www.springframework.org/schema/security/spring-security-4.2.xsd 이 부분을 

http://www.springframework.org/schema/security/spring-security.xsd" 이렇게 바꾸었다.. 

(에러메세지가 정확하게는 기억이 안나지만 schema를 업데이트 하라는 내용이었음.. )

 

 

 

이렇게 하면 스프링 시큐리티 설정을 하고 바로 서버를 돌려보면 

에러가 뜬다 ^0^v

 

401 Unauthorized : 아예 비로그인 상태에서 권한이 필요한 요청을 했을때 발생하는 에러

403 Forbidden : 로그인은 했으나 권한이 맞지 않는 경우에 발생하는 에러

 

구글링을 해보니, 

Spring security를 사용하는 경우 Ajax의 POST호출 시 403 Forbidden 에러가 발생한다고 한다. 

 

해결방안으로 csrf().disable()로 csrf를 사용하지 않게 설정하는 방법이 많이 나오는데

그럼 보안에 문제가 될 수 있기 때문에 csrf가 설정되어 있는 상태에서 403 에러를 발생하지 않게 하려고 한다. 

 

해결방법은 

Ajax 요청 header에 csrf 토큰을 넣어서 POST요청을 하는 것 ! 

 

1. index.jsp 파일 (본인이 사용하는 jsp파일... )에  csrf meta tag를 추가한다.

<index.jsp>

<head>
<meta id="_csrf" name="_csrf" content="${_csrf.token}"/>
<meta id="_csrf_header" name="_csrf_header" content="${_csrf.headerName}"/>
</head>

이렇게 <head> 태그 내에 csrf 토큰 정보를 삽입했다. 

(이 방식을 사용해도 되고 form 을 전송할때 input 박스에 값을 넣고 hidden으로 숨겨서 전달해도 됨 ! )

 

2. Ajax 호출할때 헤더에 csrf를 전달한다. 

 

나는 js파일에서 공통으로 사용하는 부분에 

<index.js>

$(document).ready(function() {
	var token = $("meta[name='_csrf']").attr("content");
	var header = $("meta[name='_csrf_header']").attr("content");
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader("AJAX", true);
            xhr.setRequestHeader(header, token);
        }
    });

이렇게 csrf 를 전달하도록 작성하였다. 

 

그리고 확인해보니 403에러 발생하지 않음 ! 

 

요청헤더에 

csrf token이 잘 담겨져 있고, 

 

응답헤더에는 

기본적인 시큐리티 설정이 되어있다. 

 

끝  ! 

 

 

* 틀린 부분이 있다면 마음껏 지적해주세요..♥