사이드 채널 공격은 시스템 자체에서 얻은 정보를 기반으로 하는 보안 공격입니다. 필요한 것보다 더 광범위한 권한을 가진 공격자는 청구, 로깅 또는 시스템 메시지를 관찰 또는 검색하여 부채널 공격을 마운트하고 민감한 정보를 학습할 수 있습니다.
이러한 학습 기회를 차단하기 위해 BigQuery는 행 수준 보안을 갖춘 테이블에 대한 모든 쿼리의 민감한 통계를 숨깁니다.
이러한 민감한 통계에는 처리된 바이트 및 파티션 수, 청구 대상 바이트 수, 쿼리 계획 단계가 포함됩니다.
관리자는 민감한 정보에 대한 액세스 권한을 부여하지 않도록 필터링된 데이터만 확인해야 하는 사용자에게 다음 권한을 부여하지 않는 것이 좋습니다.
권한
민감한 정보
프로젝트 소유자
프로젝트 소유자는 감사 로그에서만 처리된 바이트 및 관련 데이터를 볼 수 있습니다.
결제 메타데이터는 작업 세부정보에서 볼 수 없습니다. 이 결제 메타데이터에 대한 보기 권한을 부여하는 특정 권한이나 역할은 없습니다.
BigQuery 데이터 수정, 소유자, 뷰어 역할
쿼리의 오류 메시지를 봅니다.
Cloud Billing 뷰어 권한
BigQuery 결제를 봅니다.
예시
행 수준 액세스 정책이 있는 테이블을 쿼리할 때 쿼리 기간을 반복적으로 관찰하여 사용자가 행 수준 액세스 정책으로 보호할 수 있는 행의 값을 추론할 수 있습니다. 이 유형의 공격에는 파티션 나누기 또는 클러스터링 열의 키 값 범위에 대해 다수의 반복된 시도가 필요합니다. 쿼리 기간을 관찰하거나 측정할 때 노이즈가 있더라도 공격자가 반복 시도를 통해 신뢰할 수 있는 예상치를 얻을 수 있습니다. 이 보호 수준에 민감한 경우 다른 액세스 제어 요구사항이 있는 행을 격리하기 위해 별도의 테이블을 사용하는 것이 좋습니다.
공격자는 쿼리 작업 한도(예: 청구 가능한 최대 바이트 또는 커스텀 비용 관리)를 초과할 때 발생하는 오류를 모니터링하여 쿼리에서 처리된 바이트를 검색할 수 있습니다. 하지만 이 공격에는 많은 양의 쿼리가 필요합니다.
Cloud Billing에서 반복 쿼리를 통해 BigQuery 결제 금액을 관찰하면 사용자가 행 수준 액세스 정책으로 보호될 수 있는 행 값을 추론할 수 있습니다. 이 유형의 공격에는 파티션 나누기 또는 클러스터링 열의 키 값 범위에 대해 다수의 반복된 시도가 필요합니다. 이 보호 수준에 민감한 경우 쿼리 결제 데이터에 대한 액세스를 제한하는 것이 좋습니다.
또한 관리자는 Cloud 감사 로그(/bigquery/docs/reference/auditlogs)를 모니터링하여 예기치 않은 행 추가, 수정, 행 수준 액세스 정책 삭제와 같은 행 수준 보안이 설정된 테이블에서 의심스러운 활동이 있는지 모니터링하는 것이 좋습니다.
사용자 권한을 제한하여 데이터 조작 제한
테이블에 대한 쓰기 권한이 있는 사용자는 bq load 명령어 또는 BigQuery Storage Write API를 사용하여 테이블에 데이터를 삽입할 수 있습니다. 이렇게 하면 쓰기 권한이 있는 사용자는 다른 사용자의 쿼리 결과를 변경할 수 있습니다.
관리자는 테이블 쓰기 액세스 및 행 수준 액세스 정책에 대해 별도의 Google 그룹을 만드는 것이 좋습니다. 필터링된 테이블 결과만 표시되어야 하는 사용자에게는 필터링된 테이블에 대한 쓰기 액세스 권한이 없어야 합니다.
행 수준 액세스 정책을 다시 만들 때 부적절한 액세스 방지
테이블에 행 액세스 정책을 처음 추가하면 쿼리 결과에서 즉시 데이터 필터링이 시작됩니다. 테이블에서 마지막 행 수준 액세스 정책을 삭제하면 행 수준 액세스 정책만 다시 만들더라도 의도보다 더 광범위한 잠재고객에게 필터링되지 않은 액세스 권한을 부여할 수 있습니다.
관리자는 다음 가이드라인에 따라 테이블에서 마지막 행 수준 액세스 정책을 다시 만들 때 특히 주의해야 합니다.
또는 먼저 테이블에 새 행 수준 액세스 정책을 만든 다음 더 이상 필요하지 않은 이전 행 수준 액세스 정책을 삭제할 수 있습니다.
조직 간이 아닌 조직 내에서만 행 수준 보안 사용
사이드 채널에 의한 데이터 유출을 방지하고 민감한 정보에 대한 액세스를 더 효과적으로 제어하기 위해 조직 전체의 행 수준 보안 기능을 사용하지 마세요.
서브 쿼리 행 수준 액세스 정책의 경우 조직 또는 프로젝트 내에서 테이블을 만들고 검색합니다. 이를 통해 피부여자는 정책의 대상 및 참조된 테이블에 대한 bigquery.tables.getData 권한은 물론 관련 열 수준 보안 권한을 가지고 있어야 하므로 보안이 강화되고 ACL 구성이 더 간단해집니다.
행 수준 보안 기능은 조직 간 보안 제약 조건에만 사용하고(예: 조직/기업/회사 내에서 데이터 공유) 조직 간 또는 공개 보안에는 사용하지 않는 것이 좋습니다.
예시
조직 외부에서는 데이터에 액세스할 수 있는 사용자를 제어할 수 없습니다.
조직 내에서 행 수준 액세스 정책이 있는 테이블에 대한 쿼리 결제 정보에 액세스할 수 있는 사용자를 제어할 수 있습니다. 결제 정보는 사이드 채널 공격을 위한 벡터입니다.
행 수준 액세스 정책을 통해 Filtered Data Viewer 역할 관리
행 수준 액세스 정책을 생성하면 정책의 주 구성원에게 bigquery.filteredDataViewer 역할이 자동으로 부여됩니다. DDL 문을 사용하여 액세스 정책에서 주 구성원만 추가하거나 삭제할 수 있습니다.
bigquery.filteredDataViewer 역할은 IAM을 통해 테이블, 데이터 세트, 프로젝트와 같은 상위 수준 리소스에 부여해서는 안 됩니다. 이러한 방식으로 역할을 부여하면 의도한 제한과 관계없이 해당 범위 내의 모든 행 수준 액세스 정책에 정의된 행을 사용자가 볼 수 있습니다. 행 수준 액세스 정책 필터의 합집합이 전체 테이블을 포함하지 않을 수 있지만 이 방법은 심각한 보안 위험을 초래하고 행 수준 보안의 목적을 저해합니다.
bigquery.filteredDataViewer 역할은 행 수준 액세스 정책을 통해서만 관리하는 것이 좋습니다. 이 메서드는 각 정책에 대해 정의된 필터 조건자를 준수하여 주 구성원에게 bigquery.filteredDataViewer 역할이 암시적으로 올바르게 부여되도록 합니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-04(UTC)"],[[["\u003cp\u003eAvoid granting sensitive permissions like project owner, BigQuery data editor/owner/viewer, or Cloud Billing viewer roles to users who should only access filtered data, to prevent side-channel attacks and data leakage.\u003c/p\u003e\n"],["\u003cp\u003eRefrain from granting table write permissions to users who should only see filtered data to prevent data tampering, and use separate groups for table write access and row-level access policies.\u003c/p\u003e\n"],["\u003cp\u003eWhen managing row-level access policies, avoid using \u003ccode\u003eCREATE OR REPLACE\u003c/code\u003e for the last policy on a table; instead, remove all access, recreate the policies, and then re-enable access to prevent inadvertent unfiltered access.\u003c/p\u003e\n"],["\u003cp\u003eUse row-level security exclusively within your organization, not across organizations, to mitigate the risk of side-channel attacks and to maintain control over sensitive data access.\u003c/p\u003e\n"],["\u003cp\u003eManage the \u003ccode\u003ebigquery.filteredDataViewer\u003c/code\u003e role exclusively through row-level access policies, and avoid applying this role via IAM, to ensure intended restrictions are enforced.\u003c/p\u003e\n"]]],[],null,["# Best practices for row-level security in BigQuery\n=================================================\n\nThis document explains best practices when using\n[row-level security](/bigquery/docs/row-level-security-intro).\n\nBefore you read this document, familiarize yourself with\nrow-level security by reading\n[Introduction to BigQuery row-level security](/bigquery/docs/row-level-security-intro)\nand\n[Working with row-level security](/bigquery/docs/managing-row-level-security).\n\nRestrict user permissions to limit side-channel attacks\n-------------------------------------------------------\n\n| **Best practice:** Don't grant sensitive permissions to users who should only see filtered data.\n\nA side-channel attack is a security attack based on information gained from the\nsystem itself. An attacker with broader permissions than necessary can\nmount side-channel attacks, and learn sensitive data by **observing** or\n**searching** billing, logging, or system messages.\n\nTo mitigate such opportunities, BigQuery hides\nsensitive statistics on all queries against tables with row-level security.\nThese sensitive statistics include the number of bytes and partitions processed,\nthe number of bytes billed, and the query plan stages.\n\n*We recommend that admins should refrain from granting the following permissions\nto users who should only see filtered data, to avoid giving access to sensitive\ndata.*\n\n**Examples**\n\n- Through repeated **observation** of query duration when querying tables with row-level access policies, a user could infer the values of rows that otherwise might be protected by row-level access policies. This type of attack requires many repeated attempts over a range of key values in partitioning or clustering columns. Even though there is inherent noise when observing or measuring query duration, with repeated attempts, an attacker could obtain a reliable estimate. *If you are sensitive to this level\n of protection, we recommend using separate tables to isolate rows with\n different access control requirements, instead.*\n- An attacker could **search** for the bytes processed by a query by monitoring the errors that occur when the query job limits (such as maximum bytes billed or custom cost controls) are exceeded. However, this attack requires a high volume of queries.\n- Through repeated queries and **observing** the BigQuery billing amount in Cloud Billing, a user could infer the values of rows that otherwise might be protected by row-level access policies. This type of attack requires many repeated attempts over a range of key values in partitioning or clustering columns. *If you are sensitive to this level of protection, we recommend that you limit access to billing data for\n queries.*\n\n*We also recommend that admins monitor\nCloud Audit Logs(/bigquery/docs/reference/auditlogs)\nfor suspicious activity on tables with row-level security, such as unexpected\nadditions, modifications, and deletions of row-level access policies.*\n\nRestrict user permissions to limit data tampering\n-------------------------------------------------\n\n| **Best practice:** Don't grant table write permissions to users who should only see filtered data.\n\nUsers with write permissions to a table can insert data into the table with the\n[`bq load` command](/bigquery/docs/reference/bq-cli-reference#bq_load) or with\nthe BigQuery Storage Write API. This can allow the user with\nwrite permissions to alter the query results of other users.\n\n*We recommend that admins create separate Google groups for table write access\nand row-levels access policies. Users that should only see filtered table\nresults shouldn't have write access to the filtered table.*\n\nAvoid inadvertent access when re-creating row-level access policies\n-------------------------------------------------------------------\n\n| **Best practice:** If there is only one row-level access policy on a table, don't recreate that row-level access policy with the `CREATE OR REPLACE` command. Instead, first remove all access to the table with table access controls, recreate the policies as needed, and then re-enable access.\n\nWhen you add a row access policy on a table for the first time, you immediately\nbegin filtering data in query results. When you remove the last row-level access\npolicy on a table, even if you intend to only re-create the row-level access\npolicy, you may inadvertently grant unfiltered access to a wider-than-intended\naudience.\n\n*We recommend that admins pay special attention when recreating the last\nrow-level access policy on a table, by following these guidelines:*\n\n1. First remove all access to the table, by using [table access controls](/bigquery/docs/control-access-to-resources-iam).\n2. Remove all row-level access policies.\n3. Re-create the row-level access policies.\n4. Re-enable access to the table.\n\nAlternatively, you can first create new row-level access policies on the table,\nthen delete the earlier row-level access policies that are no longer needed.\n\nUse row-level security only within organizations, not across organizations\n--------------------------------------------------------------------------\n\n| **Best practice:** Only use row-level security within your organization.\n\nDon't use the row-level security feature across organizations, to help prevent\ndata leakage through side-channel attacks, and to maintain greater control over\naccess to sensitive data.\n\nFor subquery row-level access policies, create and search tables within\norganizations or projects. This leads to better security and simpler ACL\nconfiguration, as grantees must have the `bigquery.tables.getData` permission on\nthe target and referenced tables in policies, as well as any relevant\n[column-level security](/bigquery/docs/column-level-security-intro) permissions.\n\n*We recommend using row-level security feature for within-organization\nsecurity constraints only (such as for sharing data within an\norganization/enterprise/company), and not for cross-organizational or public\nsecurity.*\n\n**Example**\n\nOutside of your organization, you have less control over who has access to data.\nWithin your organization, you can control who has been granted access to billing\ninformation of queries against tables with row-level access policies. Billing\ninformation is a vector for [side-channel attacks](#limit-side-channel-attacks).\n\nManage the `Filtered Data Viewer` role through row-level access policies\n------------------------------------------------------------------------\n\n| **Best practice:** `bigquery.filteredDataViewer` is a system-managed role granted through row-level access policies. Manage the role only through row-level access policies. Don't apply the role through Identity and Access Management (IAM).\n\nWhen you\n[create a row-level access policy](/bigquery/docs/managing-row-level-security#create-policy),\nthe principals in the policy are automatically granted the\n`bigquery.filteredDataViewer` role. You can only add or remove principals from\nthe access policy\n[with a DDL statement](/bigquery/docs/managing-row-level-security#examples).\n\nThe `bigquery.filteredDataViewer` role *must not* be granted through\n[IAM](/bigquery/access-control) to a higher-level resource, such\nas a table, dataset, or project. Granting the role in this way lets users\nview rows defined by *all* row-level access policies within that scope,\nregardless of intended restrictions. While the union of row-level access policy\nfilters might not encompass the entire table, this practice poses a significant\nsecurity risk and undermines the purpose of row-level security.\n\nWe recommend managing the `bigquery.filteredDataViewer` role exclusively through\nrow-level access policies. This method ensures that principals are granted the\n`bigquery.filteredDataViewer` role implicitly and correctly, respecting the\ndefined filter predicates for each policy.\n\nPerformance impact of filters on partitioned columns\n----------------------------------------------------\n\n| **Best practice:** Try to avoid making row access policies that filter on clustered and partitioned columns.\n\nRow-level access policy filters don't participate in query\n[pruning on partitioned and clustered tables](/bigquery/docs/using-row-level-security-with-features#partitioned_and_clustered_tables).\n\nIf your row-level access policy names a partitioned column, your query does not\nreceive the performance benefits of query pruning."]]