| 제목 | Casdoor v2.356.0 Open Redirect |
|---|
| 설명 | **Evidence:**
```go
for _, targetUri := range application.RedirectUris {
targetUriRegex := regexp.MustCompile(targetUri)
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
return true
}
}
```
Two critical flaws:
1. `strings.Contains(redirectUri, targetUri)` is a substring match. If an application registers `https://app.example.com/callback`, then `https://evil.com/https://app.example.com/callback` passes validation.
2. `regexp.MustCompile(targetUri)` treats stored redirect URIs as regex patterns. A URI containing `.` matches any character. An entry like `https://example.com` matches `https://exampleXcom.evil.com`.
**Attack scenario:** An attacker constructs an OAuth authorization request with `redirect_uri=https://evil.com/?x=https://app.example.com/callback`. This passes the `strings.Contains` check. The OAuth code/token is then sent to `evil.com`.
**Fix:** Use strict equality or validated prefix matching. Never treat user-configured values as regex patterns. Compare parsed URL components (scheme, host, path) individually:
```go
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
parsedRedirect, err := url.Parse(redirectUri)
if err != nil { return false }
for _, targetUri := range application.RedirectUris {
parsedTarget, err := url.Parse(targetUri)
if err != nil { continue }
if parsedRedirect.Scheme == parsedTarget.Scheme &&
parsedRedirect.Host == parsedTarget.Host &&
strings.HasPrefix(parsedRedirect.Path, parsedTarget.Path) {
return true
}
}
return false
}
``` |
|---|
| 사용자 | Ghufran Khan (UID 95493) |
|---|
| 제출 | 2026. 03. 17. PM 02:23 (18 날 ago) |
|---|
| 모더레이션 | 2026. 04. 03. AM 09:26 (17 days later) |
|---|
| 상태 | 수락 |
|---|
| VulDB 항목 | 355071 [Casdoor 2.356.0 OAuth Authorization Request redirect_uri Redirect] |
|---|
| 포인트들 | 17 |
|---|