May 1, 2025

glooseRPC - A vrnCTF Writeup

Мы рады сообщить пользователям слабых компьютеров, что мы наконец-то перенесли редактирование изображений на сервер. Обрезайте картинки и загоняйте их в ромбы еще быстрее, чем раньше!

Спидран по эндпоинтам

cd tasks/web/glooseRPC/deploy/
docker compose up --build

Открываем сайт, распаковываем любимую тулзу - Burp, Postman или встроенный отладчик в браузер. Я, например, фанат связки Postman + Postman Interceptor.

Посмотрим в Postman как сайт режет картинки:

gRPC в URL и X-Grpc-Web: 1 в заголовках - худшие подозрения подтвердились: действительно кто-то использовал gRPC и завернул его в веб через Envoy! Узнать методы через рефлексию простым grpcurl list не получится...

...к счастью нам в комплекте шел proto-файл

syntax = "proto3";

package imageservice;

service ImageService {
  rpc CropSquare(ImageRequest) returns (ImageResponse);
  rpc CropCircular(ImageRequest) returns (ImageResponse);
  rpc CropRhombus(ImageRequest) returns (ImageResponse);
  rpc GetFlag(FlagRequest) returns (FlagResponse);
}

message ImageRequest {
  bytes image_data = 1;
  int32 width = 2;
  int32 height = 3;
  string api_key = 4;
}

message ImageResponse {
  bytes image_data = 1;
  string message = 2;
}

message FlagRequest {
  string api_key = 1;
}

message FlagResponse {
  string flag = 1;
  string message = 2;
}

Одного взгляда на /imageservice.ImageService/CropSquare хватает, чтобы понять, что нам просто нужно заменить CropSquare на GetFlag:

{
    "flag": "",
    "message": "Nice try, but the secret key is incorrect!"
}

Ах, да, API ключ, который идет со всеми остальными запросами:

{"api_key":"sSG7kA2ir8pgw8pSfHUjVHBnz35YCM95"}

И получаем ⛳

{
    "flag": "vrnctf{Gl00s3_RPC_just_w4nt3d_y0u_to_int3rcept_1t}",
    "message": "Congratulations! You found the hidden method!"
}