Wednesday, August 28, 2024

Java Http3/QUIC implementation security, part 5: HTTP/3

...continued from part 4

RFC 9204 QPACK: Field Compression for HTTP/3

7.1 Probing Dynamic Table Size

HttpClient only uses the dynamic table for known-safe fields: ":authority" and "user-agent".

Fields "cookie", "authorization" and "proxy-authorization" are flagged with never-indexed bit.

7.2. Static Huffman Encoding

No additional requirements.

7.3 Memory Consumption

HttpClient limits the maximum size of the dynamic table to 4096. Blocked streams are disallowed by default.

The encoder table size is limited to 4KB even if the decoder advertises a larger table size.

The decoder limits the allowed field section size to 384KB. When that size is reached, the processing is aborted.

We currently do not monitor the amount of unsent data on the encoder and the decoder stream.

7.4 Implementation Limits

Integer values that can't be encoded on a Java long are rejected. String literals longer than 2GB are rejected, but only after parsing. This will be improved before the final release.


Java Http3/QUIC implementation security, part 4: HTTP/3

 ...continued from part 3

RFC 9114 HTTP/3

10.1 Server Authority

HTTP/3 uses QUIC and TLS to verify the server authority. We always set endpoint identification algorithm to HTTPS to ensure that the server certificate identity is authoritative for the URL host name.

10.2 Cross-Protocol Attacks

The underlying TLS implementation ensures that both parties agree on the ALPN.

10.3 Intermediary-Encapsulation Attacks

HttpClient validates incoming field names and values. Responses containing invalid fields are treated as malformed, and are not delivered to the application.

10.4 Cacheability of Pushed Responses

HttpClient does not cache any responses. 

The default PushPromiseHandler rejects push promises where the :authority header does not match the hostname that was used to establish the connection. Custom push promise handlers might choose to implement different checks.

10.5 Denial-of-Service Considerations

The number of PUSH_PROMISE frames is limited to a maximum of 100 concurrently used push IDs at any given time.

The maximum allowable SETTINGS frame size is limited to 1280 bytes, which is more than enough to hold all defined settings.

HttpClient does not monitor the use of unknown frame types and unknown stream types. H3_EXCESSIVE_LOAD error is not generated.

HttpClient limits the maximum size of a field section and the maximum size of a field.

10.6 Use of Compression

HttpClient does not support compression. The Accept-Encoding and Content-Encoding headers are not set by the client. They may be set by the application.

10.7 Padding and Traffic Analysis

No additional requirements.

10.8 Frame Parsing

HttpClient checks the frame lengths.

10.9 Early data

HttpClient does not implement 0-RTT

10.10 Migration

No additional requirements.

10.11 Privacy Considerations

No additional requirements.

continued in part 5...

Monday, August 26, 2024

Java Http3/QUIC implementation security, part 3: QUIC

 ...continued from part 2

RFC 8999, 9368, 9369

The security considerations sections of these documents focus on downgrade prevention. No additional requirements beyond what is already discussed elsewhere in the documents.

RFC 9001 Using TLS to Secure QUIC

9.1 Session Linkability

JSSE TLS implementation does not reuse session tickets. It is also possible to prevent session resumption by using a different SSLContext for every connection.

9.2 Replay Attacks with 0-RTT

0-RTT requires support in HttpClient, QUIC and TLS. None of these is implemented.

9.3 Packet Reflection Attack Mitigation

This section discusses server anti-amplification limit. The requirements do not apply to the client side.

9.4 Header Protection Analysis

No additional requirements

9.5 Header Protection Timing Side Channels

We do not discard packets with duplicate packet number without decrypting them first.

We do not generate packet decryption keys while decrypting.

The packet decryption time might differ between current, previous and next key space. It might need further improvement.

9.6 Key Diversity

No additional requirements

9.7 Randomness

Connection IDs are generated with a secure random number generator.

RFC 9002 QUIC Loss Detection and Congestion Control

8.1 Loss and Congestion Signals

No additional requirements

8.2 Traffic Analysis

No additional requirements

8.3 Misreporting ECN Markings

Our QUIC implementation does not currently support sending or receiving ECN.

This concludes the overview of QUIC RFCs.

continued in part 4...

Java Http3/QUIC implementation security, part 2: QUIC

...continued from part 1

21.5 Request Forgery Attacks

This paragraph focuses on the risk posed by reflected datagrams. The concerns are somewhat similar to these in the anti-amplification section, except that here the focus is on sending datagrams to otherwise inaccessible services, and forging datagrams that would make the inaccessible services react in a specific way.

Most of the concerns listed here apply to the server side; other than using the server-supplied preferred address, the client does not migrate to other addresses. We do not support preferred address at the moment, so that doesn't apply either.

21.6 Slowloris attack

Slowloris aims at making the endpoint keep as many open connections as possible.

HttpClient may keep multiple connections to the same server. The number of open connections to a single server is at most the number of outstanding requests plus one. It's the user's responsibility to limit the number of concurrently executing requests.

