Skip to content

Harden instrumentation socket: auth token / drop dill on the wire #1179

Description

@vringar

Summary

The instrumentation sockets that carry all measurement records from the
WebExtension to the Python StorageController (and the reverse control channel)
are loopback-only, random-ephemeral-port, and not reachable from web content or
off-host
— but they are unauthenticated and carry no transport security.

Concretely:

  • StorageController binds ("localhost", 0) (AF_INET, random port) and hands
    the (host, port) to the extension via the profile directory
    (browser_params.json). The extension's reverse listener binds
    init(-1, true, -1) (loopback-only, random port) and publishes its port via
    extension_port.txt.
  • The first client message is just a name string (Browser-<id> /
    custom_command), not a secret. There is no per-connection token.

Impact

Any local process running as the same (or a more privileged) user, during
the window the port is open, can:

  1. Connect to the StorageController loopback port and inject/forge framed
    records (>Lc header + JSON [instrument, record]), poisoning the dataset or
    forging Initialize/Finalize control events.
  2. In the dill-enabled in-process path, send a d-tagged frame. _parse in
    openwpm/socket_interface.py deserializes d frames via dill.loads, which
    is full pickle — i.e. arbitrary code execution in the StorageController
    process.

Risk assessment

  • Acceptable for single-tenant deployments (the typical OpenWPM measurement
    host), where there is no untrusted local user. The sockets are not web-reachable
    and not reachable off-host, so this is a same-user local-process threat only.
  • A real concern on shared / multi-tenant hosts, where an unprivileged
    co-tenant could poison the dataset or, via the dill path, achieve RCE.

This is documented as a known issue in openwpm/socket_interface.py and
docs/Architecture-Internals.md. The current remediation decision is to treat it
as a documented single-tenant known-issue and not change the wire protocol.

Possible hardening (follow-up)

  • Add a per-connection shared secret: the StorageController generates a random
    64-bit token, writes it alongside the address in the (filesystem-protected)
    profile dir, and requires it as the first framed message.
  • Stop accepting d (dill) frames from any peer that has not authenticated, or
    drop dill on the wire entirely in favour of a non-code-executing format for
    the in-process TaskManager -> StorageController path.

References

  • Audit: privileged sockets WebExtension experiment (internal).
  • Related OpenWPM threat-model concern about local data injection.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions