| タイトル | kekingcn kkFileView v5.0.2 (reviewed release commit `c4288f7e`, official-baseline jar `server/target/kkFileView-5.0.2.jar`); the `X-Base-Url` header precedence has been in place since 2021 and the same filter pair is still present on upstream `main` URL r |
|---|
| 説明 | Unauthenticated open redirect via the attacker-controlled `X-Base-Url` header in kkFileView's trailing-slash normalization filter
Vendor: kekingcn
Affected versions: v5.0.2 (reviewed release commit `c4288f7e`, official-baseline jar `server/target/kkFileView-5.0.2.jar`); the `X-Base-Url` header precedence has been in place since 2021 and the same filter pair is still present on upstream `main`
Vulnerability class: URL redirection to untrusted site (open redirect) (CWE-601)
Preconditions: None. Any anonymous network caller can trigger it; no configuration change is needed, because the shipped default `baseUrl=default` makes `BaseUrlFilter` fall through to the request-supplied header, and these routes carry no authentication by default (access password disabled in the default configuration).
Unauthenticated open redirect via the attacker-controlled `X-Base-Url` header in kkFileView's trailing-slash normalization filter
Data flow: `HTTP request header X-Base-Url (any request whose path needs trailing-slash normalization, e.g. GET /index/)` → `BaseUrlFilter.getBaseUrl()` returns the header value unconditionally when present → `UrlCheckFilter` builds `redirectUrl = baseUrl + servletPath` → `sendRedirect(redirectUrl + "?" + queryString)` → `302 Location: <attacker URL><path>?<query>`, verbatim, with no scheme/host validation
### Affected interfaces
| Interface |
|---|
| Any path ending in `/` or containing `//` (e.g. `GET /index/`) - `UrlCheckFilter` (mapped `/*`, order 30) emits `302 Location: <X-Base-Url value><path>?<query>` |
Primary route detail:
```
GET /index/?poc=1
X-Base-Url: https://evil.example.com
```
Any anonymous network caller; the header is honored from the client directly:
1. `UrlCheckFilter` is registered on `/*` and triggers for trailing-slash (or `//`) paths regardless of
authentication.
2. The shipped default `baseUrl=default` makes `BaseUrlFilter` fall through to the request-supplied
`X-Base-Url` header, and no route on this path requires a login.
### Root cause
The gap is a default-config, unauthenticated trust-boundary failure: a header designed for the operator's reverse proxy is honored from any client and lands unvalidated in `Location`.
1. `server/src/main/java/cn/keking/web/filter/BaseUrlFilter.java:43-45` - the request header wins unconditionally over the configured base URL:
```java
final String urlInHeader = servletRequest.getHeader("X-Base-Url");
if (StringUtils.isNotEmpty(urlInHeader)) { baseUrl = urlInHeader; }
```
2. `server/src/main/java/cn/keking/web/filter/UrlCheckFilter.java:30-47` - for a trailing-slash (or `//`) path the filter builds `redirectUrl = BaseUrlFilter.getBaseUrl() + servletPath` and emits the redirect:
```java
((HttpServletResponse) response).sendRedirect(redirectUrl + "?" + httpServletRequest.getQueryString());
```
3. No scheme/host validation is applied to `baseUrl` (no check against the deployment URL, no relative-path constraint): the header value is copied verbatim into the `Location` response header. `TrustHostFilter`/`TrustDirFilter` guard the URL-fetching and directory routes, not this redirect.
Baseline: kkFileView v5.0.2 official-baseline jar, booted on `127.0.0.1:18120` with default `application.properties` (`baseUrl=default`, `trust.host=default`, access password disabled).
**1. Positive - attacker header controls the redirect target:**
```http
GET /index/?poc=1 HTTP/1.1
Host: 127.0.0.1:18120
X-Base-Url: https://evil.example.com
Connection: close
```
Response (observed):
```http
HTTP/1.1 302
Location: https://evil.example.com/index?poc=1
```
(equivalent: `curl -s -D - -o /dev/null -H 'X-Base-Url: https://evil.example.com' 'http://127.0.0.1:18120/index/?poc=1'`)
**2. Baseline behavior without the header** - `GET /index/` -> `HTTP/1.1 302` + `Location: http://127.0.0.1:18120/index?null` (self redirect: the trailing-slash normalization stays on the server's own origin).
**3. Negative control** - `GET /index` (no trailing slash) -> `HTTP/1.1 200` (no redirect at all); `GET /index/` without the header -> `302` to the server's own base. The off-site redirect appears if and only if the attacker-controlled header is present.
- **Vendor contact**: GitHub Private Vulnerability Reporting - kekingcn/kkFileView
- **Status**: vendor notified 2026-10-06 through GitHub Private Vulnerability Reporting; private report https://github.com/kekingcn/kkFileView/security/advisories/GHSA-wrm9-r4fj-f8q5; not publicly disclosed; no CVE assigned
- **Duplicate check**: public advisories (NVD/OSV/GitHub) and the project issue tracker were searched before reporting; please tell us if this duplicates something already tracked internally. |
|---|
| ソース | ⚠️ https://github.com/kekingcn/kkFileView |
|---|
| ユーザー | lucasg2g (UID 84737) |
|---|
| 送信 | 2026年10月15日 07:33 (24 日 ago) |
|---|
| モデレーション | 2026年11月08日 15:13 (24 days later) |
|---|
| ステータス | 承諾済み |
|---|
| VulDBエントリ | 432888 [kekingcn kkFileView 迄 5.0.3 BaseUrlFilter.java BaseUrlFilter.getBaseUrl X-Base-Url Redirect] |
|---|
| ポイント | 20 |
|---|