Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalize web socket requirements #1908

Closed
tghosth opened this issue Mar 20, 2024 · 12 comments · Fixed by #1909
Closed

Finalize web socket requirements #1908

tghosth opened this issue Mar 20, 2024 · 12 comments · Fixed by #1909
Assignees
Labels
5) awaiting PR A proposal hs been accepted and reviewed and we are now waiting for a PR V13 _5.0 - prep This needs to be addressed to prepare 5.0

Comments

@tghosth
Copy link
Collaborator

tghosth commented Mar 20, 2024

Web Socket requirements were introduced following discussions in #842 and #649.

In preparation for 5.0, I have been through them and would suggest making the following changes (additions in bold, deletions in strikethrough.)

V13.5 WebSocket

# Description L1 L2 L3 CWE
13.5.1 [ADDED] Verify that WebSocket Secure (wss) is used for all WebSocket connections. 319
13.5.2 [ADDED] Verify that, during the initial HTTP WebSocket handshake, the Origin header is checked against an allow list of authorized origins. 346
13.5.3 [ADDED] Verify that rate limiting is in place for WebSocket messages. 770
13.5.4 [ADDED] Verify that, if the application's standard session management cannot be used, dedicated tokens are being used for this which comply with the relevant Session Management security requirments. Verify that tokens possess at least 128 bits of entropy and are generated using approved cryptographic algorithms if session or channel tokens specific to WebSockets are being used. 331
13.5.5 [ADDED] Verify that the dedicated WebSocket session management tokens are initially obtained from a response to secure POST request only, and are not sent by the server through the WebSocket connection. 319
13.5.6 [ADDED] Verify that authentication is done before opening the WebSocket connection if only authenticated users should be able to use WebSockets. 306

I don't think 13.5.3, the original 13.5.4 and 13.5.6 are specific enough to web sockets. I think the others have specific application to web sockets so they should stay.

@Racater @elarlang any thoughts before I commit the changes?

@tghosth tghosth added the V13 label Mar 20, 2024
@tghosth tghosth added 1) Discussion ongoing Issue is opened and assigned but no clear proposal yet _5.0 - prep This needs to be addressed to prepare 5.0 labels Mar 20, 2024
@tghosth tghosth added the next meeting Filter for leaders label Mar 20, 2024
@tghosth
Copy link
Collaborator Author

tghosth commented Mar 20, 2024

@tghosth tghosth added the Community wanted We would like feedback from the community to guide our decision otherwise we will progress label Mar 20, 2024
@tghosth tghosth mentioned this issue Mar 20, 2024
@elarlang
Copy link
Collaborator

Just quick feedback:

13.5.1 - in a way covered by 9.1.1

Verify that TLS is used for all connectivity between a client and external facing, HTTP-based services, and does not fall back to insecure or unencrypted communications.

I don't know the answer, but can you use not secure web socket, when you have HSTS set?

13.5.2 - in a way covered by 4.1.1

Verify that the application enforces access control rules at a trusted service layer and doesn't rely on controls which an untrusted user could manipulate such as client-side JavaScript.

What means "list of authorized origins"?

13.5.3 - remove as duplicate of 11.2.2?

13.5.4 - what is the message or goal for the requirement? Require session? For everyone? How it is aligned wit 13.5.5?

13.5.6 - what is/was the point for this?

@tghosth
Copy link
Collaborator Author

tghosth commented Mar 21, 2024


13.5.1 - in a way covered by 9.1.1

Verify that TLS is used for all connectivity between a client and external facing, HTTP-based services, and does not fall back to insecure or unencrypted communications.

I don't know the answer, but can you use not secure web socket, when you have HSTS set?

Looks like HSTS also applies to WebSocket:

Sources to support

I agree it is theoretically a duplicate but it is also quite a specific case that would need to be specific configured, especially if for whatever reason HSTS is not in use. Hence suggesting leaving it in.


13.5.2 - in a way covered by 4.1.1

Verify that the application enforces access control rules at a trusted service layer and doesn't rely on controls which an untrusted user could manipulate such as client-side JavaScript.

Again, this is a very specific case which is why I think it is worth including it

What means "list of authorized origins"?

Yeah I agree, I think it should be worded slightly better:

# Description L1 L2 L3 CWE
13.5.2 [ADDED] Verify that, during the initial HTTP WebSocket handshake, the Origin header is checked against a list of origins allowed for the application. 346

13.5.3 - remove as duplicate of 11.2.2?

Basically yes, I didn't tag it because it is ADDED


13.5.4 - what is the message or goal for the requirement? Require session? For everyone? How it is aligned wit 13.5.5?

