Echo has Arbitrary Scheme Injection in WWWRedirect/NonWWWRedirect Middlewares via X-Forwarded-Proto
Description
Summary
The c.Scheme() method in Echo (context.go:162-181) trusts the X-Forwarded-Proto, X-Forwarded-Protocol, and X-Url-Scheme request headers without validating that the value is http or https. The WWWRedirect() and NonWWWRedirect() middlewares use this unsanitized scheme to construct redirect URLs, allowing an attacker to inject arbitrary URI schemes into the Location response header.
Affected
Components
context.go:162-181-Scheme()method returns attacker-controlled value verbatimmiddleware/redirect.go:172-184-redirectWWW/redirectNonWWWuse unsanitized scheme
Proof of
Concept
GET /path HTTP/1.1
Host: example.com
X-Forwarded-Proto: javascript
Response:
HTTP/1.1 301 Moved Permanently
Location: javascript://www.example.com/path
Confirmed injectable schemes: javascript, data, vbscript, file, ftp, ssh, telnet, gopher.
Only WWWRedirect() and NonWWWRedirect() (and WithConfig variants) are affected. HTTPSRedirect, HTTPSWWWRedirect, HTTPSNonWWWRedirect are NOT affected (they hardcode https://).
Impact
- Open redirect to arbitrary scheme URLs when app is not behind a proxy that strips
X-Forwarded-Proto - Cache poisoning when behind a CDN that caches redirect responses keyed by path
file://scheme injection could trigger file access in some browser configurations
Suggested
Fix
Whitelist scheme in c.Scheme() to only return http or https:
func (c *Context) Scheme() string {
if c.IsTLS() {
return "https"
}
if scheme := c.request.Header.Get(HeaderXForwardedProto); scheme != "" {
scheme = strings.ToLower(strings.TrimSpace(scheme))
if scheme == "https" {
return "https"
}
}
return "http"
}
Disclosure
Source code review, manually verified with actual HTTP server. Tested on Echo v5.0.4 (latest master).
Patches
Fixed in github.com/labstack/echo/v5 v5.1.1 and github.com/labstack/echo/v4 v4.15.2. Context.Scheme() now accepts only http, https, ws or wss from the X-Forwarded-Proto, X-Forwarded-Protocol and X-Url-Scheme headers, and falls back to http for any other value (#2953).
Workarounds
Upgrade to a patched version. If you cannot upgrade, have your edge proxy overwrite or remove the X-Forwarded-Proto, X-Forwarded-Protocol and X-Url-Scheme request headers.
Patches
Vulnerability mechanics
References
7- github.com/advisories/GHSA-23wf-92cp-8pcjghsaADVISORY
- github.com/labstack/echo/commit/ca4f38a474302aabee93c66bdd0052359882e181ghsa
- github.com/labstack/echo/commit/d1d8ad3f99dd9b80542cd0c357d56a8916c515dfghsa
- github.com/labstack/echo/pull/2953ghsa
- github.com/labstack/echo/releases/tag/v4.15.2ghsa
- github.com/labstack/echo/releases/tag/v5.1.1ghsa
- github.com/labstack/echo/security/advisories/GHSA-23wf-92cp-8pcjghsa
News mentions
0No linked articles in our index yet.