I really like the centralized configuration feature of Cloudflare Tunnel. The recommended way to run a tunnel as a service on Windows is to use cloudflared service install <token>, where the token is a JSON document encoded in base64 that allows cloudflared to fetch the centralized configuration and run the tunnel. The token includes the tunnel's secret.
The problem with this command, on Windows at least, is that cloudflared saves the token in the executable path of the service. Therefore, the tunnel token can be read by any user regardless of privileges, which is not necessary since the service runs as the Local System user. A service's path is not an appropriate way to store a secret.
To test this, run the PS command Get-WmiObject win32_service | ?{$_.Name -eq 'cloudflared'} | select PathName as an unprivileged user and you’ll see the token. This is a big issue since the origin of the tunnel is likely to be trusted by users, who will then send their RDP/SSH/HTTP credentials to whatever service is routed by the tunnel. If tunnel credentials are stolen, an attacker can steal whatever data is sent to the origin.
This token should be stored in a file where only administrators or the System user can read.
The same error appears on Linux, where the service token can be viewed both by inspecting the service file, which is world readable, or by looking for cloudflared in the process tree.
I really like the centralized configuration feature of Cloudflare Tunnel. The recommended way to run a tunnel as a service on Windows is to use
cloudflared service install <token>
, where the token is a JSON document encoded in base64 that allows cloudflared to fetch the centralized configuration and run the tunnel. The token includes the tunnel's secret.The problem with this command, on Windows at least, is that cloudflared saves the token in the executable path of the service. Therefore, the tunnel token can be read by any user regardless of privileges, which is not necessary since the service runs as the
Local System
user. A service's path is not an appropriate way to store a secret.To test this, run the PS command
Get-WmiObject win32_service | ?{$_.Name -eq 'cloudflared'} | select PathName
as an unprivileged user and you’ll see the token. This is a big issue since the origin of the tunnel is likely to be trusted by users, who will then send their RDP/SSH/HTTP credentials to whatever service is routed by the tunnel. If tunnel credentials are stolen, an attacker can steal whatever data is sent to the origin.This token should be stored in a file where only administrators or the
System
user can read.Related Cloudflare Community post: https://community.cloudflare.com/t/insecure-cloudflared-credential-storage-on-windows/391387