[TIL] 241223 보안

MONA·2024년 12월 23일

나혼공

목록 보기
49/92

시큐어 코딩

CORS(Cross-Origin Resource Sharing)

웹 브라우저에서 다른 출처(origin)의 리소스를 요청할 때 발생하는 보안 정책
웹 애플리케이션이 서버와 상호작용할 때 동일 출처 정책(Same-Origin Policy)가 적용되고, 이 정책은 스크립트 기반 요청이 동일한 출처에서만 허용되도록 제한함
CORS는 이 제한을 우회하기 위해 브라우저와 서버 간에 안전한 방식으로 교차 출처 요청을 처리할 수 있게 함

기본 개념

Same-Origin Policy (동일 출처 정책)

  1. 출처는 세 가지 요소로 구성됨
    • 프로토콜(Http, Https, ...)
    • 호스트
    • 포트
  2. 동일 출처 정책은 동일한 출처 간의 요청만 허용함

Same-Origin Policy가 필요한 이유?

왜 굳이 교차 출처 요청을 기본적으로 제한하고, 이를 우회하도록 설정해야하는 걸까?
-> 보안 때문이다. 악의적인 요청으로부터 사용자의 데이터를 보호하기위한 핵심 원칙 중 하나.

  1. 악의적인 사이트로부터의 보호(CSRF 방지)
    • 웹 브라우저는 로그인 상태에서 사용자의 쿠키와 세션 정보를 요청에 자동으로 포함한다.
    • 이 특성을 이용해 공격자가 Cross-Site Request Forgery(CSRF) 같은 공격을 수행할 수 있다.

만약, 이런 상황이 있다면 어떨까?

- 사용자가 A 웹사이트에 로그인함
- 동시에 사용자가 악의적인 B 웹사이트에 방문함
- B 웹사이트가 A 웹사이트로 요청을 보냄
- 브라우저는 자동으로 A 웹사이트에 대한 쿠키와 인증 정보를 포함하여 요청을 처리함
-> 사용자의 인증 정보를 악용해 공격자가 권한 없는 작업을 수행할 수 있음

동일 출처 정책은 이를 방지하기 위한 방법이다.

  1. 사용자 데이터 도난 방지

    • 교차 출처 요청이 허용된다면, 악성 웹사이트는 사용자가 방문한 다른 웹사이트의 데이터에 접근할 수 있음.
    • ex) 사용자가 자신의 은행 웹사이트에서 데이터를 확인 중일 때, 악성 웹사이트가 그 데이터를 읽거나 조작하려고 시도하는 경우.

    동일 출처 정책은 이러한 데이터 탈취 공격을 방지할 수 있다.

  2. 불필요한 자원 노출 방지

    • 모든 교차 출처 요청을 허용한다면 서버는 출처에 관계없이 요청을 처리한다.
    • 공격자는 이 허점을 다음과 같은 방식으로 악용할 수 있다.
      • 비공개 API 엔드포인트의 정보 유출
      • 민감 데이터 노출
      • 서버 리소스를 소모시켜 서비스 거부 공격(DoS)

    동일 출처 정책은 신뢰할 수 없는 출처로부터의 요청을 제한해 이런 문제를 방지한다.

  3. XSS와의 연계 문제

    • 교차 출처 요청 허용은 Cross-Site Scripting(XSS) 공격과 결합될 수 있다.
    • 공격자는 악성 스크립트를 사용해 브라우저에 삽입하고, 이를 이용해 민감한 데이터를 다른 출처로 전송할 수 있다.
      • 사용자 세션 정보, 쿠키, 개인 데이터 탈취
      • 권한 없는 요청을 자유롭게 실행 가능

CORS의 역할

  • 다른 출처의 리소스를 요청할 때 브라우저가 요청을 차단하지 않도록 허용하는 매커니즘
  • 서버가 응답에 적절한 CORS 헤더를 추가해 브라우저가 요청을 허용하도록 함

교차 출처 정책을 우회하도록 설계한 이유

