웹 보안 취약점 정리(Injection, XSS, CSRF)

JACKJACK·2023년 8월 24일
1
post-thumbnail

웹 보안 취약점

우리의 개인정보 보호와 비즈니스 위험을 줄이기 위해, 웹 어플리케이션의 보안 취약점에는 어떤것들이 있는지 이해하고 사전에 방어하는 방법을 알아보자.

가장 유명한 웹 보안 취약점으로는 다음과같은 것들이 있다.

  • SQL Injection (SQL 삽입): 악의적인 SQL 쿼리를 삽입하여 데이터베이스에 접근하거나 조작하는 공격으로, 웹 애플리케이션에서 사용자 입력을 적절하게 필터링하지 않을 경우 발생할 수 있다.
  • XSS(Cross-Site Scripting): 웹 애플리케이션에서 악의적인 스크립트를 삽입하여 사용자의 브라우저에서 실행되게 하는 공격으로, 사용자가 이 스크립트를 실행하면 개인 정보 유출이나 세션 도용 등의 문제가 발생할 수 있다.
  • CSRF(Cross-Site Request Forgery): 사용자의 인증 정보를 이용하여 피해자의 권한으로 비정상적인 요청을 보내는 공격으로, 사용자가 악의적인 웹 사이트를 방문할 때 발생할 수 있다.

1. SQL Injection

웹 애플리케이션에서 사용자 입력을 적절하게 필터링하지 않을 경우 발생할 수 있으며,
취약한 SQL 쿼리를 실행하도록 만들어진다. 공격자는 주로 입력 폼, URL 매개변수 또는 쿠키와 같은 입력 경로를 통해 공격을 시도한다. 그렇다면 SQL Injection의 예시와 해결방법에 대해 알아보자.

간단한 예시로 로그인 페이지에서 다음과 같은 쿼리문을 사용한다고 가정하면
SELECT * FROM users WHERE username = '$username' AND password = '$password';
username와 password에 다음과 같은 정보를 입력해 데이터베이스에 접근이 가능해진다.
SELECT * FROM users WHERE username = ' ' OR '1'='1' -- password = 'anything';

이러한 SQL Injection을 방지하기 위해서는 다음과 같은 방법들이 사용된다.

  • Prepared Statements (Parametrized Queries): 사용자 입력 값을 직접 SQL 쿼리에 삽입하지 말고, Prepared Statements를 사용하여 쿼리와 사용자 입력을 분리한다. 이를 통해 입력 값이 쿼리 파라미터로 취급되어 SQL Injection을 방지할 수 있다.
  • 입력 유효성 검사: 사용자 입력 값을 받을 때, 필요한 형식이나 범위를 검사하여 유효한 입력인지 확인하는 방법으로, 숫자가 필요한 곳에 문자열이 들어오는 것을 regex로 막을 수 있다.
  • ORM (Object-Relational Mapping) 사용: JPA와 같이 ORM 라이브러리를 사용하면 SQL을 직접 작성하지 않아도 되므로 SQL Injection 취약성의 가능성이 줄어든다.
  • 데이터베이스 사용자 권한 관리: 데이터베이스 사용자에게 최소 권한만 부여하여 데이터베이스 내의 중요한 작업을 수행할 수 없도록 제한한다.
  • 에러 메시지 관리: 사용자 친화적이지 않은 에러 메시지를 표시하여 공격자가 시스템 정보를 알아내는 것을 방지한다.

2. XSS(Cross-Site Scripting)

악의적인 사용자가 스크립트 코드를 삽입하여 다른 사용자의 브라우저에서 실행되게 만드는 공격으로, 세션 쿠키를 탈취하거나 사용자의 브라우저에서 악의적인 동작을 수행한다. 그렇다면 XSS의 예시와 해결방법에 대해 알아보자.

간단한 예시로 사용자의 입력을 바로 출력하는 코드가 있다고 가정하면
<div>Welcome, <?php echo $_GET['username']; ?></div>
공격자가 입력란에 다음과 같은 스크립트를 추가한 URL을 사용자에게 노출시켜 접속 시 ALERT 경고창을 띄우게 된다.
<script>alert("XSS Attack");</script>
이 외에도 게시글과 같이 웹사이트에 업로드를 하는 방식으로도 사용자에게 몰래 접근해 쿠키 정보 및 세션 ID의 내용 탈취 등의 악의적인 동작을 수행한다.

이러한 XSS를 방지하기 위해서는 다음과 같은 방법들이 사용된다.

  • 입력 값 이스케이프: 사용자 입력 값을 출력하기 전에 적절한 이스케이프(escape) 함수를 사용하여 스크립트 코드가 실행되지 않도록 처리한다. (<script>alert("XSS Attack");</script>경우 태그를 Replace 시키는 등...)
  • Content Security Policy (CSP): CSP를 설정하여 웹 페이지에서 실행 가능한 스크립트의 소스를 제한하거나 허용된 도메인만 실행하도록 설정(HTTP 헤더 설정 예시: <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted-domain.com; style-src 'self';"> 현재 도메인, 신뢰할수 있는 도메인만 허용 )
  • 입력 유효성 검사: 입력 값의 형식을 검사하여 허용되지 않는 문자나 패턴을 차단한다.
  • HttpOnly 속성 사용: 세션 쿠키에 HttpOnly 속성을 적용하여 JavaScript에서 쿠키에 접근할 수 없도록 한다.
  • X-XSS-Protection 헤더 사용: 웹 서버에서 X-XSS-Protection 헤더를 설정하여 브라우저의 내장 XSS 필터를 활성화한다.

3. CSRF(Cross-Site Request Forgery)

사용자의 인증 정보를 이용하여 피해자의 권한으로 비정상적인 요청을 보내는 공격으로, 사용자가 악의적인 웹 사이트를 방문할 때 발생할 수 있다. CSRF의 예시와 해결방법에 대해 알아보자.

간단한 예시로 다음과 같이 사용자 정보를 업데이트 하는 폼을 사용자의 의도 없이 자동으로 제출하게 하는 방식으로, 악의적인 URL을 노출해 CSRF공격이 들어올 수 있다.
<form action="https://example.com/update-profile" method="POST">
<input type="text" name="newUsername" value="hackerUsername">
<input type="submit" value="Update Profile">
</form>
<script>
// 폼이 자동으로 제출되도록 하는 코드
document.forms[0].submit();
</script>

이러한 CSRF를 방지하기 위해서는 다음과 같은 방법들이 사용되며, 서로 조합해 더욱 강화된 보안을 구축할 수 있다.

  • CSRF 토큰 사용: 가장 효과적이고 널리 사용되는 CSRF 방어 방법 중 하나이다. CSRF 토큰은 웹 페이지의 폼 제출 시 고유한 토큰을 생성하여 함께 전송하는 방식으로, 서버는 이 토큰을 검증하여 요청이 유효한지 확인해 요청의 출처를 확인할 수 있다.
  • SameSite 쿠키 속성 설정: SameSite 쿠키 속성을 Strict 또는 Lax로 설정하여, 동일한 사이트에서 온 요청에서만 쿠키가 전송되도록 한다. 이를 통해 타 사이트에서의 요청에 의한 CSRF 공격을 방지할 수 있다.
  • Referrer Policy 설정: Referrer-Policy 헤더를 사용하여 요청의 Referrer 정보를 제어(출저정보를 헤더에 담을지 등..)하거나 숨길 수 있어, 외부 사이트로부터의 요청에서 온 Referrer 헤더를 제어/차단하여 CSRF 공격을 방지할 수 있다.
profile
러닝커브를 빠르게 높이자🎢

0개의 댓글