Echo has Open Redirect via Control-Character Prefix Defeating sanitizeURI
Affected packages
| Ecosystem | Package | Affected | Fixed |
|---|---|---|---|
| labstack | echo | — | — |
| go | github.com/labstack/echo/v5 |
< 5.4.0 |
5.4.0 |
| go | github.com/labstack/echo/v4 |
< 4.16.0 |
4.16.0 |
Original description The description as published by the source.
Summary
Echo's dedicated open-redirect guard, sanitizeURI, decides whether a redirect target is a local path by inspecting exactly two byte positions: uri[0] and uri[1]. If the value begins with a control character such as a tab or a newline, followed by a separator pair, the guard does not fire and the value is written to the Location header unchanged.
Browsers remove tab and newline characters from URLs before parsing them, and treat a backslash as a forward slash for HTTP and HTTPS URLs. A Location value of /\t/attacker.example is therefore resolved by the browser as an absolute URL on attacker.example. Confirmed end to end in a headless browser.
Technical background
The guard
middleware/slash.go:144 (duplicated verbatim at echo.go:958):
func sanitizeURI(uri string) string {
// double slash `\\`, `//` or even `\/` is absolute uri for browsers and by redirecting request to that uri
// we are vulnerable to open redirect attack. so replace all slashes from the beginning with single slash
if len(uri) > 1 && (uri[0] == '\\' || uri[0] == '/') && (uri[1] == '\\' || uri[1] == '/') {
uri = "/" + strings.TrimLeft(uri, `/\`)
}
return uri
}
The condition is anchored at absolute offsets 0 and 1. It cannot see a separator that has been shifted by one byte.
Data flow
RemoveTrailingSlash(middleware/slash.go:112-140) readsurl.Path, whichnet/httphas already percent-decoded, strips the trailing slash, and appends the…
Source: CVE.org (CVE Program・cvelistV5) NVD GitHub Advisory