CORS는 동일 출처 정책을 유지하면서도 특정 조건 하에 안전하게 교차 출처 요청을 허용할 수 있도록 설계되었다. 동일 출처 정책이 중요하면서도 CORS를 우회하도록 설계된 이유는 무엇일까?

  1. 현대 웹 애플리케이션의 분산 아키텍처

    • 현대의 웹 애플리케이션은 프론트엔드와 백엔드가 서로 다른 도메인에서 운영되는 경우가 많다.
    • 이 경우 동일 출처 정책만 고수하면 정당한 요청도 주고받을 수 없다.
    • CORS는 안전한 방식으로 이러한 요청을 허용할 수 있게 한다.
  2. 공유 API와 서비스

    • 다양한 서드파티 API와 서비스를 사용하는 애플리케이션이 많다.
    • 이런 API는 많은 클라이언트에서 요청을 받고, 이 요청은 안전하게 이루어져야 한다.
    • CORS는 이러한 요청을 허용하면서도 각 API 제공자가 요청 출처를 통제할 수 있게 한다.
  3. 정당한 비즈니스 요청 지원

    • 크로스도메인 요청은 데이터 분석, 광고 추적, CDN 등의 현대 웹 서비스에 필수적이다.
    • CORS는 비즈니스 요구를 충족시키면서 보안을 유지하도록 돕는다.

결론
동일 출처 정책은 웹의 기본 보안 매커니즘으로, 사용자를 악의적인 공격으로부터 보호하기 위해 설계되었음.
출처가 동일한 경우에만 데이터를 교환하도록 제한하여 웹 애플리케이션의 기본적인 보안 경계를 설정함.

CORS는 동일 출처 정책을 유지하면서도, 특정 조건에서 교차 출처 요청을 허용할 수 있도록 도와주는 매커니즘.

동작 방식

1. CORS 요청 유형

  • Simple Request(단순 요청)
    • GET, POST, HEAD 메서드만 사용
    • Content-Typetext/plain, multipart/form-data, application/x-www-form-urlencoded 중 하나
    • 브라우저가 서버로 직접 요청을 전송함
  • Preflight Request(사전 요청)
    • OPTIONS 메서드를 사용해 브라우저가 서버에 미리 요청을 전송
    • 서버가 허용하는 메서드와 헤더를 확인
    • ex) Authorization 헤더 사용 시, 사전 요청 발생
  • Credentialed Request(자격 증명 요청)
    • 인증 정보(쿠키, HTTP 인증 헤더)를 포함한 요청
    • 서버가 Access-Control-Allow-Credentials 헤더로 명시적으로 허용해야 함
Preflight request

브라우저가 실제 요청을 보내기 전에 서버에 요청할 권한이 있는지 확인하는 과정
특정 조건을 만족하는 HTTP 요청이 서버에 전송되기 전에 실행됨

  • HTTP 메서드가 simple request가 아닐 때(PUT, DELETE etc)
  • 특정 헤더를 사용할 때: 커스텀 헤더 또는 특정 표준 헤더 사용 시
  • 특정 content-type을 사용할 때: 위의 simple request에서 언급한 헤더가 아닐 때

동작 방식

  1. 브라우저가 preflight 요청을 보낸다.
    • OPTIONS 메서드를 사용해 서버에 사전 요청을 보냄
    • 실제 요청의 메서드, 헤더 정보 포함
  2. 서버가 preflight 요청에 응답
    • 서버가 요청된 메서드와 헤더를 허용할지의 여부를 결정해 응답한다.
  3. 브라우저는 이 응답을 확인하고 요청 허용 시 실제 요청을 보낸다.

2. CORS 헤더

서버는 응답에 아래와 같은 CORS 헤더를 추가해 브라우저와의 교차 출처 통신을 허용함

  • Access-Control-Allow-Origin: 요청을 허용할 출처를 지정
  • Access-Control-Allow-Methods: 서버가 허용하는 HTTP 메서드 지정
  • Access-Control-Allow-Headers: 서버가 허용하는 요청 헤더 지정
  • Access-Control-Allow-Credentials: 인증 정보(쿠키 등)를 요청에 포함하는 것을 허용
  • Access-Control-Expose-Headers: 클라이언트가 읽을 수 있는 응답 헤더를 명시
  • Access-Control-Max-Age: 사전 요청 결과를 캐싱하는 시간(초단위)을 설정