21.7 Stream Fragmentation and Reassembly Attacks

QUIC implementation needs to buffer stream data on on the sending side until the data is acknowledged by peer, and on the receiving side until the data is received by the higher layer. If there are gaps in the received stream, the data needs to be buffered until the gaps are filled. This can lead to excessive memory consumption.

On the receiver side, HttpClient limits the MAX_DATA QUIC parameter to a maximum of 15 MB per connection at all times. If certain portions of stream data are received multiple times, only one copy is preserved until the data is received by the application. Buffer memory utilization is therefore bounded.

Memory structures used to store discontinuous ranges of stream data might consume excessive amounts of memory. The maximum memory usage has not been measured.

Crypto stream receive buffer is limited to 64KB per connection.

On the sender side, we buffer as much data as the congestion controller allows. This might lead to memory overcommit if the receiver successfully inflates the congestion window.

21.8 Stream Commitment Attack

We limit the number of streams the peer can open at any time to 100 per stream type per connection.

21.9 Peer Denial of Service

This section recommends to "track cost of processing relative to progress and treat [excess] as indicative of an attack".

We do not track the cost of processing.

21.10 Explicit Congestion Notification Attacks

No additional requirements.

HttpClient's QUIC implementation does not support sending or receiving ECN yet.

21.11 Stateless Reset Oracle

Every QUIC endpoint uses a different randomly generated key for generating stateless reset tokens. The keys are never shared, so a stateless reset is only generated if a connection ID is not in use.

21.12 Version Downgrade

The current implementation only supports QUIC v1 and v2. These versions offer identical security properties, so version downgrade is not a concern.

21.13 Targeted Attacks by Routing

This section describes deployment concerns, as opposed to implementation concerns. No additional implementation requirements.

21.14 Traffic Analysis

Currently our QUIC API offers no way to obscure the length of the packet content.


This concludes the review of RFC 9000 security considerations.

continued in part 3...

Tuesday, August 20, 2024

Java Http3/QUIC implementation security, part 1: QUIC

Support HTTP/3 in the HttpClient

As part of the JEP, we implement:

  • RFC 9114: HTTP/3
  • RFC 9204: QPACK: Field Compression for HTTP/3
  • RFC 8999: Version-Independent Properties of QUIC
  • RFC 9000: A UDP-Based Multiplexed and Secure Transport
  • RFC 9001: Using TLS to Secure QUIC
  • RFC 9002: QUIC Loss Detection and Congestion Control
  • RFC 9368: Compatible Version Negotiation for QUIC
  • RFC 9369: QUIC Version 2

QUIC is implemented on top of TLS 1.3, defined in RFC 8446. TLS 1.3 support in JSSE was implemented in a prior JEP, and this JEP builds on top of that work.

The goal of the JEP is to implement a working implementation of HTTP/3 in the HttpClient. The QUIC implementation is supposed to be in a reasonably usable state; in particular, optional features and features that are only required by the server might not exist.

QUIC security considerations

This section structure mirrors the formal requirements specified in RFC 9000

21.1.1.1 Anti-Amplification

The QUIC implementation is supposed to limit the number of bytes it sends to an unvalidated address.
- The client only sends stateless reset messages to unvalidated addresses. We make sure that the stateless reset messages are only sent when they are strictly smaller than the incoming datagram.
- The server also sends handshake messages to unvalidated clients. Our server-side implementation does not have anti-amplification limit.

21.1.1.2 Server-Side DoS

In order to filter out forged handshake packets, the server can implement secure token generation, either in a retry packet, or in a new_token frame.
- Our client implementation of new_token and retry is complete
- The tokens generated by our server are not secure and easily forged, offering no protection against DoS.

21.1.1.3 On-Path Handshake Termination

We offer no extra protection against forged initial/retry packets.

21.1.1.4 Parameter Negotiation

No additional requirements

21.1.2 Protected packets

No additional requirements

21.1.3 Connection Migration

The server can offer a preferred address, and the client can choose to migrate to the preferred address or stay on the original one.
The client can switch addresses as a result of a (local) network change or as a result of a (remote) NAT rebinding.
In order to tell apart a real and a spoofed address migration, the QUIC endpoints are supposed to implement path validation. Until the path validation succeeds, the new address is subject to anti-amplification limit.
Our implementation:
- does not perform path validation. The handling of connection migration needs to be reevaluated.
- always sends packets to the same remote address. This is good enough on the client side, but not good enough on the server side.
- selects source address individually for each packet. The client source address might change in the middle of a connection if the routing tables change. This would be reasonable if we implemented path validation.
- optionally filters the source address on the incoming packets. This is good on the client side, but might be counterproductive on the server side.

21.2 Handshake Denial of Service

No additional requirements

21.3 Amplification Attack

Server guidance only. Our server implementation does not offer any guarantees for token validity.

21.4 Optimistic ACK Attack

(optional) We are vulnerable to optimistic ACK attack. We do not detect acknowledgements of non-existent packet numbers other than packet numbers that were not assigned yet.

continued in part 2...