[ Java ] CSRF
포스트
취소

[ Java ] CSRF

취약한 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package kr.co.openeg.lab.test.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import kr.co.openeg.lab.member.model.MemberModel;
import kr.co.openeg.lab.member.model.MemberSecurity;
import kr.co.openeg.lab.member.service.MemberService;

@Controller
public class CsrfTestController {

	@Autowired
	private MemberService service;

	@RequestMapping(value="/test/csrf_test",produces = "application/text; charset=utf8")
	@ResponseBody
	public String testCSRF(HttpServletRequest request) {
			StringBuffer buffer=new StringBuffer();
			String id=request.getParameter("id");
		    MemberSecurity m=service.findMemberSecurity(id);
			buffer.append("<p>ID: "+m.getUserId()+"</p>");
			buffer.append("<p>Comment: "+m.getComment()+"</p>");
	        return buffer.toString();
	}
} 



취약점 분석


1
String id=request.getParameter("id");

어떤 형태의 요청이든지 기본적으로 특정 웹사이트에 대해 사용자가 인지하지 못한 상황에서 사용자의 의도와는 무관하게 공격자가 의도한 행위를 요청하는 CSRF 취약점을 가질 수 있다.


이를 방지하기 위해선 CORS 허용 정책을 사용하거나, 입력화면이 요청되었을 때 임의의 토큰을 생성하여 세션에 저장했다가 요청 파라미터와 세션에 저장된 토큰을 비교해서 일치하는 경우에만 요청을 처리하는 방법이 있다.



안전한 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package kr.co.openeg.lab.test.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import kr.co.openeg.lab.member.model.MemberModel;
import kr.co.openeg.lab.member.model.MemberSecurity;
import kr.co.openeg.lab.member.service.MemberService;

@Controller
public class CsrfTestController {

	@Autowired
	private MemberService service;

	@RequestMapping(value="/test/csrf_test",produces = "application/text; charset=utf8")
	@ResponseBody
	public String testCSRF(HttpServletRequest request) {
			StringBuffer buffer=new StringBuffer();
			String id=request.getParameter("id");
		    MemberSecurity m=service.findMemberSecurity(id);
			buffer.append("<p>ID: "+m.getUserId()+"</p>");
			buffer.append("<p>Comment: "+m.getComment()+"</p>");
	        return buffer.toString();
	}
}


// Spring Secruity framework를 이용하여 CORS 허용 정책을 적용==========
package kr.co.openeg.lab.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.httpBasic().disable()
            .cors().configurationSource(corsConfigurationSource())
               .headers().frameOptions().disable()
            .csrf()
                .and().disable()
			.formLogin().disable()  
			.headers().frameOptions().disable();
	}
}