[ 
https://issues.apache.org/jira/browse/CASSANDRA-21755?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Brad Schoening updated CASSANDRA-21755:
---------------------------------------
    Description: 
The native protocol STARTUP message carries a {{[string map]}} of options. The 
server
accepts and retains the entire map up to {{native_transport_max_frame_size}} 
(16 MB by default)— including keys it does not recognize — and exposes it to 
operators via {{system_views.clients}} ({{{}client_options{}}}), {{{}nodetool 
clientstats{}}}, and
the JMX client metrics.

This happens {*}before authentication{*}. The connection is registered in the 
connection tracker when STARTUP is processed (via the {{Connection}} 
constructor →
{{{}ConnectionTracker.addConnection{}}}), and {{StartupMessage.execute()}} calls
{{ClientState.setClientOptions(options)}} before the authentication challenge 
is issued. As a result, an unauthenticated client controls data that appears in 
operator-facing views for as long as it keeps the socket open, whether or not 
it ever presents valid credentials.

The retained values are also neither sanitized nor bounded:
 * Strings are decoded as UTF-8 but are otherwise unconstrained — control 
characters,
newlines, and terminal escape sequences are all accepted.
 * {{ConnectedClient.asMap()}} (which feeds {{nodetool clientstats}} and JMX) 
joins the entries as {{k=v, k=v}} with no escaping, so a value containing {{", 
foo=bar"}} is
indistinguishable from a separate option in that output.
 * There is no limit on key/value length, on the number of entries, or on 
duplicate keys,
beyond the overall {{native_transport_max_frame_size}} (16 MB by default).

h3. Steps to reproduce
 # Open a native protocol connection and send a STARTUP message with a 
populated options map
(optionally including a non-printable character or a {{", k=v"}} fragment in a 
value).
 # Do *not* complete authentication — leave the connection open at the 
authenticating stage.
 # Observe the connection in operator views.

{noformat}
% nodetool clientstats --all
Address          SSL   Cipher    Protocol  Version User      Keyspace Requests 
Driver-Name Driver-Version
/127.0.0.1:51690 false undefined undefined 3       anonymous          1        
undefined   undefined
{noformat}
The same connection appears in {{system_views.clients}} with its 
{{client_options}}
populated and {{connection_stage}} = {{{}authenticating{}}}.
h3. Expected behaviour

Client-supplied STARTUP options should be constrained before being 
retained/displayed, and skip display of un-authenticed clients or, 
alternatively, option paths should not be able to carry control characters or 
forge delimiter structure.
h3. Proposed hardening

Deferring {{setClientOptions()}} (and option retention generally) until after 
successful
authentication would additionally remove the unauthenticated-exposure aspect.

For one approach, see the Postgres pg_clean_ascii() which sanitizes startup 
options for display with pg_stat_activity()

  was:
The native protocol STARTUP message carries a {{[string map]}} of options. The 
server
accepts and retains the entire map up to {{native_transport_max_frame_size}} 
(16 MB by default)— including keys it does not recognize — and exposes it to 
operators via {{system_views.clients}} ({{{}client_options{}}}), {{{}nodetool 
clientstats{}}}, and
the JMX client metrics.

This happens {*}before authentication{*}. The connection is registered in the 
connection tracker when STARTUP is processed (via the {{Connection}} 
constructor →
{{{}ConnectionTracker.addConnection{}}}), and {{StartupMessage.execute()}} calls
{{ClientState.setClientOptions(options)}} before the authentication challenge 
is issued. As a result, an unauthenticated client controls data that appears in 
operator-facing views for as long as it keeps the socket open, whether or not 
it ever presents valid credentials.

The retained values are also neither sanitized nor bounded:
 * Strings are decoded as UTF-8 but are otherwise unconstrained — control 
characters,
newlines, and terminal escape sequences are all accepted.
 * {{ConnectedClient.asMap()}} (which feeds {{nodetool clientstats}} and JMX) 
joins the entries as {{k=v, k=v}} with no escaping, so a value containing {{", 
foo=bar"}} is
indistinguishable from a separate option in that output.
 * There is no limit on key/value length, on the number of entries, or on 
duplicate keys,
beyond the overall {{native_transport_max_frame_size}} (16 MB by default).

h3. Steps to reproduce
 # Open a native protocol connection and send a STARTUP message with a 
populated options map
(optionally including a non-printable character or a {{", k=v"}} fragment in a 
value).
 # Do *not* complete authentication — leave the connection open at the 
authenticating stage.
 # Observe the connection in operator views.

{noformat}
% nodetool clientstats --all
Address          SSL   Cipher    Protocol  Version User      Keyspace Requests 
Driver-Name Driver-Version
/127.0.0.1:51690 false undefined undefined 3       anonymous          1        
undefined   undefined
{noformat}
The same connection appears in {{system_views.clients}} with its 
{{client_options}}
populated and {{connection_stage}} = {{{}authenticating{}}}.
h3. Expected behaviour

Client-supplied STARTUP options should be constrained before being 
retained/displayed, and skip display of un-authenticed clients or, 
alternatively, option paths should not be able to carry control characters or 
forge delimiter structure.
h3. Proposed hardening

Deferring {{setClientOptions()}} (and option retention generally) until after 
successful
authentication would additionally remove the unauthenticated-exposure aspect.


> NTR STARTUP options are retained and exposed (system_views.clients, nodetool 
> clientstats, JMX) before authentication, with no sanitization or size limits
> ---------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-21755
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21755
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: Observability/JMX
>            Reporter: Brad Schoening
>            Assignee: Rishabh Saraswat
>            Priority: Normal
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> The native protocol STARTUP message carries a {{[string map]}} of options. 
> The server
> accepts and retains the entire map up to {{native_transport_max_frame_size}} 
> (16 MB by default)— including keys it does not recognize — and exposes it to 
> operators via {{system_views.clients}} ({{{}client_options{}}}), {{{}nodetool 
> clientstats{}}}, and
> the JMX client metrics.
> This happens {*}before authentication{*}. The connection is registered in the 
> connection tracker when STARTUP is processed (via the {{Connection}} 
> constructor →
> {{{}ConnectionTracker.addConnection{}}}), and {{StartupMessage.execute()}} 
> calls
> {{ClientState.setClientOptions(options)}} before the authentication challenge 
> is issued. As a result, an unauthenticated client controls data that appears 
> in operator-facing views for as long as it keeps the socket open, whether or 
> not it ever presents valid credentials.
> The retained values are also neither sanitized nor bounded:
>  * Strings are decoded as UTF-8 but are otherwise unconstrained — control 
> characters,
> newlines, and terminal escape sequences are all accepted.
>  * {{ConnectedClient.asMap()}} (which feeds {{nodetool clientstats}} and JMX) 
> joins the entries as {{k=v, k=v}} with no escaping, so a value containing 
> {{", foo=bar"}} is
> indistinguishable from a separate option in that output.
>  * There is no limit on key/value length, on the number of entries, or on 
> duplicate keys,
> beyond the overall {{native_transport_max_frame_size}} (16 MB by default).
> h3. Steps to reproduce
>  # Open a native protocol connection and send a STARTUP message with a 
> populated options map
> (optionally including a non-printable character or a {{", k=v"}} fragment in 
> a value).
>  # Do *not* complete authentication — leave the connection open at the 
> authenticating stage.
>  # Observe the connection in operator views.
> {noformat}
> % nodetool clientstats --all
> Address          SSL   Cipher    Protocol  Version User      Keyspace 
> Requests Driver-Name Driver-Version
> /127.0.0.1:51690 false undefined undefined 3       anonymous          1       
>  undefined   undefined
> {noformat}
> The same connection appears in {{system_views.clients}} with its 
> {{client_options}}
> populated and {{connection_stage}} = {{{}authenticating{}}}.
> h3. Expected behaviour
> Client-supplied STARTUP options should be constrained before being 
> retained/displayed, and skip display of un-authenticed clients or, 
> alternatively, option paths should not be able to carry control characters or 
> forge delimiter structure.
> h3. Proposed hardening
> Deferring {{setClientOptions()}} (and option retention generally) until after 
> successful
> authentication would additionally remove the unauthenticated-exposure aspect.
> For one approach, see the Postgres pg_clean_ascii() which sanitizes startup 
> options for display with pg_stat_activity()



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to