The principle, detection and remediation of cross-site WebSocket vulnerabilities.
WebSocket is one of the new features of HTML5 that has attracted the attention of developers because it has made it possible for clients (primarily browsers) to provide support for sockets, thus providing a bidirectional channel between the client and the server based on a single TCP connection.
For applications with high real-time requirements, such as *** games, and information synchronization between different devices. Real-time synchronization of information has always been a technical challenge, and before the advent of WebSockets, the common solutions were polling and Comet techniques, but these technologies increased design complexity, created additional burdens on the network and servers, and were relatively inefficient under heavy loads, resulting in limited scalability of applications. For developers of such applications, WebSocket technology is a powerful tool for readers to log in to WebSocketFeatured cases of org **, as well as a comparative analysis of the performance of websocket and comet it provides.
In recent years, WebSocket technology has been widely used by developers in a variety of practical applications. Unfortunately, WebSocket-related security vulnerabilities are also being revealed, the most likely of which is cross-site WebSocket hijacking vulnerabilities. This article will introduce the principles, detection methods, and fixes of cross-site WebSocket vulnerabilities in simple terms, hoping to help readers avoid this known security vulnerability in their actual work.
In order to illustrate the principle of cross-site WebSocket hijacking vulnerability, this article will briefly describe the handshake and switching process of the WebSocket protocol. Interested readers are advised to read the RRFC 6455 specification provided in the reference for an in-depth study of the WebSocket protocol.
Anyone who has learned about websocket technology knows itws://
withhttp://
So what's the relationship between websockets and http? The author's understanding of this problem is that WebSocket is a new protocol introduced by HTML5, and has nothing to do with the content of the HTTP protocol itself. WebSocket is a persistent protocol, while HTTP is a non-persistent connection.
As mentioned earlier, WebSocket provides full-duplex communication, commonly known as TCP connectivity to the Web, but TCP typically handles byte streams (independent of messages), while WebSocket implements message flow based on TCP. WebSocket is also similar to TCP for handshake connections, unlike TCP, WebSocket is based on the HTTP protocol. The author used Chrome developer tools to collect WebSocketsThe protocol handshake request and response for the ECHO Test Service are shown in Listings 1 and 2.
Listing 1WebSocket protocol upgrade request.
get ws: http/1.1host: echo.websocket.orgconnection: upgradepragma: no-cachecache-control: no-cacheupgrade: websocketorigin: 13user-agent: mozilla/5.0 (macintosh; intel mac os x 10_11_4) chrome/49.0.2623.110accept-encoding: gzip, deflate, sdchaccept-language: en-us,en;q=0.8,zh-cn;q=0.6cookie: _gat=1; _ga=ga1.2.2904372.1459647651; jsessionid=1a9431cf043f851e0356f5837845b2ecsec-websocket-key: 7arps0ajshn8bx5dci1kkq==sec-websocket-extensions: permessage-deflate; client_max_window_bits
Those who are familiar with HTTP can discover the core of WebSocket, yes, these are the two lines of connection:upgrade and upgrade:websocket. These two lines are equivalent to telling the server: I want to request to switch to the websocket protocol.
Listing 2WebSocket protocol upgrade response.
http/1.1 101 web socket protocol handshakeaccess-control-allow-credentials: trueaccess-control-allow-headers: content-typeaccess-control-allow-headers: authorizationaccess-control-allow-headers: x-websocket-extensionsaccess-control-allow-headers: x-websocket-versionaccess-control-allow-headers: x-websocket-protocolaccess-control-allow-origin: upgradedate: sun, 03 apr 2016 03:09:21 gmtsec-websocket-accept: ww9bl95vtfjdbphdfivy7csoado=server: kaazing gatewayupgrade: websocket
Once the server side returns a 101 response, the websocket protocol switch is complete. The server side can then use the same port to transfer the communication protocol fromhttp://
orhttps://
Switch tows://
orwss://
。Once the protocol switch is complete, the browser and server can use the WebSocket API to send and receive text and binary messages to and from each other.
Here are some important security-related header parameters, sec-websocket-key and sec-websocket-accept. This involves a websocket security feature where the client is responsible for generating a base64-encoded random number as the sec-websocket-key, and the server will generate a GUID along with the client's random number to generate a hash key that is returned to the client as sec-websocket-accept. This can be used to avoid caching proxies and request replay.
Attentive readers may also notice a number of other websocket-related headers that start with "sec". In fact, this is also a special design of the websocket designer for security, the header starting with "sec-" can avoid being read by the browser script, so that the attacker cannot use xmlhttprequest to forge the websocket request to perform cross-protocol attacks, because the xmlhttprequest interface does not allow setting the header starting with sec-.
Although the WebSocket protocol is designed with security in mind, with the popularization of WebSocket technology, security workers have slowly discovered some WebSocket-related security vulnerabilities, such as the Wireshark vulnerability CVE-2013-3562 (Wireshark 18.7 before 18.epan dissectors packet-websocket. in the websocket resolver in the x versionThere are multiple integer symbol errors in the 'tvb unmasked' function in C, which can be exploited by a remote attacker via malicious packets to cause a denial of service).
DOS vulnerability CVE-2014-9374 in Asterisk WebSocket Server (a double-free vulnerability in a module of the WebSocket Server could enable a remote attacker to send zero-length frames to cause a denial of service). These two DDoS vulnerabilities have little to do with the WebSocket protocol itself and WebSocket applications. However, in 2015, Brian Manifold of Cisco and Paul McMillan of Nebula reported a WebSocket vulnerability in the OpenStack Nova Console (CVE-2015-0259), which received widespread attention and was found in many WebSocket applications.
In fact, the vulnerability was discovered and made public in 2013 by Christian Schneider, a German white-hat hacker who named it Cross Site WebSocket Hijacking (CSWSH). Cross-site websocket hijacking is relatively harmful and easier for developers to overlook.
What is a cross-site WebSocket hijacking vulnerability, as mentioned earlier, in order to create full-duplex communication, the client needs to switch to the WebSocket protocol based on the HTTP handshake, and this process of upgrading the protocol is the potential Achilles heel. If you look closely at the handshake get request above, you can see that the cookie header sends all the cookies under the domain name to the server.
If you have a chance to read the websocket protocol (10Chapter 5 Client Authentication) found that the WebSocket protocol does not specify how the server should authenticate the client during the handshake phase. The server can use the client-side authentication mechanism of any HTTP server, such as cookies, HTTP basic authentication, TLS authentication, etc. Therefore, for most web applications, client authentication should be a cookie such as a sessionid or an HTTP auth header parameter. Friends who are familiar with Cross Site Request Forgery (CSRF) should be able to think of hackers who may forge handshake requests to bypass identity authentication.
Because the client of the websocket is not limited to the browser, the origin of the websocket specification does not have to be the same (interested readers can read specification 10.)2 chapters for the origin specification). All browsers send origin headers, which can lead to cross-site websocket hijacking attacks if the server does not validate against the origin headers.
For example, if a user is logged into an application, if he is tricked into visiting a malicious web page of social **, the malicious web page will plant a websocket handshake request in an element to request a websocket connection to the target application. Once the malicious web page is opened, the following request is automatically initiated: Please note that both origin and sec-websocket-key are automatically generated by the browser, and authentication parameters such as cookies are automatically uploaded by the browser to the server side of the target application. If the server fails to check the origin, the request will successfully switch to the WebSocket protocol, and the malicious web page can successfully bypass the identity authentication to connect to the WebSocket server, and then steal the information sent by the server, or send forged information to the server to tamper with the server's data.
Interested readers can compare this vulnerability with CSRF, which mainly quietly initiates data modification requests through malicious web pages and does not cause information leakage problems, while cross-site WebSocket forgery attacks can not only modify server data, but also control the entire two-way communication channel for reading and modifying. That's why Christian named the vulnerability hijacking, not request forgery.
Listing 3A tampered websocket protocol upgrade request.
get ws: http/1.1host: echo.websocket.orgconnection: upgradepragma: no-cachecache-control: no-cacheupgrade: websocketorigin: 13accept-encoding: gzip, deflate, sdchaccept-language: en-us,en;q=0.8,zh-cn;q=0.6cookie: _gat=1; _ga=ga1.2.290430972.14547651; jsessionid=1a9431cf043f851e0356f5837845b2ecsec-websocket-key: 7arps0ajshn8bx5dci1kkq==sec-websocket-extensions: permessage-deflate; client_max_window_bits
At this point, readers familiar with j**ascript cross-origin resource access may be skeptical. If the HTTP response does not specify "access-control-allow-origin", the browser script will not be able to access the cross-origin resource, yes, this is the well-known cross-origin resource sharing (CORS), which is indeed one of the new features brought by HTML5. Unfortunately, cross-origin resource sharing is not suitable for websockets, which do not specify how to handle them across domains.
After understanding the principle of cross-site WebSocket hijacking vulnerability, it is easy to think of the detection method of this vulnerability, which focuses on replaying WebSocket protocol upgrade requests. Simply put, use a tool that intercepts the websocket handshake request, modify the origin header in the request, and then resend the request to see if the server can successfully return a 101 response.
If the connection fails, then the websocket is secure because it correctly rejects connection requests from different origins. If the connection is successful, it is usually proven that the server is not performing a source check, and for the sake of rigor, it is a good idea to further test whether the websocket message can be sent, and if the websocket connection is capable of sending and accepting messages, the existence of the cross-site websocket hijacking vulnerability is fully proved.
In order to demonstrate how to test and fix this vulnerability, the author wrote a simple WebSocket application, which implements HTTP Basic authentication based on Jaas, and readers can deploy this program to Tomcat for testing. After opening the client web page, first log in, then click the "Connect" button to establish a websocket connection through j**ascript, and then click the "Send" button to submit a problem to the server, the server confirms the receipt of the query request in real time, and then pushes the result to the client after 5 seconds.
There are a lot of options when it comes to testing tools, and for licensing reasons, I use the open-source OWASP ZAP v24.3。To briefly mention here, the test process is mainly based on the ** of the test tool, intercepting the websocket handshake request and the websocket message communication, and then resending the request after modifying the origin through the tool, and resending the websocket client message if the connection is successful. All of the above functions can be done by any commercial security testing tool.
1. First configure Zap in Firefox, and then explore the entire WebSocket application. As you can see in the following figure, HTTP Basic Authorization information appears in the request header, indicating that the login has been successful.
Figure 1WebSocket protocol upgrade request.
2. Right-click and select Resend WebSocket protocol upgrade request, modify the origin to any other**, and click Send.
Figure 2Tampering with WebSocket protocol upgrade requests.
3. Click the response tab, and you can see that 101 is returned on the server side, that is, the protocol handshake is successful.
Figure 3The WebSocket protocol handshake is successful.
4. Further test whether the websocket message can be retransmitted. As shown in the figure below, right-click the first websocket message sent by the client, select Retransmit, enter the test message "www" and click send, you can see that ZAP has received two messages returned by the server one after another. This fully proves that there is a cross-site WebSocket hijacking vulnerability in the test application site.
Figure 4Resend client websocket messages.
The principle and detection of cross-site websocket hijacking vulnerabilities have been introduced above, and I believe readers have understood its harms, so let's talk about how to prevent this vulnerability. The principle of this vulnerability sounds slightly complicated, but fortunately it is relatively simple to test, so it would be easy to fix. Many readers will think that it is not just to check the origin parameter in the server**. Yes, checking the origin is necessary, but not sufficient. If the origin information sent by the client comes from a different domain, it is recommended that the server reject the request and send back a 403 error response to reject the connection.
The author uses the J**A EE technology to write a WebSocket test application, and the J**A EE WebSocket API provides a configurator that allows developers to override the configuration to intercept and check the protocol handshake process. The author has included this part in the source ** in the appendix of the article**, and the following is a brief introduction to some core classes and configurations. If you are not familiar with the J**A EE WebSocket API, it is recommended that you check the relevant specifications first.
1. First, write a configurator for the websocket server terminal, inherit and rewrite the checkorigin method as shown in Listing 4. Note that the author ignores the scenario where there is no origin, which depends on the actual situation of each application, and if there is a non-browser client, this check needs to be added. It is also recommended that non-browser clients see the token mechanism below.
Listing 4WebSocket source check configurator.
public class customconfigurator extends serverendpointconfig.configurator }
2. Then associate the configurator to the websocket server.
Listing 5Configure websocket source checking.
@serverendpoint(value = "/query", configurator = customconfigurator.class)public class websockettestserver }
3. Repackage and publish the websocket application.
Interested readers can try it for themselves, if you replay the tampered websocket handshake protocol request after making up the above **, you will receive a 403 error.
The above looks great, but it's not enough to just check the origin, and don't forget that if the websocket client is not a browser, the request from a non-browser client has no origin at all. In addition to this, we need to remember that malicious web pages can forge origin header information. A more radical solution would be to borrow from the CSRF's token mechanism.
For reasons of space, the author will not post the entire design in detail, but suggest that readers refer to the following summary design to improve the security of websocket applications.
The server side generates a unique one-time token for each websocket client; The client uses the token as a parameter to the WebSocket connection URL (e.g., WS: sent to the server for WebSocket handshake connection; The server verifies whether the token is correct, and if it is correct, the token is marked as discarded and no longer reused, and the websocket handshake connection is successful. If token authentication fails or authentication fails, a 403 error is returned. The token design in this scheme is the key, and the author's recommended scheme is to generate a Secure Random for the logged-in user and store it in the session, and then use symmetric encryption (such as AES GCM) to encrypt this Secure Random value as a token, and send the encrypted token to the client for connection. This allows each session to have a unique random number, and each random number can generate several one-time tokens through symmetric encryption. Even if a user connects to the server through a websocket through different terminals, the server can still associate information from different channels with the same user on the premise of ensuring that the token is unique and used once.
There may be another design idea, which is to add tokens and identity information to websocket messages, but I feel that this design is contrary to the design idea of websockets and adds unnecessary network load. Readers are welcome to provide better design solutions.
In this article, the author shares with readers the understanding of the WebSocket protocol handshake, and on this basis, explains the principle of cross-site WebSocket hijacking vulnerability. As mentioned in this article, this is the only one that is widely known to be a websocket vulnerability in web applications. At the same time, the author also shares the method of detecting cross-site WebSocket hijacking vulnerability, and introduces the fix of the vulnerability based on J**A EE technology, as well as a more comprehensive security solution based on the token mechanism.