[ 
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

Aggressively sanitize and limit size of options since these are sent before 
authentication. 

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()|https://github.com/ryogrid/create_pg_super_document/blob/master/generated_docs/p/pg_clean_ascii.md]
 which sanitizes startup options for display with 
[pg_stat_activity()|https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW]

  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.

For one approach, see the Postgres 
[pg_clean_ascii()|https://github.com/ryogrid/create_pg_super_document/blob/master/generated_docs/p/pg_clean_ascii.md]
 which sanitizes startup options for display with 
[pg_stat_activity()|https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW]


> 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: 3.5h
>  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
> Aggressively sanitize and limit size of options since these are sent before 
> authentication. 
> 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()|https://github.com/ryogrid/create_pg_super_document/blob/master/generated_docs/p/pg_clean_ascii.md]
>  which sanitizes startup options for display with 
> [pg_stat_activity()|https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW]



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

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

Reply via email to