Overview

소개

참고: 이 문서는 현재 개발 중입니다. 곧 개선될 예정입니다.

Google 세이프 브라우징 v5는 Google 세이프 브라우징 v4가 개선된 버전으로, v5의 두 가지 주요 변경사항은 데이터 최신성과 IP 개인 정보 보호입니다. 또한 유연성과 효율성을 높이고 팽창을 줄이기 위해 API 노출 영역이 개선되었습니다. 또한 Google 세이프 브라우징 v5는 v4에서 쉽게 이전할 수 있도록 설계되었습니다.

현재 Google은 v4와 v5를 모두 제공하며 v4와 v5 모두 프로덕션에 즉시 사용할 수 있는 것으로 간주됩니다. v4 또는 v5를 사용할 수 있습니다. v4의 지원 종료 날짜는 아직 공지하지 않았으며, 공지할 경우 최소 1년 전에 공지할 예정입니다. 이 페이지에서는 v5에 대한 설명과 v4에서 v5로의 이전 가이드를 설명합니다. 전체 v4 문서는 제공됩니다.

데이터 최신 상태

v4에 비해 Google 세이프 브라우징 v5 (특히 v4 Update API)에서 크게 개선된 한 가지는 데이터 업데이트 및 노출 범위입니다. 방어는 고객이 유지관리하는 로컬 데이터베이스에 따라 크게 달라지므로, 로컬 데이터베이스 업데이트의 지연과 크기가 보호 실패의 주요 원인입니다. v4의 경우, 일반적인 클라이언트는 최신 버전의 위협 목록을 얻는 데 20~50분이 걸립니다. 안타깝게도 피싱 공격은 빠르게 확산됩니다. 2021년 기준으로, 공격을 유도하는 사이트의 60% 가 10분 이내에 지속됩니다. FireEye의 분석에 따르면 피싱 방지 기능 누락의 약 25~30% 는 이러한 데이터 비활성으로 인한 것입니다. 또한 일부 기기는 Google 세이프 브라우징 위협 목록 전체를 관리할 수 있는 준비가 되어 있지 않으며, 이러한 목록은 시간이 지남에 따라 계속해서 증가하고 있습니다.

v5에서는 실시간 보호라고 하는 작동 모드가 도입되었습니다. 이렇게 하면 위의 데이터 비활성 문제를 우회할 수 있습니다. v4에서 클라이언트는 로컬 데이터베이스를 다운로드 및 유지하고, 로컬로 다운로드된 위협 목록에 대한 검사를 수행한 다음, 부분 접두사 일치가 있을 때 전체 해시를 다운로드하도록 요청을 수행해야 합니다. v5에서는 클라이언트가 위협 목록의 로컬 데이터베이스를 계속 다운로드하고 유지 관리해야 하지만, 이제 클라이언트도 양성일 가능성이 높은 사이트 목록 (전역 캐시라고 함)을 다운로드하고, 이 글로벌 캐시에 대한 로컬 검사와 로컬 위협 목록 확인을 모두 수행해야 하며, 마지막으로 위협 목록에 대해 부분 일치 접두사가 있거나 글로벌 캐시에 일치하지 않는 항목이 있는 경우 전체 해시를 다운로드하라는 요청을 수행해야 합니다. (클라이언트가 필요로 하는 로컬 처리에 대한 자세한 내용은 아래 제공된 절차를 참조하시기 바랍니다.) 이는 기본적으로 허용에서 기본 확인으로의 전환을 의미하며, 웹에서 위협이 더 빠르게 전파되므로 보호 기능이 개선될 수 있습니다. 즉, 실시간에 가까운 보호 기능을 제공하도록 설계된 프로토콜로, 고객이 최신 Google 세이프 브라우징 데이터로 혜택을 누릴 수 있도록 하는 것을 목표로 합니다.

IP 개인 정보 보호

Google 세이프 브라우징 (v4 또는 v5)은 요청을 처리하는 과정에서 사용자의 ID와 관련된 어떠한 정보도 처리하지 않습니다. 전송된 쿠키는 무시됩니다. 요청의 발신 IP 주소는 Google에 알려져 있지만, Google에서는 필수 네트워킹 요구사항 (즉, 응답 전송용) 및 DoS 방지 목적으로만 IP 주소를 사용합니다.

v5와 동시에 Safe Browsing Oblivious HTTP Gateway API라는 호환 API가 도입됩니다. 이렇게 하면 Oblivious HTTP를 사용하여 Google로부터 최종 사용자의 IP 주소를 숨깁니다. 결단하지 않는 제3자가 사용자 요청의 암호화된 버전을 처리한 다음 이를 Google에 전달하도록 하는 방식으로 작동합니다. 따라서 서드 파티는 IP 주소에만 액세스할 수 있고 Google은 요청 콘텐츠에만 액세스할 수 있습니다. 서드 파티는 Oblivious HTTP Relay (예: Fastly 서비스)를 운영하며 Google은 Oblivious HTTP Gateway를 운영합니다. 이는 선택적 컴패니언 API입니다. Google 세이프 브라우징과 함께 사용하면 최종 사용자의 IP 주소가 더 이상 Google로 전송되지 않습니다.

적절한 사용법

허용되는 사용

Safe Browsing API는 비상업적 용도로만 사용합니다('판매 또는 수익 창출 목적'이 아님). 상업적 목적의 솔루션이 필요한 경우 웹 위험 관리를 참조하세요.

가격 책정

모든 Google Safe Browsing API는 무료입니다.

할당량

Safe Browsing API를 사용 설정하면 개발자에게 기본 사용 할당량이 할당됩니다. 현재 할당 및 사용량은 Google Developer Console에서 확인할 수 있습니다. 현재 할당된 할당량보다 많은 할당량을 사용할 것으로 예상되면 Play Console의 할당량 인터페이스에서 추가 할당량을 요청할 수 있습니다. Google은 이러한 요청을 검토한 후 할당량 증가를 신청할 때 모든 사용자의 필요를 충족하는 서비스 제공을 위해 담당자에게 연락해야 합니다.

