inblog logo
|
spencer-tech

    CORS

    CORS, SOP, Cross-Origin Resource Sharing, Same-Origin-Policy
    Sang Un Lee's avatar
    Sang Un Lee
    Jul 04, 2024
    CORS
    Contents
    1. 배경 개념1.1 origin1.2 same-origin1.3 cross-origin1.4 Same-origin policy 1.5 CORS2. Preflight3. Images4. CORS 요청, 응답에 사용되는 헤더4.1 요청 헤더4.2 응답 헤더
     
    1. 배경 개념1.1 origin1.2 same-origin1.3 cross-origin1.4 Same-origin policy 1.5 CORS2. Preflight3. Images4. CORS 요청, 응답에 사용되는 헤더4.1 요청 헤더4.2 응답 헤더
     

    1. 배경 개념

    1.1 origin

     
    • origin = scheme + host + port
      • scheme : URL의 프로토콜을 나타냄
        • ex. http, https, ftp 등
      • host : 서버의 도메인 이름 or IP 주소
        • ex. localhost, www.naver.com
      • port : 네트워크 포트
        • 표준 포트가 아닐 경우 나타냄
        • 포트가 URL에 없는 경우, origin = scheme + host
        • ex. 8080, 3306
     
    • 예시 : URL: https://localhost:8080/surveys
      • scheme: https
      • host: localhost
      • port: 8080
      • path: /surveys

    1.2 same-origin

     
    • 클라이언트가 서버에 요청을 보냈을 때
      • 서버의 origin과 클라이언트의 origin이 동일한 경우
     
    • 예시
      • https://aurora.net/home -> https://aurora.net/api/pos?id=290
      • 클라이언트, 서버 둘 다 origin이 https://aurora.net 으로 동일

    1.3 cross-origin

     
    • 클라이언트가 서버에 요청을 보냈을 때
      • 서버의 origin과 클라이언트의 origin이 다른 경우
    • 예시
    https://localhost:8080/home -> https://aurora.net/api/pos?id=290 https://localhost:8080/home -> https://127.0.0.1:8080/api/pos?id=290 https://localhost:8080/home -> https://127.0.0.1:3000/api/pos?id=290
    • 클라이언트의 origin : https://localhost:8080
    • 서버의 origin은 이와 다르므로 cross-origin

    1.4 Same-origin policy

     
    • 브라우저의 역할
      • 클라이언트
      • ex. 웹 페이지를 로드, 사용자와 상호작용, HTTP 요청을 서버에 보내고 응답을 처리
     
    • 기본적으로 브라우저는 same origin의 HTTP 요청만 허용함
      • Same origin policy(보안 정책)
     
    • SOP가 필요한 이유 : 클라이언트와 서버를 보호하기 위해서
     
    • 서버를 보호하는 관점
      • 클라이언트가 악의적인 스크립트를 요청으로 보내는 것을 제한하기 위함
      • CSRF (Cross-Site Request Forgery)
        • 공격 대상: 주로 서버
        • 공격 방식 : 사용자가 신뢰하는 웹 사이트에 이미 로그인된 상태 → 공격자가 사용자를 속여 특정 요청을 수행
          • 사용자가 의도하지 않은 요청이 서버로 전송돼서 서버에서 의도하지 않은 동작 발생 가능
     
    • 클라이언트를 보호하는 관점
      • 사용자의 민감한 정보(쿠키, 세션 데이터 등)가 악의적인 스크립트에 의해 탈취되는 것을 방지하기 위함
      • XSS (Cross-Site Scripting)
        • 공격 대상 : 주로 클라이언트 (브라우저에서 실행되는 사용자)
        • 공격 방식 : 공격자가 악성 스크립트를 웹 페이지에 삽입 → 사용자가 페이지를 열었을 때 스크립트가 실행
          • 이를 통해 사용자의 세션 정보, 쿠키 등을 탈취 가능

    1.5 CORS

     
    • CORS : 브라우저에서 다른 origin으로 요청을 허용하는 메커니즘
     
    • CORS 요청을 할 때 클라이언트, 서버가 해야하는 것
      • 클라이언트 : 없음, 요청을 실행하기만 하면 됨
      • 서버 : 클라이언트의 origin을 허용하고 응답
        • 서버는 Access-Control-Allow-Origin 응답 헤더를 전송
        • 이 응답 헤더의 값은 * 또는 특정 origin이 될 수 있음
          • * : 서버가 모든 origin의 요청을 수락한다는 의미
     
    • CORS 요청에 대한 응답이 왔을 때
      • 클라이언트 : 응답 검토
      • Access-Control-Allow-Origin 에 * 값이 있거나 origin 값이 클라이언트의 origin과 일치하면 브라우저는 응답을 수락함
      • 그렇지 않으면 응답을 삭제하고 콘솔에 CORS 설정 오류를 표시
     
    • CORS 메커니즘 과정
      • 1. 브라우저(origin X)가 서버(origin Y)로 요청을 보냄 2. 서버가 브라우저의 요청에 응답, 이때 Access-Control-Allow-Origin 응답 헤더를 포함하고 origin X를 해당 헤더의 값으로 넣음 3. 브라우저 : 서버 응답에 Access-Control-Allow-Origin 응답 헤더의 값에 origin X가 있는지 확인 4.1 origin X가 있다면 응답을 수락 4.2 origin X가 없다면 응답을 폐기하고 CORS 오류 메세지 표시
     
    • origin을 알 수 없는 경우, Access-Control-Allow-Origin 을 null로 설정할 수도 있음
      • origin을 알 수 없는 경우 예시 : 웹사이트가 아닌 파일에 접근하는 경우

    2. Preflight

     
    • 위 내용은 CORS라는 메커니즘을 사용해서 origin이 다른 경우 요청을 처리하는 방법
      • 실제로 CORS 요청을 보내기 전에 브라우저는 preflight 요청을 보냄
      • Preflight 요청의 목적 : 서버가 실제 요청을 허용하는지 확인
     
    • 브라우저가 preflight 요청을 보내는 경우 : 아래 조건 중 하나라도 충족하는 경우
        1. HTTP 메서드가 GET, POST, HEAD가 아닌 경우
            • GET, HEAD, POST가 아닌 경우 데이터 수정/삭제와 관련 있을 수 있으므로 보안상 서버의 허가를 확인
        1. Content-Type 헤더의 값이 아래 3가지 중 하나가 아닌 경우
            • application/x-www-form-urlencoded
            • multipart/form-data
            • text/plain
            • application/x-www-form-urlencoded, multipart/form-data, text/plain은 일반적으로 안전한 MIME 타입으로 간주됨
              • 위 타입 외에 application/json과 같은 Content-Type은 데이터의 구조가 복잡할 수 있으므로 서버가 이를 처리할 준비가 되어 있는지 확인하기 위해 Preflight 요청이 필요
        1. 요청 헤더에 Accept, Accept-Language, Content-Language 외에 다른 요청 헤더가 있는 경우
            • ex. Authorization와 같은 헤더가 있다면 preflight 요청 필요
            • Accept, Accept-Language, Content-Language는 일반적으로 안전한 헤더로 간주됨
              • 그러나 Authorization과 같은 다른 헤더는 인증 정보나 사용자 데이터와 관련될 수 있어 보안 검증이 필요함
              • 따라서 서버가 이러한 헤더를 수락할 준비가 되어 있는지 확인하기 위해 preflight 요청을 보냄
        1. XMLHttpRequest 객체가 업로드 이벤트를 포함하는 경우
            • 파일 업로드와 같은 작업은 더 많은 리소스를 필요로 하고 보안 위험이 있을 수 있음
              • 따라서 서버가 이러한 요청을 허용할 준비가 되어 있는지 확인하기 위해 Preflight 요청을 보냄
     
    • 위 4가지 조건 중 하나라도 해당된다면, 브라우저는 실제 CORS 요청을 보내기 전에 서버에 preflight 요청을 보내서 서버가 해당 요청을 허용하는지 확인
     
    • Preflight 요청 : HTTP 메서드 중 OPTIONS 메서드를 사용
      • 서버가 이에 적절한 응답을 보내면, 브라우저는 그때 실제 요청을 보냄
     
    • Preflight 요청은 CORS 요청을 보낼 때만 preflight 요청을 보냄
      • Preflight 요청을 통해 서버가 CORS 요청에 대한 응답을 잘 보낼 수 있도록
     
    • Preflight 요청에서 브라우저는 아래와 같은 응답 헤더를 보냄
        1. Origin: 클라이언트의 origin
        1. Access-Control-Request-Method: 실제 CORS 요청에서 사용할 HTTP 메서드 (하나의 메서드만 지원)
        1. Access-Control-Request-Headers: 단순하지 않은 헤더들
     
    • 서버는 preflight 요청에서 다음을 확인
      • 요청의 origin(Origin)
      • CORS 요청의 메서드(Access-Control-Request-Method)
      • CORS 요청에 포함된 추가 헤더들(Access-Control-Request-Headers)
     
    • 서버는 이 정보들이 서버의 허용 목록에 있는지 확인함
      • 허용 목록에 있다면 서버는 200번대의 status code로 응답
      • 이 응답에는 응답 본문은 없음
     
    • preflight 요청에 대한 응답으로, 서버는 다음과 같은 응답 헤더를 보냄
        1. Access-Control-Allow-Origin: 허용된 출발지 도메인
        1. Access-Control-Allow-Methods: 허용된 HTTP 메서드들
        1. Access-Control-Allow-Headers: 허용된 요청 헤더들
      • 이는 서버가 브라우저에게 해당 CORS 요청을 허용한다는 의미
      • 이후 브라우저는 해당 서버에게 CORS 요청을 보낼 수 있음
      •  
    • preflight 요청의 예시
      • OPTIONS /api/posts HTTP/1.1 User-Agent: Chrome Host: 127.0.0.1:8080 Accept: */* Origin: http://localhost:3000 Access-Control-Request-Method: GET Access-Control-Request-Headers: Security-Level, App-Name
     
    • preflight 응답 예시
      • HTTP/1.1 204 No Content Access-Control-Allow-Origin: http//localhost:3000 Access-Control-Allow-Methods: GET, DELETE Access-Control-Allow-Headers: Security-Level, App-Name
     
    • Preflight 요청을 포함한 CORS 요청을 처리하는 과정
      • 1. 브라우저(origin X)가 서버(origin Y)로 요청 P를 보냄 - 요청 P는 HTTP 메서드 M과 헤더 C를 포함 2.1 HTTP 메서드 M이 간단한 메서드 && 헤더 C가 간단한 헤더라면 -> 요청 P를 서버로 보냄 -> 서버 응답(끝) - 간단한 HTTP 메서드 : GET, POST, HEAD - 간단한 헤더 : Accept, Accept-Language, Content-Language, Content-Type(Content-Type은 값이 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나인 경우) 2.2 HTTP 메서드 M이 간단하지 않거나 | 헤더 C가 간단하지 않다면 -> preflight 요청 F를 보냄 - 요청 F의 헤더 - origin = X - Access-Control-Request-Method = M - (헤더 C가 간단하지 않은 경우) Access-Control-Request-Headers = C 3. 서버 : X, M, C가 허용 목록에 있는지 확인 4. 허용 목록에 있다면 -> 요청 F에 대한 preflight 응답을 보냄 - status code : 200 범위 - 응답 헤더 : Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers 5. 클라이언트가 preflight 응답을 받았다면, 이제 요청 P를 서버로 보냄 -> 서버 응답(끝)
     
    • Preflight 요청에 대한 응답은 캐시 가능
      • 따라서 캐시가 있다면 preflight 요청을 보내지 않아도 됨
      • 캐시의 기준 : origin + path
        • ex. https://www.naver.com/api/data

    3. Images

     
    • 다른 origin의 이미지는 처리를 제한
      • 이미지의 src 속성이 클라이언트와 origin이 다른 경우
      • 브라우저는 해당 이미지를 로드, 표시는 가능하지만 조작은 불가
      • 조작 예시 : toBlob, toDataURL, getImageData
     
    • 이미지에 대해 CORS를 활성화하는 방법
      • 즉, origin이 다른 이미지의 조작을 가능하게 하는 방법
      • crossOrigin 속성의 값을 anonymous 또는 user-credentials로 설정
        • anonymous : 자격 증명이 필요하지 않은 경우
        • user-credentials : 자격 증명이 필요한 경우

    4. CORS 요청, 응답에 사용되는 헤더

    4.1 요청 헤더

     
    • Origin
      • 브라우저에 의해 추가됨
      • 클라이언트의 origin을 표시
      • 여기에 대응되는 응답 헤더 : Access-Control-Allow-Origin
      •  
    • Access-Control-Request-Method
      • 브라우저가 preflight 요청 시 추가함
      • 실제 CORS 요청에서 클라이언트가 사용할 HTTP 메서드를 포함
      • 여기에 대응되는 응답 헤더 : Access-Control-Allow-Methods
     
    • Access-Control-Request-Headers
      • 브라우저가 preflight 요청 시 추가함
      • 실제 CORS 요청에서 클라이언트가 보낼 HTTP 헤더를 포함
      • 여기에 대응되는 응답 헤더 : Access-Control-Allow-Headers
     

    4.2 응답 헤더

     
    • Access-Control-Allow-Origin
      • 값이 *일 경우 모든 출처가 허용됨을 의미
      • 특정 값이 있을 경우 서버가 해당 origin에서만 요청을 허용함을 의미
      • 값이 null일 경우 웹 사이트가 아닌 출처(예: 파일)에서의 요청만 허용함을 의미
      • 여기에 대응되는 요청 헤더 : Origin
     
    • Access-Control-Allow-Credentials
      • 값이 true이면 서버가 쿠키와 같은 사용자 자격 증명의 사용을 지원함을 나타냄
     
    • Access-Control-Allow-Methods
      • 서버에서 허용하는 HTTP 메서드들의 목록
      • 간단한 메서드(GET, POST, HEAD)는 포함할 필요는 없지만, 포함하는 것이 좋은 관행
      • 이 헤더는 preflight 요청에 대한 응답으로만 보내야 함
      • 여기에 대응되는 요청 헤더 : Access-Control-Request-Methods
     
    • Access-Control-Allow-Headers
      • 서버에서 허용하는 HTTP 헤더들의 목록
      • 이 헤더는 preflight 요청에 대한 응답으로만 보내야 함
      • 여기에 대응되는 요청 헤더 : Access-Control-Request-Headers
     
    • Access-Control-Max-Age
      • preflight 요청에 대한 응답의 캐시를 유지할 최대 시간
      • 이 헤더는 preflight 요청에 대한 응답으로만 보내야 함
     
    • Access-Control-Expose-Headers
      • 브라우저가 읽을 수 있는 헤더들
      • 선택 사항이며, CORS 요청이 성공적으로 처리되기 위해 반드시 필요하지는 않음
     
    Share article
    Contents
    1. 배경 개념1.1 origin1.2 same-origin1.3 cross-origin1.4 Same-origin policy 1.5 CORS2. Preflight3. Images4. CORS 요청, 응답에 사용되는 헤더4.1 요청 헤더4.2 응답 헤더

    spencer-tech

    RSS·Powered by Inblog