설정 시 주의사항

보안

  • 신뢰할 수 없는 출처를 허용하면 안 됨
  • allowedOrigins에 와일드카드 사용 시 모든 출처를 허용하는 것
  • 민감 정보 보호를 위해 Access-Control-Allow-Credentials를 신중하게 설정해야 함

성능

  • Preflight 요청이 빈번할 시 성능 저하가 발생할 수 있어 Access-Control-Max-Age를 설정해 Preflight 요청을 캐싱
  • 불필요한 preflight 요청을 최소화하기 위해 단순 요청 조건을 충족하도록 API 설계를 검토해야 함

CSRF(Cross-Site Request Forgery)

사용자가 신뢰하는 웹 애플리케이션을 대상으로 악의적인 요청을 전송하게 하는 보안 취약점
공격자는 사용자의 인증 정보를 악용해 사용자가 의도치 않은 작업을 수행하도록 유도함

위의 예시로 든 정상적인 웹사이트 A와 악의적인 웹사이트 B를 동시 접속했을 때, 사용자가 모르게 사용자의 인증 정보(쿠키)를 포함해 정상적인 요청인 것 처럼 요청을 보내는 행위 같은 것.
피해자가 로그인 상태일 경우 공격이 성공하며, 공격자는 사용자의 인증 정보를 알 필요가 없다. 브라우저가 자동으로 쿠키를 전송하기 때문에 발생한다.

CSRF 방지하기

1. CSRF 토큰 사용

서버에서 생성하여 클라이언트에게 제공하고, 요청마다 이를 포함하도록 요구함

동작 방식

  1. 서버는 사용자 세션에 CSRF 토큰을 생성하여 저장한다.
  2. 클라이언트는 요청 시 CSRF 토큰을 함께 전송한다(토큰은 요청 본문, 헤더, 또는 URL 매개변수에 포함됨)
  3. 서버는 요청에 포함된 토큰과 세션의 토큰을 비교하여 요청의 유효성을 검증한다.
  4. 토큰이 일치하지 않을 경우 요청을 거부한다.

2. Referer or Origin 헤더 검증

요청의 Referer 또는 Origin 헤더를 확인하여 요청이 신뢰할 수 있는 출처에서 온 것인지 검증함

동작 방식

  1. 요청 헤더에 포함된 Referer 또는 Origin 값이 서버의 도메인과 일치하는 지 확인한다.
  2. 일치하지 않으면 요청을 거부한다.

제한: 일부 브라우저 또는 프록시 환경에서는 헤더가 제거될 수 있음

3. 쿠키의 SmaeSite 속성 설정

쿠키가 동일 출처 요청에서만 전송되도록 제한하는 속성을 설정함

동작 방식

  • SameSite=Strict: 쿠키는 동일한 출처에서 발생한 요청에만 포함
  • SameSite=Lax: GET 요청 또는 특정 안전한 요청에서만 쿠키 포함

4. CORS 설정

CORS 설정을 통해 특정 출처에서만 서버 자원에 접근할 수 있도록 제한함
다만 CSRF 방지 목적으로만 사용하는 것은 권장되지 않는다

XSS(Cross-Site Scripting)

공격자가 악성 스크립트를 삽입하여 다른 사용자의 브라우저에서 실행되도록 만드는 공격 기법
주로 사용자가 신뢰하는 웹사이트를 대상으로 수행되며, 이를 통해 사용자의 개인 정보, 세션 쿠키, 브라우저 데이터 등을 탈취하거나 악성 동작을 수행할 수 있음

특징

  • 공격 대상: 사용자의 브라우저
  • 공격 목표: 악성 스크립트를 삽입하고 실행하여 데이터를 탈취하거나, 악성 동작 수행
  • 피해 범위: 개인 정보 탈취(쿠키, 세션 토큰)/ 악성 행동 수행(데이터 조작 등)/사이트 신뢰 훼손

유형

1. Stored XSS(저장형 XSS)

  • 악성 스크립트가 서버에 영구적으로 저장되며, 해당 컨텐츠를 읽는 모든 사용자가 공격에 노출됨
  • ex) 사용자가 게시판에 악성 스크립트를 포함된 댓글을 작성하고, 이를 서버가 저장한다.
    이후 다른 사용자가 이 댓글을 읽을 때 스크립트가 실행됨

2. Reflected XSS(반사형 XSS)

  • 악성 스크립트가 즉각적으로 실행되며 서버에 저장되지 않음
  • 주로 URL 파라미터 또는 입력값을 통해 공격이 이루어짐
  • ex) 공격자가 악성 URL을 생성하고, 타인이 이 URL 클릭 시 스크립트 실행됨

3. DOM-based XSS

  • DOM 조작으로 발생하며, 서버가 아닌 클라이언트에서 실행됨
  • 클라이언트 측 자바스크립트 코드가 취약한 경우 발생

XSS 방지 방법

1. 입력값 검증(Input Validation)

  • 사용자가 입력한 데이터를 검증하여 허용된 값만 처리
  • 허용되지 않은 문자 또는 태그를 필터링

2. 출력값 이스케이프(Output Escaping)

  • 사용자 입력을 HTML로 출력하기 전에 특별한 문자를 이스케이프

3. Content Security Policy (CSP)

  • 서버에서 특정 콘텐츠만 실행되도록 브라우저에 정책을 설정
  • 스크립트 실행을 제한

4. HTTPOnly 쿠키 사용

  • 쿠키에 HttpOnly 속성을 추가하여 자바스크립트에서 쿠키 접근을 방지

5. 템플릿 엔진 사용

  • 서버 템플릿 엔진을 사용해 자동으로 XSS를 방지하는 HTML 이스케이프 처리
  • ex) JSP, Thymeleaf, Handlebars 등

6. DOM 조작 주의

  • DOM 조작 시 사용자 입력값을 직접 삽입하지 않음

7. 라이브러리 활용

  • XSS 방지 라이브러리를 사용하여 검증과 이스케이프 처리

SQL Injection

공격자가 웹 애플리케이션의 보안 취약점을 악용해 SQL 쿼리를 조작하는 공격 기법
공격자는 이를 통해 데이터베이스의 민감 정보를 조회하거나 조작하는 등 공격할 수 있음

동작 원리

웹 애플리케이션이 사용자 입력값을 제대로 검증하지 않고 SQL 쿼리에 직접 삽입할 때 발생함.
공격자는 입력값을 통해 SQL 쿼리를 조작하고 의도치 않은 동작을 수행할 수 있음.

ex)

정상 쿼리

SELECT * FROM users WHERE username = 'john' AND password = 'password123';

공격자가 입력값을 조작
입력값:

  • username = 'john' OR '1'='1

  • password = 'anything'

    결과 쿼리

    SELECT * FROM users WHERE username = 'john' OR '1'='1' AND password = 'anything';

    1=1은 항상 참이므로 데이터베이스는 모든 사용자 정보를 반환하게 됨.

유형

  1. Classic SQL Injection

    공격자가 입력값을 조작하여 SQL 쿼리를 직접 변경

    입력값: admin' --
    생성 쿼리:

    SELECT * FROM users WHERE username = 'admin' --' AND password = 'password';

    -- 이후는 주석처리 되어 비밀번호 조건을 우회할 수 있음

  2. Blind SQL Injection

    데이터베이스의 응답 내용을 직접 확인할 수 없는 경우, 참/거짓 응답을이용해 데이터를 추출

    입력값: ' OR 1=1 --

    참일 경우:
    SELECT * FROM users WHERE id = 1 AND '1'='1'; -- 데이터 반환
    거짓일 경우:
    SELECT * FROM users WHERE id = 1 AND '1'='0'; -- 데이터 반환 없음
  3. Union-based SQL Injection

    UNION 명령어를 이용해 여러 쿼리의 결과를 결합

    입력값: ' UNION SELECT username, password FROM admin --
    결과 쿼리:

    SELECT username, password FROM users WHERE id = '' UNION SELECT username, password FROM admin --;
  4. Error-based SQL Injection

    쿼리 실행 중 발생한 에러 메시지를 통해 데이터베이스 정보를 추출

    입력값: 1' AND EXTRACTVALUE(1, CONCAT(0x3a, (SELECT @@version))) --
    반환: 데이터베이스 버전 정보

  5. Time-based Blind SQL Injection

    데이터베이스의 응답 지연 시간을 이용해 참/거짓 조건 판단

    입력값: ' OR IF(1=1, SLEEP(5), 0) --
    참일 경우 서버 응답이 지연됨

SQL Injection의 영향

  1. 데이터 유출 및 조작
  2. 권한 조작: 관리자 계정의 비밀번호를 변경하거나 새 계정 삽입으로 권한을 탈취할 수 있음
  3. 서버 손상: 데이터베이스 조작으로 삭제, 파일 시스템 접근 등 심각한 손상 초래할 수 있음
  4. 비즈니스 피해: 데이터 손실, 서비스 중단, 브랜드 신뢰도 하락으로 이어질 수 있음

SQL Injection 방지 방법

  1. Prepared Statements (Parameterized Queries)

    사용자 입력값을 직접 사용하지 않고 플레이스홀더를 사용함

    String query = "SELECT * FROM users WHERE username = ? AND password = ?";
    PreparedStatement pstmt = connection.prepareStatement(query);
    pstmt.setString(1, username);
    pstmt.setString(2, password);
    ResultSet rs = pstmt.executeQuery();
  2. Stored Procedures(저장 프로시져)

    데이터베이스에서 미리 정의된 SQL 쿼리의 집합. 서버 측에서 실행되는 재사용 가능한 프로그램 단위로, 하나 이상의 SQL 문장을 포함하며, 매개변수를 받아 특정 작업을 수행할 수 있음

CREATE PROCEDURE GetUserByUsername
    @username NVARCHAR(50)
AS
BEGIN
    SELECT * FROM users WHERE username = @username;
END;

호출

CallableStatement stmt = connection.prepareCall("{call GetUserByUsername(?)}");
stmt.setString(1, "john");
ResultSet rs = stmt.executeQuery();

입력값인 john은 @username 파라미터에 바인딩되며 SQL Injection이 어려움

  1. Input Validation(입력값 검증)

    사용자 입력값을 철저히 검증하여 SQL에 사용될 수 없는 문자나 패턴을 필터링함

    if (!input.matches("\\d+")) {
        throw new IllegalArgumentException("Invalid input");
    }
  2. ORM 사용

    Hibernate, JPA 같은 ORM(Object-Relational Mapping) 도구를 사용해 직접 SQL 작성 최소화

  3. 데이터베이스 권한 제한

    Principle of Least Privilege(최소 권한 원칙)를 적용, 애플리케이션 계정은 필요한 작업만 수행할 수 있는 권한만 가지도록 함

  4. 에러 메시지 숨기기

    사용자에게 자세한 SQL 에러 메시지를 노출하지 않음
    ex) 잘못된 입력 시, "Invalid Request"와 같은 일반적인 메시지를 반환

  5. 웹 애플리케이션 방화벽(WAF) 활용

    SQL Injection 공격 패턴을 탐지하고 차단하는 방화벽 도입

  6. 로그 모니터링

SQL Injection 테스트 도구

  • Burp Suite: 웹 애플리케이션 취약점 스캐너
  • SQLMap: SQL Injection 자동화 도구
  • OWASP ZAP:OWASP의 오픈소스 취약점 분석 도구
profile
고민고민고민

0개의 댓글