보안 공부/소스코드 보안약점 진단

소스코드 보안약점 진단 - 크로스사이트 요청위조

H.J.World 2021. 12. 23. 10:10
728x90
반응형

소스코드 보안약점 진단 // 소프트웨어 보안약점 진단 // SW 보안약점 진단과 같이 다양한 이름으로 불리는 진단 과업 중 하나이다.

SW개발보안은 해킹 등 사이버공격의 원인인 보안약점을 SW개발단계에서 사전에 제거하고 SW 개발 생명주기의 각 단계별로 수행하는 일련의 보안활동을 통하여 안전한 SW를 개발·운영하기 위한 목적으로 적용하는 개발체계이다.

해당 내용은 KISA에서 발간하는 취약점 진단 가이드 항목을 기준으로 작성한다.


10. 크로스사이트 요청위조

가. 개요

특정 웹사이트에 대해서 사용자가 인지하지 못한 상황에서 사용자의 의도와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 요청하게 하는 공격을 말한다. 웹 응용프로그램이 사용자로부터 받은 요청에 대해서 사용자가 의도한 대로 작성되고 전송된 것인지 확인하지 않는 경우 발생 가능 하고 특히 해당 사용자가 관리자인 경우 사용자 권한관리, 게시물삭제, 사용자 등록 등 관리자 권한 으로만 수행 가능한 기능을 공격자의 의도대로 실행시킬 수 있게 된다.

공격자는 사용자가 인증한 세션이 특정 동작을 수행하여도 계속 유지되어 정상적인 요청과 비정상 적인 요청을 구분하지 못하는 점을 악용한다. 웹 응용프로그램에 요청을 전달할 경우, 해당 요청의 적법성을 입증하기 위하여 전달되는 값이 고정되어 있고 이러한 자료가 GET 방식으로 전달된다면 공격자가 이를 쉽게 알아내어 원하는 요청을 보냄으로써 위험한 작업을 요청할 수 있게 된다.

나. 보안대책

입력화면 폼 작성시 GET 방식보다는 POST 방식을 사용하고 입력화면 폼과 해당 입력을 처리하는 프로그램 사이에 토큰을 사용하여, 공격자의 직접적인 URL 사용이 동작하지 않도록 처리한다. 특히 중요한 기능에 대해서는 사용자 세션검증과 더불어 재인증을 유도한다.

다. 코드예제

클라이언트로부터의 요청(request)에 대해서 정상적인 요청 여부인지를 검증하지 않고 처리하는 경우, 크로스사이트 요청 위조 공격에 쉽게 노출될 수 있다.

 

- 안전하지 않은 코드의 예 JAVA -

// 어떤 형태의 요청이던지 기본적으로 CSRF 취약점을 가질 수 있다.

 

- 안전한 코드의 예 JAVA -

정상 요청 여부를 판단하기 위해 토큰을 이용한다. 사용자가 입력(신청) 페이지를 요청하면 임의의 토큰을 생성한 후 세션에 저장하고, 입력(신청) 페이지에 생성한 토큰을 HIDDEN 필드 항목의 값 으로 설정한다. 입력(신청)을 처리하는 페이지에서는 입력(신청) 페이지에서 요청 파라미터로 전달된 HIDDEN 필드의 토큰 값과 세션에 저장된 토큰 값을 비교하여 일치하는 경우에만 정상 요청으로 판단하여 입력(신청)이 처리될 수 있도록 한다.

// 입력화면이 요청되었을 때, 임의의 토큰을 생성한 후 세션에 저장한다.
1: session.setAttribute("SESSION_CSRF_TOKEN", UUID.randomUUID().toString());
// 입력화면에 임의의 토큰을 HIDDEN 필드항목의 값으로 설정해 서버로 전달되도록 한다.
2: <input type="hidden" name="param_csrf_token" value="${SESSION_CSRF_TOKEN}" />
// 요청 파라미터와 세션에 저장된 토큰을 비교해서 일치하는 경우에만 요청을 처리한다.
3: String pToken = request.getParameter("param_csrf_token");
4: String sToken = (String)session.getAttribute("SESSION_CSRF_TOKEN");
5: if (pToken != null && pToken.equals(sToken) {
// 일치하는 토큰이 존재하는 경우 -> 정상 처리
6: ......
7: } else {
// 토큰이 없거나 값이 일치하지 않는 경우 -> 오류 메시지 출력
8: ......
9: }

 

라. 진단방법

사용자 권한변경, 신규정보 등록 등 주요 기능을 확인하고(①), 해당 기능 수행시 권한확인 절차 존재 여부 확인한다②). 권한확인 절차가 없거나 권한 확인 방법이 세션쿠키, 사용자 IP, SSL 인증과 같이 자동 제출되는 자격증명에 의존하는 경우 취약하다.

1: …
2: int level = request.getParameter(“level”);------------------①
3: int group = request.getParameter(“group”);------------------①
4: String id = request.getParameter(“id”);----------------------①
5: String sql=”update member set level=? , group=? where id=?;”;-----①
6: pstmt =con.prepareStatement(sql);
7: pstmt.setInt(1, level);
8: pstmt.setString(2, group);
9: pstmt.setInt(3, id);
10: pstmt.executeUpdate();---------------------------------②
11: …

 

- 오탐코드의 예 -

다음의 예제를 살펴보면, 2번째 라인에서 임의의 토큰을 생성한 후 세션에 저장하고, 5번째 라인에서 생성한 토큰을 HIDDEN 필드 항목의 값으로 설정한다. 그리고 10번째 라인에서 HIDDEN 필드의 토큰 값과 세션에 저장된 토큰 값을 비교하여 일치하는 경우에만 정상 요청으로 판단하여 처리하고 있기 때문에 오탐으로 판단한다.

1: // 입력화면이 요청되었을 때, 임의의 토큰을 생성한 후 세션에 저장한다.
2: session.setAttribute(“SESSION_CSRF_TOKEN”, UUID.randomUUID().toString());
3:
4: // 입력화면에 임의의 토큰을 HIDDEN 필드항목의 값으로 설정해 서버로 전달되도록 한다.
5: <input type=”hidden” name=”param_csrf_token” value=”${SESSION_CSRF_TOKEN}” />
6:
7: // 요청 파라미터와 세션에 저장된 토큰을 비교해서 일치하는 경우에만 요청을 처리한다.
8: String pToken = request.getParameter(“param_csrf_token”);
9: String sToken = (String)session.getAttribute(“SESSION_CSRF_TOKEN”);
10: if (pToken != null && pToken.equals(sToken) {
11: // 일치하는 토큰이 존재하는 경우 -> 정상 처리
12: ......
13: } else {
14: // 토큰이 없거나 값이 일치하지 않는 경우 -> 오류 메시지 출력
15: ..
..
..
16: }
728x90
반응형