Basic problem is that websockets support cookie based sessions but not tokens in headers so if that is the required Auth mechanism you have to do something specific.

At that point, how you get the token is important hence the need for 13.5.5 as well.


13.5.6 - what is/was the point for this?

Not sure but it doesn't seem like it adds something specific on V2 and 13.5.4/13.5.5


@ryarmst
Copy link
Contributor

ryarmst commented Mar 21, 2024

Regarding 13.5.4/13.5.5, having seen a number of implementations, it seems the most common practice is to associate connections with standard sessions supplied during the handshake.

Basic problem is that websockets support cookie based sessions but not tokens in headers so if that is the required Auth mechanism you have to do something specific.

Unless I am misunderstanding, I think this is not correct. Cookies, headers, and query parameters equally (though the latter obviously not preferred) can be utilized from a handshake to authenticate a connection. From a complexity point of view, I think it's probably preferred to use the standard session management regardless.

@elarlang elarlang removed the next meeting Filter for leaders label Mar 23, 2024
@elarlang elarlang removed their assignment Mar 29, 2024
@tghosth
Copy link
Collaborator Author

tghosth commented Apr 3, 2024

Hi @ryarmst :)

Basic problem is that websockets support cookie based sessions but not tokens in headers so if that is the required Auth mechanism you have to do something specific.

Unless I am misunderstanding, I think this is not correct. Cookies, headers, and query parameters equally (though the latter obviously not preferred) can be utilized from a handshake to authenticate a connection. From a complexity point of view, I think it's probably preferred to use the standard session management regardless.

So I think I wasn't clear enough. What I should have said was:

Basic problem is that the websocket "upgrade" handshake supports cookie based sessions but not tokens in headers so if that is the required Auth mechanism you have to do something specific.

So if I have an app where all my authentication involves using a header token, for the handshake request which will result in a 101 upgrade response, it will be necessary to somehow transmit that header separately.

Does that match how you understand it? If so, I may try and reword/clarify 13.5.4/13.5.5.

@ryarmst
Copy link
Contributor

ryarmst commented Apr 4, 2024

Hi @tghosth!

Sorry, I was mistaken. I checked the protocol spec, but ignored the API spec that does not support custom headers. I had seen an implementation repurpose Sec-WebSocket-Protocol to send session/auth data, but I think this should not be recommended. That said, 13.5.5 feels overly specific but without detailing the complete flow that is expected. Am I correct that the approach would involve obtaining a transient token for session transfer and subsequently sending in an initial WS message to "authenticate" the WS connection (tracked server-side)?

@tghosth
Copy link
Collaborator Author

tghosth commented Apr 4, 2024

Hi @tghosth!

Sorry, I was mistaken. I checked the protocol spec, but ignored the API spec that does not support custom headers. I had seen an implementation repurpose Sec-WebSocket-Protocol to send session/auth data, but I think this should not be recommended. That said, 13.5.5 feels overly specific but without detailing the complete flow that is expected. Am I correct that the approach would involve obtaining a transient token for session transfer and subsequently sending in an initial WS message to "authenticate" the WS connection (tracked server-side)?

So from an access control/session management perspective, my understanding is that securing the websocket handshake is the crucial part so if a non-cookie session mechanism is in use then a session token of some sort would need to be obtained from the server and then sent in the handshake request. The server would then only perform the handshake "upgrade" if the session token was valid. It may be better if the regular session token is not used for this as sending it in the handshake request might expose it more than usual (e.g. if it goes in the request header).

@ryarmst
Copy link
Contributor

ryarmst commented Apr 9, 2024

So from an access control/session management perspective, my understanding is that securing the websocket handshake is the crucial part so if a non-cookie session mechanism is in use then a session token of some sort would need to be obtained from the server and then sent in the handshake request. The server would then only perform the handshake "upgrade" if the session token was valid.

I am assuming the scenario where "securing the websocket handshake" means to associate the created WS connection with a user's existing web session/identity (derived from an HTTP-based web app). IMO the ideal approach would be with a properly secured cookie-based session mechanism, but obviously that does not account for the diversity of mechanisms as implemented. The challenge with authenticating in the handshake/upgrade without cookies is that there are essentially only 2 other options within this HTTP request to send a token to associate the connection with the existing session:

  1. Use of a query parameter (not ideal, but not terrible for a transient token revoked on use)
  2. Use of the Sec-WebSocket-Protocol header (not the intended use of this header)
  3. Use of a cookie just for this purpose even if the application's primary session mechanism does not use cookies.

