如何解密对app-measurement.com的Firebase请求

hen*_*nes 3 encryption ios firebase firebase-analytics

我们注意到我们的iOS应用正在将请求发送到http://app-measurement.com。主体似乎已被加密或压缩

:method: POST
:scheme: https
:path: /a
:authority: app-measurement.com
accept: */*
content-type: application/x-www-form-urlencoded
content-encoding: gzip
accept-language: en-gb
content-length: 371
accept-encoding: br, gzip, deflate


 ;

_uwa

_pfoq


_oauto

_r

_c_fݶ- 
...
Run Code Online (Sandbox Code Playgroud)

我已经检查了它是否是gzip,但事实并非如此。

有谁知道如何解密才能看到请求内容?

Chr*_*ris 6

它是一个 gzip 压缩的协议缓冲区 (protobuf)。使用解码工具,您可以看到所有有用的值和类型。尽管没有 .proto 定义,但很难弄清楚它的含义。

要解码请求,首先以原始形式获取它。我通过导出 HTTP .trace 文件并仅提取正文来完成此操作。我自己进行 gzip 解压的运气更好。

获得原始请求正文后,按如下方式对其进行解码:

$ gunzip - < request_body > request_uncompressed.bin
$ protoc --decode_raw < request_uncompressed.bin
Run Code Online (Sandbox Code Playgroud)

这是一个简单的 Cyber​​Chef 公式,也可以为您解码:https://gchq.github.io/Cyber​​Chef/#recipe=Gunzip()Protobuf_Decode('',false,false)

当它工作时,你会看到原始的 protobuf 值。它们看起来像这样(实际值随机化):

1 {
  1: 1
  2 {
    1 {
      1: "_si"
      3: 161212808641
    }
    1 {
      1: "_et"
      3: 57
    }
    1 {
      1: "_sc"
      2: "SomeControllerName"
    }
    1 {
      1: "_o"
      2: "auto"
    }
    2: "_e"
    3: 161236824
    4: 163120534
  }
  2 {
    1 {
      1: "_si"
      3: 1358166110
    }
    1 {
      1: "_sc"
      2: "SomeControllerName"
    }
    1 {
      1: "_o"
      2: "auto"
    }
    2: "_ab"
    3: 161336826
    4: 163123680
  }
  3 {
    1: 163129524107
    2: "_fi"
    4: 1
  }
  3 {
    1: 15514295
    2: "_fot"
    4: 15514241
  }
  3 {
    1: 1530783276
    2: "_sid"
    4: 1530783376
  }
...
  8: "ios"
  9: "13.5"
  10: "iPhone12,3"
...
Run Code Online (Sandbox Code Playgroud)

来自 @lari 的更新:创建自定义 protobuf 定义来解码请求

在 Android 上,您可以启用详细日志记录,并在设备日志中查看 Firebase Analytics 以原始格式发送到服务器的内容。这是一个例子:

FA-SVC com.google.android.gms V Uploading data. app, uncompressed size, data: com.my.app, 9332, 
batch {
  bundle {
    protocol_version: 1
    platform: android
    gmp_version: 46000
    config_version: 1679644809123456
    gmp_app_id: 1:123456789:android:aaaaaaaaaa
    app_id: com.my.app
    app_version: 1.0.0
    app_version_major: 100
    firebase_instance_id: xx_xxxx_xx
    upload_timestamp_millis: 1681470819289
    start_timestamp_millis: 1681468977430
    app_instance_id: f8s9fa09vsa4a4lk2983fsdf
    os_version: 9
    user_property {
      set_timestamp_millis: 1631520687985
      name: first_open_time(_fot)
      string_value: 
      int_value: 1631523600000
    }
    user_property {
      set_timestamp_millis: 1681468712345
      name: ga_session_id(_sid)
      string_value: 
      int_value: 1681468788
    }
    event {
      name: user_engagement(_e)
      timestamp_millis: 1681468977430
      previous_timestamp_millis: 1681468884057
      param {
        name: ga_event_origin(_o)
        string_value: auto
      }
      param {
        name: engagement_time_msec(_et)
        string_value: 
        int_value: 90654
      }
      param {
        name: ga_screen_class(_sc)
        string_value: MyViewController
      }
      param {
        name: ga_screen_id(_si)
        string_value: 
        int_value: -13918239812398123
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

通过将其与编码版本(以数字作为键的版本)进行比较,您可以非常轻松地重新创建 .proto 定义的部分内容。

例如:

  • 根消息称为“批处理”
  • 批次中的“1”为“捆绑”
  • 捆绑包中的“2”是“事件”
  • 事件中的“2”是“名称”

等等...

在此基础上,您可以创建自定义定义,例如:

// app-measurement.proto
syntax = "proto3";

package app_measurement;

message Bundle {
    message Event {
        string name = 2;
    }
    repeated Event event = 2;    
}

message Batch {
    repeated Bundle bundle = 1;
}
Run Code Online (Sandbox Code Playgroud)

并用它来解码消息:

FA-SVC com.google.android.gms V Uploading data. app, uncompressed size, data: com.my.app, 9332, 
batch {
  bundle {
    protocol_version: 1
    platform: android
    gmp_version: 46000
    config_version: 1679644809123456
    gmp_app_id: 1:123456789:android:aaaaaaaaaa
    app_id: com.my.app
    app_version: 1.0.0
    app_version_major: 100
    firebase_instance_id: xx_xxxx_xx
    upload_timestamp_millis: 1681470819289
    start_timestamp_millis: 1681468977430
    app_instance_id: f8s9fa09vsa4a4lk2983fsdf
    os_version: 9
    user_property {
      set_timestamp_millis: 1631520687985
      name: first_open_time(_fot)
      string_value: 
      int_value: 1631523600000
    }
    user_property {
      set_timestamp_millis: 1681468712345
      name: ga_session_id(_sid)
      string_value: 
      int_value: 1681468788
    }
    event {
      name: user_engagement(_e)
      timestamp_millis: 1681468977430
      previous_timestamp_millis: 1681468884057
      param {
        name: ga_event_origin(_o)
        string_value: auto
      }
      param {
        name: engagement_time_msec(_et)
        string_value: 
        int_value: 90654
      }
      param {
        name: ga_screen_class(_sc)
        string_value: MyViewController
      }
      param {
        name: ga_screen_id(_si)
        string_value: 
        int_value: -13918239812398123
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,您将看到已识别的部分被 .proto 文件中的键名称替换,而其余部分仍保留为数字,例如:

bundle {
  event {
    name: "_e"
    1 {
      1: "_et"
      3: 10856
    }
    1 {
      1: "_o"
      2: "auto"
    }
    3: 1680595820225
    4: 1680595807912
  }
...
Run Code Online (Sandbox Code Playgroud)

如果您需要其他工具的编译“描述符”,您可以使用以下--descriptor_set_out=标志创建它:

// app-measurement.proto
syntax = "proto3";

package app_measurement;

message Bundle {
    message Event {
        string name = 2;
    }
    repeated Event event = 2;    
}

message Batch {
    repeated Bundle bundle = 1;
}
Run Code Online (Sandbox Code Playgroud)

您可能会注意到,Firebase Analytics 还缩短了默认事件、参数和用户属性名称。例如 _e = user_engagement 和 _o = ga_event_origin。原始名称可以在 Android 和 iOS 的设备日志中看到。

我已经为 app-measurement.com 请求创建并发布了协议缓冲区定义的开源版本,并在 GitHub 中共享: https: //github.com/lari/firebase-ga4-app-measurement-protobuf

还有一篇博客文章提供了更多详细信息:https://larihaataja.com/firebase-ga4-app-measurement-com-calls/


Fra*_*len 5

在这里放火

此请求是Google Analytics for Firebase的一部分,用于报告来自客户端的分析事件。它经过高度压缩以最大程度地减少带宽使用。

没有API可以查看请求的原始内容,但是您可以在这里找到有关所收集数据的更多信息:

  1. 有关自动收集的事件自动收集的用户属性的文档。
  2. BigQuery的模式是我们所收集的(虽然这也包括一些字段被添加到服务器上,如位置信息和流量来源,在某些情况下)一个相当不错的表现。
  3. 设备日志(例如logcat)公开了我们记录的事件/参数。