적절한 URL

Google 세이프 브라우징은 브라우저의 주소 표시줄에 표시되는 URL에 대해 작동하도록 설계되었습니다. HTML 파일에서 참조하는 JavaScript나 이미지 또는 JavaScript에서 시작된 WebSocket URL과 같은 하위 리소스를 검사하는 데 사용하도록 설계되지 않았습니다. 이러한 하위 리소스 URL은 Google 세이프 브라우징과 대조하면 안 됩니다.

URL을 방문하여 리디렉션 (예: HTTP 301)이 발생하는 경우 리디렉션된 URL을 Google 세이프 브라우징과 대조하는 것이 좋습니다. History.pushState와 같은 클라이언트 측 URL을 조작해도 새 URL은 Google 세이프 브라우징과 대조되지 않습니다.

사용자 경고

Google 세이프 브라우징을 사용하여 사용자에게 특정 웹페이지의 위험에 관해 경고하는 경우 다음 가이드라인이 적용됩니다.

이 가이드라인은 페이지가 안전하지 않은 웹 리소스임을 100% 확실하게 알 수 없으며 경고는 단순히 잠재적인 위험을 식별하는 것임을 명확히 함으로써 사용자와 Google 모두를 오해하지 않도록 보호하는 데 도움이 됩니다.

  • 사용자에게 보이는 경고 메시지를 통해 사용자가 문제의 페이지가 안전하지 않은 웹 리소스라고 믿도록 유도해서는 안 됩니다. 식별되는 페이지 또는 사용자에게 발생할 수 있는 잠재적 위험을 언급할 때 '가능성 있음', '가능성 있음', '가능성 있음'과 같은 용어를 사용하여 경고를 표시해야 합니다.
  • 경고를 받으면 사용자가 다양한 위협에 대한 Google의 정의를 검토하여 자세한 내용을 파악할 수 있어야 합니다. 다음 링크를 사용하는 것이 좋습니다.
  • 세이프 브라우징 서비스에서 위험하다고 확인한 페이지에 관한 경고를 표시할 때는 'Google에서 제공하는 Advisory'라는 행과 세이프 브라우징 권고사항으로 연결되는 링크를 포함하여 Google에 저작자를 표시해야 합니다. 제품에 다른 소스를 기반으로 한 경고도 표시되는 경우 Google 이외의 데이터에서 파생된 경고에 Google 저작자 표시를 포함해서는 안 됩니다.
  • 제품 문서에 Google 세이프 브라우징이 제공하는 보호 기능이 완벽하지는 않음을 알리는 고지를 제공해야 합니다. 거짓양성 (위험한 것으로 신고된 안전한 사이트)과 거짓음성 (위험한 사이트가 신고되지 않음)일 가능성이 모두 있음을 알려야 합니다. 다음 표현을 사용하는 것이 좋습니다.

    Google은 안전하지 않은 웹 리소스에 관한 가장 정확한 최신 정보를 제공하기 위해 노력하고 있습니다. 하지만 Google은 사이트의 포괄적이고 오류가 없다고 보장할 수 없습니다. 일부 위험한 사이트는 식별되지 않을 수 있으며, 일부 안전한 사이트는 잘못 식별될 수 있습니다.

작업 모드

Google 세이프 브라우징 v5를 사용하면 클라이언트가 세 가지 작업 모드 중에서 선택할 수 있습니다.

실시간 모드

고객이 실시간 모드로 Google 세이프 브라우징 v5를 사용하기로 선택하는 경우, 클라이언트는 로컬 데이터베이스에서 (i) 호스트 접미어/경로 접두사 URL 표현식의 SHA256 해시 형식일 가능성이 높은 사이트의 글로벌 캐시, (ii) 호스트-접미사/경로 접두사 URL 표현식의 SHA256 해시 접두사 형식인 위협 목록 집합을 로컬 데이터베이스에 유지하게 됩니다. 대략적으로 말하면 클라이언트가 특정 URL을 확인하려고 할 때마다 글로벌 캐시를 사용하여 로컬 검사가 수행된다는 것입니다. 이 검사를 통과하면 로컬 위협 목록 검사가 수행됩니다. 그렇지 않으면 아래에 설명된 대로 클라이언트가 실시간 해시 검사를 계속합니다.

로컬 데이터베이스 외에, 클라이언트는 로컬 캐시를 유지합니다. 이러한 로컬 캐시는 영구 저장소에 있을 필요가 없으며 메모리 부족 시 삭제될 수 있습니다.

절차에 대한 자세한 사양은 아래에서 확인할 수 있습니다.

로컬 목록 모드

클라이언트가 이 모드에서 Google 세이프 브라우징 v5를 사용하도록 선택하는 경우, 클라이언트 동작은 v4의 개선된 API 노출 영역을 사용하는 경우를 제외하고 v4 Update API와 유사합니다. 클라이언트는 호스트-서픽스/경로-접두사 URL 표현식의 SHA256 해시 접두사 형식으로 된 일련의 위협 목록을 로컬 데이터베이스에 유지합니다. 클라이언트가 특정 URL을 확인할 때마다 로컬 위협 목록을 사용하여 검사가 수행됩니다. 일치하는 항목이 있는 경우에만 클라이언트가 서버에 연결하여 확인을 계속합니다.

위와 마찬가지로 클라이언트는 영구 저장소에 있을 필요가 없는 로컬 캐시도 유지합니다.

스토리지 없는 실시간 모드

클라이언트가 스토리지 없는 실시간 모드에서 Google 세이프 브라우징 v5를 사용하기로 선택하는 경우, 영구적인 로컬 데이터베이스를 유지할 필요가 없습니다. 그러나 클라이언트는 여전히 로컬 캐시를 유지해야 합니다. 이러한 로컬 캐시는 영구 저장소에 있을 필요가 없으며 메모리 부족 시 삭제될 수 있습니다.

클라이언트는 특정 URL을 확인하려고 할 때마다 항상 서버에 연결하여 검사를 수행합니다. 이 모드는 v4 Lookup API의 클라이언트가 구현할 수 있는 것과 유사합니다.

이 모드는 실시간 모드와 비교할 때 더 많은 네트워크 대역폭을 사용할 수 있지만 클라이언트가 지속적인 로컬 상태를 유지하는 것이 불편한 경우에는 더 적합할 수 있습니다.

URL 확인

이 섹션에는 클라이언트가 URL을 확인하는 방법에 대한 자세한 사양이 포함되어 있습니다.

URL 표준화

URL을 확인하기 전에 클라이언트는 해당 URL에 대해 일부 표준화를 실행해야 합니다.

먼저 클라이언트가 URL을 파싱하고 RFC 2396에 따라 유효하게 만들었다고 가정합니다. URL이 국제화된 도메인 이름 (IDN)을 사용하는 경우 클라이언트는 URL을 ASCII Punycode 표현으로 변환해야 합니다. URL은 경로 구성요소를 포함해야 합니다. 즉, 도메인 다음에 하나 이상의 슬래시가 있어야 합니다 (http://google.com 대신 http://google.com/).

먼저 URL에서 탭 (0x09), CR (0x0d), LF (0x0a) 문자를 삭제합니다. 이러한 문자의 이스케이프 시퀀스를 삭제하지 마세요 (예: %0a).

둘째, URL이 프래그먼트로 끝나면 프래그먼트를 제거합니다. 예를 들어 http://google.com/#fraghttp://google.com/로 줄입니다.

셋째, 더 이상 퍼센트 이스케이프 처리되지 않을 때까지 URL의 퍼센트 이스케이프 처리를 반복합니다. 이 경우 URL이 유효하지 않게 될 수 있습니다.

호스트 이름을 정규화하려면 다음 안내를 따르세요.

URL에서 호스트 이름을 추출한 후 다음을 수행합니다.

  1. 모든 선행 및 후행 점은 삭제합니다.
  2. 연속된 점을 단일 점으로 바꿉니다.
  3. 호스트 이름을 IPv4 주소로 파싱할 수 있는 경우 4개의 점으로 구분된 십진수 값으로 정규화합니다. 클라이언트는 8진수, 16진수 및 4개 미만의 구성요소를 포함하는 모든 법적 IP 주소 인코딩을 처리해야 합니다.
  4. 호스트 이름을 괄호로 묶은 IPv6 주소로 파싱할 수 있는 경우 구성요소에서 불필요한 선행 0을 삭제하고 이중 콜론 문법을 사용해 구성요소 0개를 축소하여 정규화합니다. 예를 들어 [2001:0db8:0000::1][2001:db8::1]로 변환되어야 합니다. 호스트 이름이 다음 두 가지 특수 IPv6 주소 유형 중 하나이면 IPv4로 변환합니다.
    • 1.2.3.4로 변환해야 하는 IPv4 매핑 IPv6 주소(예: [::ffff:1.2.3.4])
    • 1.2.3.4로 변환해야 하는 [64:ff9b::1.2.3.4]와 같이 잘 알려진 접두사 64:ff9b::/96을 사용하는 NAT64 주소
  5. 전체 문자열을 소문자로 표기합니다.

경로를 정규화하려면 다음 단계를 따르세요.

  1. /.//로 바꾸고 이전 경로 구성요소와 함께 /../를 삭제하여 경로에서 /..//./ 시퀀스를 확인합니다.
  2. 연속된 슬래시 실행을 단일 슬래시 문자로 바꿉니다.

이러한 경로 표준화를 쿼리 매개변수에 적용하지 마세요.

URL에서 ASCII 32, >= 127, #, %에 해당하는 모든 문자를 퍼센트 이스케이프 처리합니다. 이스케이프는 대문자 16진수를 사용해야합니다.

호스트-서픽스 경로-접두어 표현식

URL이 표준화되면 다음 단계는 접미사/접두사 표현식을 만드는 것입니다. 각 서픽스/프리픽스 표현식은 호스트 서픽스 (또는 전체 호스트)와 경로 프리픽스 (또는 전체 경로)로 구성됩니다.

클라이언트는 최대 30개의 가능한 호스트 서픽스 및 경로 프리픽스 조합을 형성합니다. 이러한 조합에는 URL의 호스트 및 경로 구성요소만 사용됩니다. 스키마, 사용자 이름, 비밀번호, 포트는 삭제됩니다. URL에 검색어 매개변수가 포함된 경우 하나 이상의 조합에 전체 경로와 검색어 매개변수가 포함됩니다.

호스트의 경우 클라이언트는 최대 5개의 다른 문자열을 시도합니다. 각 필터는 다음과 같습니다.

  • 호스트 이름이 IPv4 또는 IPv6 리터럴이 아닌 경우, eTLD+1 도메인으로 시작하고 연속적인 선행 구성요소를 추가하여 호스트 이름을 최대 4개까지 구성할 수 있습니다. eTLD+1은 공개 접미사 목록을 토대로 판단해야 합니다. 예를 들어 a.b.example.com의 경우 example.com의 eTLD+1 도메인은 물론 추가 호스트 구성요소 b.example.com가 있는 호스트가 됩니다.
  • URL의 정확한 호스트 이름입니다. 이전 예에 따라 a.b.example.com가 확인됩니다.

경로의 경우 클라이언트는 최대 6개의 다른 문자열을 시도합니다. 각 유형은 다음과 같습니다.

  • 쿼리 매개변수를 포함한 URL의 정확한 경로입니다.
  • 쿼리 매개변수가 없는 URL의 정확한 경로입니다.
  • 루트 (/)에서 시작하고 뒤에 슬래시를 포함하여 경로 구성요소를 연속적으로 추가하여 형성된 4개의 경로입니다.

다음 예시는 확인 동작을 보여줍니다.

URL http://a.b.com/1/2.html?param=1에 대해 클라이언트는 다음과 같은 가능한 문자열을 시도합니다.

a.b.com/1/2.html?param=1
a.b.com/1/2.html
a.b.com/
a.b.com/1/
b.com/1/2.html?param=1
b.com/1/2.html
b.com/
b.com/1/

URL http://a.b.c.d.e.f.com/1.html에 대해 클라이언트는 다음과 같은 가능한 문자열을 시도합니다.

a.b.c.d.e.f.com/1.html
a.b.c.d.e.f.com/
c.d.e.f.com/1.html
c.d.e.f.com/
d.e.f.com/1.html
d.e.f.com/
e.f.com/1.html
e.f.com/
f.com/1.html
f.com/

(참고: 마지막 5개의 호스트 이름 구성요소와 전체 호스트 이름만 사용하므로 b.c.d.e.f.com은 건너뛰세요.)

URL http://1.2.3.4/1/에 대해 클라이언트는 다음과 같은 가능한 문자열을 시도합니다.

1.2.3.4/1/
1.2.3.4/

URL http://example.co.uk/1에 대해 클라이언트는 다음과 같은 가능한 문자열을 시도합니다.

example.co.uk/1
example.co.uk/

해싱

Google 세이프 브라우징은 SHA256을 해시 함수로만 사용합니다. 이 해시 함수는 위의 표현식에 적용되어야 합니다.

전체 32바이트 해시는 상황에 따라 4바이트, 8바이트 또는 16바이트로 잘립니다.

  • hashes.search 메서드를 사용할 때 현재 요청의 해시를 정확히 4바이트로 잘라야 합니다. 이 요청에서 추가 바이트를 전송하면 사용자 개인 정보 보호가 침해됩니다.

  • hashList.get 메서드 또는 hashLists.batchGet 메서드를 사용하여 로컬 데이터베이스 목록을 다운로드할 때 서버에서 전송하는 해시의 길이는 목록의 특성과 desired_hash_length 매개변수로 전달하는 해시 길이에 대한 클라이언트의 환경설정 모두의 영향을 받습니다.

실시간 URL 확인 절차

이 절차는 클라이언트가 실시간 작업 모드를 선택할 때 사용됩니다.

이 절차는 단일 URL u를 사용하고 SAFE, UNSAFE 또는 UNSURE를 반환합니다. SAFE가 반환되면 URL이 Google 세이프 브라우징에서 안전한 것으로 간주됩니다. 이 URL이 UNSAFE를 반환하면 URL은 Google 세이프 브라우징에 의해 잠재적으로 안전하지 않은 것으로 간주되며 최종 사용자에게 경고를 표시하거나, 수신한 메일을 스팸 폴더로 이동하거나, 계속하기 전에 사용자의 추가 확인을 요구하는 등 적절한 조치를 취해야 합니다. UNSURE가 반환되면 나중에 다음 로컬 확인 절차를 사용해야 합니다.

  1. expressions를 URL u에서 생성된 접미사/접두사 표현식의 목록이라고 합니다.
  2. expressionHashes를 목록이라고 가정합니다. 여기서 요소는 expressions에 있는 각 표현식의 SHA256 해시입니다.
  3. expressionHashes의 각 hash에 대해 다음을 실행합니다.
    1. 전역 캐시에서 hash를 찾을 수 있으면 UNSURE를 반환합니다.
  4. expressionHashPrefixes를 목록이라고 가정합니다. 여기서 요소는 expressionHashes에 있는 각 해시의 처음 4바이트입니다.
  5. expressionHashPrefixes의 각 expressionHashPrefix에 대해 다음을 실행합니다.
    1. 로컬 캐시에서 expressionHashPrefix를 조회합니다.
    2. 캐시된 항목이 발견되면 다음을 실행합니다.
      1. 현재 시간이 만료 시간보다 큰지 확인합니다.
      2. 더 큰 경우:
        1. 찾은 캐시된 항목을 로컬 캐시에서 삭제합니다.
        2. 순환을 계속합니다.
      3. 더 크지 않은 경우:
        1. expressionHashPrefixes에서 이 특정 expressionHashPrefix를 삭제합니다.
        2. expressionHashes 내의 상응하는 전체 해시가 캐시된 항목에 있는지 확인합니다.
        3. 찾으면 UNSAFE를 반환합니다.
        4. 찾을 수 없는 경우 루프를 계속 진행합니다.
    3. 캐시된 항목을 찾을 수 없는 경우 루프를 계속 진행합니다.
  6. RPC SearchHashes 또는 REST 메서드 hashes.search를 사용하여 expressionHashPrefixes를 Google 세이프 브라우징 v5 서버로 전송합니다. 네트워크 오류, HTTP 오류 등의 오류가 발생하면 UNSURE를 반환합니다. 그 외의 경우에는 응답이 SB 서버에서 수신된 response이 되도록 합니다. SB 서버는 전체 해시 목록과 위협의 성격(소셜 엔지니어링, 멀웨어 등) 및 캐시 만료 시간(expiration)을 식별하는 보조 정보 목록입니다.
  7. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expiration와 함께 로컬 캐시에 fullHash를 삽입합니다.
  8. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expressionHashes에서 fullHash를 찾은 결과가 isFound라고 합시다.
    2. isFound가 False인 경우 루프를 계속 진행합니다.
    3. isFound가 True이면 UNSAFE를 반환합니다.
  9. SAFE를 반환합니다.

이 프로토콜은 클라이언트가 expressionHashPrefixes를 서버로 보내는 시점을 지정하지만, 이 프로토콜은 메시지를 전송하는 정확한 방법을 의도적으로 지정하지 않습니다. 예를 들어 클라이언트는 단일 요청으로 모든 expressionHashPrefixes를 전송할 수 있으며, 클라이언트가 expressionHashPrefixes의 개별 접두사를 별도의 요청으로 서버에 보내는 것도 허용됩니다 (동시에 진행할 수 있음). 단일 요청으로 전송된 해시 프리픽스 수가 30개를 초과하지 않는 한 클라이언트가 관련이 없거나 무작위로 생성된 해시 프리픽스를 expressionHashPrefixes의 해시 프리픽스와 함께 전송하는 것도 허용됩니다.

LocalThreat List URL 확인 절차

이 절차는 클라이언트가 로컬 목록 작업 모드를 선택할 때 사용됩니다. 이 이벤트는 위의 RealTimeCheck 프로시져가 UNSURE 값을 반환할 때도 사용됩니다.

이 절차는 단일 URL u를 사용하고 SAFE 또는 UNSAFE를 반환합니다.

  1. expressions를 URL u에서 생성된 접미사/접두사 표현식의 목록이라고 합니다.
  2. expressionHashes를 목록이라고 가정합니다. 여기서 요소는 expressions에 있는 각 표현식의 SHA256 해시입니다.
  3. expressionHashPrefixes를 목록이라고 가정합니다. 여기서 요소는 expressionHashes에 있는 각 해시의 처음 4바이트입니다.
  4. expressionHashPrefixes의 각 expressionHashPrefix에 대해 다음을 실행합니다.
    1. 로컬 캐시에서 expressionHashPrefix를 조회합니다.
    2. 캐시된 항목이 발견되면 다음을 실행합니다.
      1. 현재 시간이 만료 시간보다 큰지 확인합니다.
      2. 더 큰 경우:
        1. 찾은 캐시된 항목을 로컬 캐시에서 삭제합니다.
        2. 순환을 계속합니다.
      3. 더 크지 않은 경우:
        1. expressionHashPrefixes에서 이 특정 expressionHashPrefix를 삭제합니다.
        2. expressionHashes 내의 상응하는 전체 해시가 캐시된 항목에 있는지 확인합니다.
        3. 찾으면 UNSAFE를 반환합니다.
        4. 찾을 수 없는 경우 루프를 계속 진행합니다.
    3. 캐시된 항목을 찾을 수 없는 경우 루프를 계속 진행합니다.
  5. expressionHashPrefixes의 각 expressionHashPrefix에 대해 다음을 실행합니다.
    1. 로컬 위협 목록 데이터베이스에서 expressionHashPrefix를 조회합니다.
    2. 로컬 위협 목록 데이터베이스에서 expressionHashPrefix를 찾을 수 없으면 expressionHashPrefixes에서 삭제합니다.
  6. RPC SearchHashes 또는 REST 메서드 hashes.search를 사용하여 expressionHashPrefixes를 Google 세이프 브라우징 v5 서버로 전송합니다. 네트워크 오류, HTTP 오류 등의 오류가 발생하면 SAFE를 반환합니다. 그 외의 경우에는 응답이 SB 서버에서 수신된 response이 되도록 합니다. SB 서버는 전체 해시 목록과 위협의 성격(소셜 엔지니어링, 멀웨어 등) 및 캐시 만료 시간(expiration)을 식별하는 보조 정보 목록입니다.
  7. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expiration와 함께 로컬 캐시에 fullHash를 삽입합니다.
  8. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expressionHashes에서 fullHash를 찾은 결과가 isFound라고 합시다.
    2. isFound가 False인 경우 루프를 계속 진행합니다.
    3. isFound가 True이면 UNSAFE를 반환합니다.
  9. SAFE를 반환합니다.

로컬 데이터베이스가 없는 실시간 URL 확인 절차

이 절차는 클라이언트가 스토리지 없는 실시간 작업 모드를 선택할 때 사용됩니다.

이 절차는 단일 URL u를 사용하고 SAFE 또는 UNSAFE를 반환합니다.

  1. expressions를 URL u에서 생성된 접미사/접두사 표현식의 목록이라고 합니다.
  2. expressionHashes를 목록이라고 가정합니다. 여기서 요소는 expressions에 있는 각 표현식의 SHA256 해시입니다.
  3. expressionHashPrefixes를 목록이라고 가정합니다. 여기서 요소는 expressionHashes에 있는 각 해시의 처음 4바이트입니다.
  4. expressionHashPrefixes의 각 expressionHashPrefix에 대해 다음을 실행합니다.
    1. 로컬 캐시에서 expressionHashPrefix를 조회합니다.
    2. 캐시된 항목이 발견되면 다음을 실행합니다.
      1. 현재 시간이 만료 시간보다 큰지 확인합니다.
      2. 더 큰 경우:
        1. 찾은 캐시된 항목을 로컬 캐시에서 삭제합니다.
        2. 순환을 계속합니다.
      3. 더 크지 않은 경우:
        1. expressionHashPrefixes에서 이 특정 expressionHashPrefix를 삭제합니다.
        2. expressionHashes 내의 상응하는 전체 해시가 캐시된 항목에 있는지 확인합니다.
        3. 찾으면 UNSAFE를 반환합니다.
        4. 찾을 수 없는 경우 루프를 계속 진행합니다.
    3. 캐시된 항목을 찾을 수 없는 경우 루프를 계속 진행합니다.
  5. RPC SearchHashes 또는 REST 메서드 hashes.search를 사용하여 expressionHashPrefixes를 Google 세이프 브라우징 v5 서버로 전송합니다. 네트워크 오류, HTTP 오류 등의 오류가 발생하면 SAFE를 반환합니다. 그 외의 경우에는 응답이 SB 서버에서 수신된 response이 되도록 합니다. SB 서버는 전체 해시 목록과 위협의 성격(소셜 엔지니어링, 멀웨어 등) 및 캐시 만료 시간(expiration)을 식별하는 보조 정보 목록입니다.
  6. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expiration와 함께 로컬 캐시에 fullHash를 삽입합니다.
  7. response의 각 fullHash에 대해 다음을 실행합니다.
    1. expressionHashes에서 fullHash를 찾은 결과가 isFound라고 합시다.
    2. isFound가 False인 경우 루프를 계속 진행합니다.
    3. isFound가 True이면 UNSAFE를 반환합니다.
  8. SAFE를 반환합니다.

실시간 URL 확인 절차와 마찬가지로 이 절차에서는 서버에 해시 접두사를 전송할 정확한 방법을 지정하지 않습니다. 예를 들어 클라이언트는 단일 요청으로 모든 expressionHashPrefixes를 전송할 수 있으며, 클라이언트가 expressionHashPrefixes의 개별 접두사를 별도의 요청으로 서버에 보내는 것도 허용됩니다 (동시에 진행할 수 있음). 단일 요청으로 전송된 해시 프리픽스 수가 30개를 초과하지 않는 한 클라이언트가 관련이 없거나 무작위로 생성된 해시 프리픽스를 expressionHashPrefixes의 해시 프리픽스와 함께 전송하는 것도 허용됩니다.

로컬 데이터베이스 유지보수

Google 세이프 브라우징 v5에서는 클라이언트가 스토리지 없는 실시간 모드를 선택하는 경우를 제외하고 로컬 데이터베이스를 유지해야 합니다. 이 로컬 데이터베이스의 형식과 스토리지는 클라이언트에 따라 다릅니다. 이 로컬 데이터베이스의 콘텐츠는 다양한 목록을 파일로 포함하는 폴더로 개념적으로 생각할 수 있으며, 이러한 파일의 콘텐츠는 SHA256 해시 또는 해시 접두사입니다.

데이터베이스 업데이트

클라이언트는 정기적으로 hashList.get 메서드 또는 hashLists.batchGet 메서드를 호출하여 데이터베이스를 업데이트합니다. 일반적인 클라이언트는 한 번에 여러 목록을 업데이트하려고 하므로 hashLists.batchGet 메서드를 사용하는 것이 좋습니다.

목록은 고유한 이름으로 식별됩니다. 이름은 몇 자 길이의 짧은 ASCII 문자열입니다.

목록이 위협 유형의 튜플로 식별되는 V4와 달리, v5에서는 플랫폼 유형, 위협 항목 유형이 이름으로 식별됩니다. 이는 여러 v5 목록이 동일한 위협 유형을 공유할 수 있는 경우에 유연성을 제공합니다. 플랫폼 유형 및 위협 항목 유형은 v5에서 삭제되었습니다.

목록의 이름은 한 번 선택되고 나면 절대 변경되지 않습니다. 또한 한 번 표시된 목록은 삭제되지 않습니다 (목록이 더 이상 유용하지 않을 경우 비어 있지만 계속 존재함). 따라서 Google 세이프 브라우징 클라이언트 코드에 이러한 이름을 하드 코딩하는 것이 좋습니다.

hashList.get 메서드hashLists.batchGet 메서드 모두 증분 업데이트를 지원합니다. 증분 업데이트를 사용하면 대역폭이 절약되고 성능이 향상됩니다. 증분 업데이트는 클라이언트의 목록과 최신 버전의 목록 간 델타를 전송하는 방식으로 작동합니다. (클라이언트가 새로 배포되었고 사용 가능한 버전이 없는 경우 전체 업데이트를 사용할 수 있습니다.) 증분 업데이트에는 삭제 색인 및 추가 항목이 포함됩니다. 클라이언트는 먼저 로컬 데이터베이스에서 지정된 색인의 항목을 삭제한 다음 추가 항목을 적용해야 합니다.

마지막으로, 손상을 방지하기 위해 클라이언트는 저장된 데이터를 서버에서 제공한 체크섬과 비교하여 확인해야 합니다. 체크섬이 일치하지 않을 때마다 클라이언트는 전체 업데이트를 실행해야 합니다.

목록 콘텐츠 디코딩

해시 및 해시 프리픽스 디코딩

모든 목록은 크기를 줄이기 위해 특수한 인코딩을 사용하여 제공됩니다. 이 인코딩은 Google 세이프 브라우징 목록에 개념적으로 임의의 정수와 통계적으로 구분되지 않는 해시 또는 해시 접두사의 집합이 포함되어 있음을 인식하는 방식으로 작동합니다. 이러한 정수를 정렬하고 인접한 차이를 취하면 이 인접한 차이는 어떤 의미에서 '작은' 것으로 예상됩니다. 그런 다음 Golomb-Rice 인코딩은 이러한 작은 크기를 이용합니다.

4바이트 해시 프리픽스를 사용하여 세 개의 호스트 서픽스 경로 접두사 표현식(a.example.com/, b.example.com/, y.example.com/)을 전송한다고 가정해 보겠습니다. 또한 k로 표시된 쌀 매개변수가 30으로 선택되었다고 가정해 보겠습니다. 서버는 먼저 이러한 문자열의 전체 해시를 계산하며, 각 해시는 다음과 같습니다.

291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc  a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c  b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03  y.example.com/

그런 다음 서버는 위의 각 항목에 대해 4바이트 해시 접두사를 형성합니다. 이는 32바이트 전체 해시의 처음 4바이트이며, big-endian 32비트 정수로 해석됩니다. 빅 엔디언이란 전체 해시의 첫 번째 바이트가 32비트 정수의 최상위 바이트가 된다는 사실을 의미합니다. 이 단계에서 정수 0x291bc542, 0x1d32c508, 0xf7a502e5가 생성됩니다.

서버는 3개의 해시 접두사를 사전순으로 정렬해야 하며 (빅 엔디언의 숫자 정렬과 동일), 정렬 결과는 0x1d32c508, 0x291bc542, 0xf7a502e5입니다. 첫 번째 해시 접두사는 first_value 필드에 변경되지 않고 저장됩니다.

그런 다음 서버는 두 개의 인접한 차이(각각 0xbe9003a 및 0xce893da3)를 계산합니다. k가 30으로 선택된 경우 서버는 이 두 숫자를 각각 2비트와 30비트 길이인 몫 부분과 나머지 부분으로 분할합니다. 첫 번째 숫자의 경우 몫 부분은 0이고 나머지는 0xbe9003a입니다. 두 번째 숫자의 경우 최상위 두 비트가 2진수로 11이고 나머지가 0xe893da3이기 때문에 몫 부분은 3입니다. 지정된 몫 q의 경우 정확히 1 + q비트를 사용하여 (1 << q) - 1로 인코딩되고 나머지는 k비트를 사용하여 직접 인코딩됩니다.

이 숫자가 바이트 문자열로 형성되면 Little Endian이 사용됩니다. 개념적으로는 최하위 비트부터 시작하여 긴 비트 문자열이 형성되는 것을 상상하는 것이 더 쉬울 수 있습니다. 첫 번째 숫자의 몫 부분을 취하고 첫 번째 숫자의 나머지 부분을 앞에 붙입니다. 그런 다음 두 번째 숫자의 몫 부분과 나머지 부분을 앞에 추가합니다. 이렇게 하면 다음과 같이 크게 표시됩니다 (명확히 하기 위해 줄바꿈 및 주석 추가).

001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part

한 줄로 작성하면

00111010001001001111011010001101110010111110100100000000001110100

분명히 이 숫자는 단일 바이트에서 사용할 수 있는 8 비트를 훨씬 초과합니다. 그러면 리틀 엔디언 인코딩은 해당 숫자에서 최하위 8비트를 가져와 첫 번째 바이트인 01110100으로 출력합니다. 명확하게 말하면, 위의 비트 문자열을 최하위 비트부터 시작하여 8개의 그룹으로 그룹화할 수 있습니다.

0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100

그런 다음 리틀 엔디언 인코딩은 오른쪽에서 각 바이트를 가져와 바이트 문자열에 넣습니다.

01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000

왼쪽의 큰 숫자에는 개념적으로 새 부분을 prepend하지만 (즉, 더 중요한 비트를 추가) 오른쪽에서 인코딩 (최하위 비트)하므로 인코딩과 디코딩이 점진적으로 수행될 수 있습니다.

이렇게 하면 최종적으로

additions_four_bytes {
  first_value: 489866504
  rice_parameter: 30
  entries_count: 2
  encoded_data: "t\000\322\227\033\355It\000"
}

클라이언트는 위의 단계를 역순으로 따라 해시 프리픽스를 디코딩합니다. v4와 달리 해시 접두사 정수가 Big Endian으로 해석되기 때문에 끝에 바이트 스왑을 실행할 필요가 없습니다.

디코딩 삭제 색인

삭제 색인은 32비트 정수를 사용하여 위와 동일한 기법으로 인코딩됩니다. v4와 v5에서는 삭제 색인의 인코딩 및 디코딩이 변경되지 않았습니다.

사용 가능한 목록

v5alpha1에서 다음 목록을 사용하는 것이 좋습니다.

목록 이름 해당 v4 ThreatType enum 설명
gc 없음 이 목록은 전역 캐시 목록입니다. 실시간 작업 모드에서만 사용되는 특수 목록입니다.
se SOCIAL_ENGINEERING 이 목록에는 SOCIAL_ENGINEERING 위협 유형의 위협이 포함되어 있습니다.
mw MALWARE 이 목록에는 데스크톱 플랫폼에 대한 멀웨어 위협 유형의 위협이 포함되어 있습니다.
uws UNWANTED_SOFTWARE 이 목록에는 데스크톱 플랫폼에 대한 UNWANTED_SOFTWARE 위협 유형의 위협이 포함되어 있습니다.
uwsa UNWANTED_SOFTWARE 이 목록에는 Android 플랫폼에 대한 UNWANTED_SOFTWARE 위협 유형의 위협이 포함되어 있습니다.
pha POTENTIALLY_HARMFUL_APPLICATION 이 목록에는 Android 플랫폼에 대한 POTENTIALLY_HARMFUL_APPLICATION 위협 유형의 위협이 포함되어 있습니다.

나중에 추가 목록이 제공될 예정이며, 그때 위의 표가 확장될 예정입니다.

클라이언트가 캐싱 프록시 서버를 작동하여 위의 목록의 일부 또는 전체를 검색한 다음 클라이언트가 프록시 서버에 연결하도록 할 수 있습니다. 이 기능이 구현되는 경우 캐시 기간을 5분 등으로 짧게 설정하는 것이 좋습니다. 이후에는 표준 Cache-Control HTTP 헤더를 사용하여 이 캐시 기간을 전달할 수도 있습니다.

업데이트 빈도

클라이언트는 minimum_wait_duration 필드에 있는 서버의 반환된 값을 검사하고 이를 사용하여 데이터베이스의 다음 업데이트를 예약해야 합니다. 이 값은 0일 수 있으며(minimum_wait_duration 필드가 완전히 누락됨) 이 경우 클라이언트는 즉시 또 다른 업데이트를 실행해야 합니다(SHOULD).

예시 요청

이 섹션에서는 HTTP API를 직접 사용하여 Google 세이프 브라우징에 액세스하는 몇 가지 예를 설명합니다. 일반적으로 생성된 언어 바인딩을 사용하는 것이 좋습니다. 편리한 방법으로 인코딩 및 디코딩을 자동으로 처리하기 때문입니다. 해당 바인딩에 대한 문서를 참조하세요.

다음은 hashes.search 메서드를 사용하는 HTTP 요청의 예입니다.

GET https://safebrowsing.googleapis.com/v5/hashes:search?key=INSERT_YOUR_API_KEY_HERE&hashPrefixes=WwuJdQ

응답 본문은 개발자가 디코딩할 수 있는 프로토콜 버퍼 형식의 페이로드입니다.

다음은 hashLists.batchGet 메서드를 사용하는 HTTP 요청의 예입니다.

GET https://safebrowsing.googleapis.com/v5alpha1/hashLists:batchGet?key=INSERT_YOUR_API_KEY_HERE&names=se&names=mw

응답 본문은 여기서도 디코딩할 수 있는 프로토콜 버퍼 형식의 페이로드입니다.

이전 가이드

현재 v4 Update API를 사용 중인 경우 v4에서 v5로 원활하게 이전할 수 있으며 로컬 데이터베이스를 재설정하거나 삭제하지 않아도 됩니다. 이 섹션에서는 그 방법을 설명합니다.

목록 업데이트 변환

v4에서는 threatListUpdates.fetch 메서드를 사용하여 목록을 다운로드합니다. v5에서는 hashLists.batchGet 메서드로 전환됩니다.

요청을 다음과 같이 변경해야 합니다.

  1. v4 ClientInfo 객체를 모두 삭제합니다. 전용 필드를 사용하여 클라이언트 ID를 제공하는 대신 잘 알려진 사용자 에이전트 헤더를 사용하면 됩니다. 이 헤더에 클라이언트 ID를 제공하기 위한 지정된 형식은 없지만, 공백 문자 또는 슬래시 문자로 구분해 원래 클라이언트 ID와 클라이언트 버전을 포함하는 것이 좋습니다.
  2. v4 ListUpdateRequest 객체에 대해 다음을 수행합니다.
    • 위의 표에서 해당하는 v5 목록 이름을 찾고 v5 요청에 이 이름을 제공합니다.
    • threat_entry_type 또는 platform_type와 같은 불필요한 필드를 삭제합니다.
    • v4의 state 필드는 v5 versions 필드와 직접 호환됩니다. v4에서 state 필드를 사용하여 서버로 전송되는 동일한 바이트 문자열은 versions 필드를 사용하여 v5에서 간단하게 전송할 수 있습니다.
    • v4 제약조건의 경우 v5는 SizeConstraints라는 간소화된 버전을 사용합니다. region와 같은 추가 필드는 삭제해야 합니다.

응답을 다음과 같이 변경해야 합니다.

  1. v4 enum ResponseType은 단순히 partial_update라는 불리언 필드로 대체됩니다.
  2. 이제 minimum_wait_duration 필드는 0이 되거나 생략될 수 있습니다. 설정된 경우 클라이언트는 즉시 다른 요청을 하도록 요청됩니다. 이는 클라이언트가 SizeConstraints에서 최대 데이터베이스 크기보다 더 작은 제약조건을 최대 업데이트 크기에 지정하는 경우에만 발생합니다.
  3. 32비트 정수의 Rice 디코딩 알고리즘을 조정해야 합니다. 차이점은 인코딩된 데이터가 다른 엔디언으로 인코딩된다는 것입니다. v4와 v5에서 모두 32비트 해시 접두사는 사전순으로 정렬됩니다. 그러나 v4에서는 이러한 접두사가 정렬될 때 리틀 엔디언으로 취급되는 반면, v5에서는 이러한 접두사가 정렬될 때 빅 엔디언으로 취급됩니다. 즉, 사전순 정렬은 빅 엔디언을 사용한 숫자 정렬과 동일하므로 클라이언트에서 어떠한 정렬도 수행할 필요가 없습니다. v4의 Chromium 구현에서 이러한 종류의 예는 여기에서 확인할 수 있습니다. 이러한 정렬은 삭제할 수 있습니다.
  4. Rice 디코딩 알고리즘을 다른 해시 길이에 구현해야 합니다.

해시 검색 변환

v4에서는 fullHashes.find 메서드를 사용하여 전체 해시를 가져옵니다. v5의 동일한 메서드는 hashes.search 메서드입니다.

요청을 다음과 같이 변경해야 합니다.

  1. 길이가 정확히 4바이트인 해시 프리픽스만 전송하도록 코드를 구성합니다.
  2. v4 ClientInfo 객체를 모두 삭제합니다. 전용 필드를 사용하여 클라이언트 ID를 제공하는 대신 잘 알려진 사용자 에이전트 헤더를 사용하면 됩니다. 이 헤더에 클라이언트 ID를 제공하기 위한 지정된 형식은 없지만, 공백 문자 또는 슬래시 문자로 구분해 원래 클라이언트 ID와 클라이언트 버전을 포함하는 것이 좋습니다.
  3. client_states 필드를 삭제합니다. 더 이상 필요하지 않습니다.
  4. 더 이상 threat_types 및 유사한 필드를 포함하지 않아도 됩니다.

응답을 다음과 같이 변경해야 합니다.

  1. minimum_wait_duration 필드가 삭제되었습니다. 고객은 언제든지 필요에 따라 새 요청을 보낼 수 있습니다.
  2. v4 ThreatMatch 객체FullHash 객체로 간소화되었습니다.
  3. 캐싱이 단일 캐시 기간으로 간소화되었습니다. 캐시와 상호작용하려면 위의 절차를 참조하세요.