However, there are also other options following the creation of the WS connection, using messages within the connection (that each also have their own pros/cons):

  1. A token specific to this purpose (session transfer) is generated server-side and retrieved over HTTP. In the initial WS message from the client to the server, the client submits this token, which is used by the server to associate the WS connection with the user's existing session before revoking the token.
  2. A token specific to this purpose is generated server-side and returned in an initial WS message from the server to the client. The client must then resubmit the token within their existing HTTP session. The server receives the token and associates the identified WS connection with the user's active session. (Disclaimer: I don't think I have seen this pattern).
  3. Same as (1) above, but the token is stored by the client and sent in every WS message, associating individual messages with their existing session rather than the connection.
  4. The user re-authenticates over the WS connection following the handshake (IMO this is the worst approach, but worth mentioning for completeness). I have seen this pattern where the only authenticated portion of an application is over the WS connection.

The way I interpret 13.5.5 right now is either (1), (2), (3), or (4) from above. I also interpret it as advising against (5), but I think this is a fine approach if implemented correctly. All approaches will have implementation concerns with respect to cross-origin and cross-site attacks.

It may be better if the regular session token is not used for this as sending it in the handshake request might expose it more than usual (e.g. if it goes in the request header).

Agree 100% that a secondary and ideally transient token should be used when an existing cookie mechanism isn't available. I cannot immediately think of a phrasing I would recommend for the requirement, but I think it should either be adjusted to be more broad or more specific (endorsing a specific implementation, though I think flexibility will be required in practice).

@tghosth
Copy link
Collaborator Author

tghosth commented Apr 16, 2024

Thanks for the feedback @ryarmst :)

# Description L1 L2 L3 CWE
13.5.5 [ADDED] Verify that the dedicated WebSocket session management tokens are initially obtained or validated through a previously authenticated HTTPS session. 319

Do you think this updated version of 13.5.5 is more accommodating whilst also secure?

@ryarmst
Copy link
Contributor

ryarmst commented Apr 17, 2024

@tghosth That looks great! It might also be worth adding an exclusion for when the primary session (and authentication) occurs over WS rather than HTTP (this is seemingly rare, but I have seen at least one case). What about this?

# Description L1 L2 L3 CWE
13.5.5 [ADDED] When transitioning an existing HTTPS session to a WebSocket channel, verify that the dedicated WebSocket session management tokens are initially obtained or validated through the previously authenticated HTTPS session. 319

@tghosth
Copy link
Collaborator Author

tghosth commented Apr 18, 2024

That looks great @ryarmst, fancy opening a PR with your change into the following branch?
https://github.com/OWASP/ASVS/tree/refresh_v13_websockets

Note that the requirement will now be 13.5.4 because 13.5.3 got deleted.

@tghosth tghosth added 5) awaiting PR A proposal hs been accepted and reviewed and we are now waiting for a PR and removed 1) Discussion ongoing Issue is opened and assigned but no clear proposal yet Community wanted We would like feedback from the community to guide our decision otherwise we will progress labels Apr 18, 2024
@tghosth tghosth linked a pull request Apr 18, 2024 that will close this issue
ryarmst added a commit to ryarmst/ASVS that referenced this issue Apr 19, 2024
Additionally fixed a 13.5.3 typo
tghosth pushed a commit that referenced this issue Apr 21, 2024
* Updated 13.5.4 as per #1908

Additionally fixed a 13.5.3 typo

* Updated wording of 13.5.4 to begin with "Verify that"
tghosth added a commit that referenced this issue Apr 21, 2024
* intial trim of websocket section

* Fix linting issue

* Clarify 13.5.2

* Fix numbering

* Updated 13.5.4 as per #1908 (#1936)

* Updated 13.5.4 as per #1908

Additionally fixed a 13.5.3 typo

* Updated wording of 13.5.4 to begin with "Verify that"

---------

Co-authored-by: Ryan Armstrong <ryarmst@users.noreply.github.com>
@tghosth
Copy link
Collaborator Author

tghosth commented Apr 21, 2024

Closed by #1909

@tghosth tghosth closed this as completed Apr 21, 2024
tghosth added a commit that referenced this issue Apr 21, 2024
* intial trim of websocket section

* Fix linting issue

* Clarify 13.5.2

* Fix numbering

* Updated 13.5.4 as per #1908 (#1936)

* Updated 13.5.4 as per #1908

Additionally fixed a 13.5.3 typo

* Updated wording of 13.5.4 to begin with "Verify that"

---------

Co-authored-by: Ryan Armstrong <ryarmst@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5) awaiting PR A proposal hs been accepted and reviewed and we are now waiting for a PR V13 _5.0 - prep This needs to be addressed to prepare 5.0
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants