Menu â–¾ â–´

#501 Security hardening: every OpenChronology service shares one Unix account and its secrets

closed
nobody
None
2 days ago
2 days ago
Anonymous
No

Originally created by: athanclark

All services share one Unix account, so a compromise of any of them reaches every secret and the journal group

  • Severity: Low. This is defense in depth and needs code execution in one service first. It widens the reach of two network-facing parsers (the web server and the syslog receiver).
  • Affected: Debian, Ubuntu, Fedora, Rocky and Arch (systemd units), FreeBSD (rc scripts), NixOS module.
  • Location:
  • deploy/debian-server/openchronology.service:10-13.
  • openchronology-syslog.service:10-12, which runs as User=openchronology with its own syslog.env.
  • openchronology-journald.service:10-14, which adds SupplementaryGroups=systemd-journal.
  • deploy/debian-server/journald.env:20-21 (rendered in the env template at lines 211-214), where the SSH key is "readable by the openchronology user".
  • postinst:24 and 35-40 (/etc/openchronology 0750 root:openchronology, files 0640).
  • nix/module.nix:60-64 and 306.
  • Description: The web server, mail worker, syslog receiver (unauthenticated UDP/TCP parser) and journald follower all run as the same UID. Each env file is readable by that UID, so each process can read the others' secrets:
  • openchronology.env: DATABASE_URL, AUTH_ENCRYPTION_KEY, RESEND_API_KEY, OAuth secrets, LDAP bind password, S3 keys, ADMIN_INITIAL_PASSWORD.
  • syslog.env and journald.env: OCH_API_KEY.
  • The journald SSH private key.

The journald follower also holds systemd-journal. With the same UID, and Yama ptrace_scope=0 (Debian's default), the web process can ptrace or write /proc/<pid>/mem of the follower and act with that group.

  • Attack scenario:
  • Precondition: code execution in the syslog receiver, for example through a parser bug reached over UDP from any host that can send to it.
  • Steps: read /etc/openchronology/openchronology.env, then use DATABASE_URL (peer authentication as the same UID), AUTH_ENCRYPTION_KEY and the Resend key.
  • Alternatively, from the web server: read journald_ssh_key and log into the remote log host, or inject into the journald follower and read the whole system journal.
  • Impact: full platform compromise from the log receiver, and lateral movement to the remote log host.
  • What defends against it today: the units use NoNewPrivileges, ProtectSystem=strict and ProtectHome. The receivers listen on loopback by default (syslog-receiver.mjs:137; syslog.env SYSLOG_HOST=127.0.0.1).
  • Suggested fix: Run the syslog and journald units with DynamicUser=yes, or as separate users (openchronology-syslog, openchronology-journald), each able to read only its own env file and key. Give each unit only the env file it needs (for example 0640 root:openchronology-syslog). Add ProtectProc=invisible, or at least PrivateUsers=, to the workers.
  • Confidence: confirmed for file access. The ptrace path is likely and depends on the host's Yama setting.

From the security review of 2026-11-06 (commit 6776c44), finding L-14: hardening or information, filed publicly because it describes no way in. The exploitable findings are private security advisories.

🤖 Generated with Claude Code

https://claude.ai/code/session_011fFY8eruEi1xAkkMBni13B

Related

Tickets: #527
Tickets: #530

Discussion

  • Anonymous

    Anonymous - 2 days ago

    Originally posted by: athanclark

    Assessed while hardening deployment (#527). There's no small safe change here.

    • Shared units: the four units are shared by the Debian, RPM and Arch packages.
    • Files at the operator's paths: the syslog routes file and the journald SSH key are wherever the operator put them, so a new service user couldn't read them after an upgrade unless the upgrade found and regrouped them.
    • systemd sandboxing isn't enough: it can't separate processes running as the same user. They can read each other's environment through /proc and use the database's passwordless peer login.

    What it would take:

    • an openchronology-logs user in each package (Debian adduser, RPM %pre useradd, an Arch sysusers line);
    • the syslog receiver's and journald follower's units switched to it;
    • upgrade scripts that read the configured file paths and change their group, with the package upgrade tests run in CI;
    • the same in the FreeBSD rc scripts and the NixOS module.

    [#527] adds more systemd hardening to every unit in the meantime.

    🤖 Generated with Claude Code

    https://claude.ai/code/session_011fFY8eruEi1xAkkMBni13B

     

    Related

    Tickets: #527

  • Anonymous

    Anonymous - 2 days ago

    Ticket changed by: athanclark

    • status: open --> closed
     

Log in to post a comment.