Headline
CVE-2021-43795: Exclude `%2F(/)` from decoding of percents in a request path. by ikhoon · Pull Request #3855 · line/armeria
Armeria is an open source microservice framework. In affected versions an attacker can access an Armeria server’s local file system beyond its restricted directory by sending an HTTP request whose path contains %2F
(encoded /
), such as /files/..%2Fsecrets.txt
, bypassing Armeria’s path validation logic. Armeria 1.13.4 or above contains the hardened path validation logic that handles %2F
properly. This vulnerability can be worked around by inserting a decorator that performs an additional validation on the request path.
Conversation
Motivation:
Currently, `%2F` and `%2f` are converted into `/` while decoding request paths. It might route a path to an unexpected service if users really want to send `%2F` as data itself. Furthermore, other specifications such as gRPC transcoding do not expect to decode `%2F` as `/`. https://github.com/googleapis/googleapis/blob/02710fa0ea5312d79d7fb986c9c9823fb41049a9/google/api/http.proto#L257-L258 It should be better to exclude `%2F` for less confusion and better interop with other echo systems.
Modifications:
- Exclude `%2F` and `%2f` from decoding percent-encoded characters in paths.
Result:
`%2F` and `%2f` are no longer converted to `/` when decoding a request path.
wasSlash = decoded == '/’;
if (decoded == ‘/’) {
// Do not decode ‘%2F’ and ‘%2f’ in the path to ‘/’ for compatibility with
// other echo systems, e.g. HTTP/JSON to gRPC transcoding.
// Do not decode ‘%2F’ and ‘%2f’ in the path to ‘/’ for compatibility with
// other echo systems, e.g. HTTP/JSON to gRPC transcoding.
// https://github.com/googleapis/googleapis/blob/02710fa0ea5312d79d7fb986c9c9823fb41049a9/google/api/http.proto#L257-L258
final byte marker = RAW_CHAR_TO_MARKER[‘/’];
ikhoon deleted the exclude-%2f-decoding branch
Nov 3, 2021
trustin added a commit that referenced this issue
Dec 2, 2021
Motivation:
- We changed how `PathAndQuery` handles `%2F` (/) in 1.12.0 via #3855. This change introduces an unexpected hole in its double-dot detection logic.
- Since we decided not to decode `%2F`, we should not decode it whereever possible.
Modifications:
- Hardened the double-dot detection logic in `PathAndQuery`.
- `Bytes.data` now always store the bytes in their decoded form. We keep whether the byte has to be encoded in a separate `BitSet`.
- Split `ArmeriaHttpUtil.decodePath()` into `decodePath()` and
`decodePathParam()`.
- We don’t decode `%2F` in `decodePath()` but we do in `decodePathParam()`.
- `RoutingResultBuilder.rawParam()` now uses `decodePathParam()` because `decodePath()` doesn’t decode `%2F` anymore.
Result:
- A path that contains double dots with `%2F`, such as `/files/…%2Fsecrets.txt`, are now rejected correctly.