Input
To ease into the topic, let’s begin with a well-known security concern and see how it applies to websockets. As many developers know, applications should always treat user input as possibly malicious. One example of attack that can occur if this assumption is not enforced is a cross-site scripting (XSS) attack. In a XSS attack, an attacker places malicious JavaScript code within a parameter. This malicious code is eventually viewed and executed by a victim’s browser. Many developers are aware of XSS attacks against typical form elements (such as a name or address field) and most web frameworks include libraries to protect against these attacks automatically. However, these libraries often do not automatically protect against malicious code in websocket messages. If this avenue is not secured, attackers can use a man-in-the-middle proxy, such as Burp Suite or OWASP Zap, to modify websocket traffic and conduct XSS attacks.For example, we recently analyzed a chat application that used websockets to send and receive chat messages. When a user sent a chat message, the following websocket message would be sent from the client (browser) to the server:
{“user”:”user1”, "text":"hello", "type":"message", "id":1562869260905}
By intercepting their own requests to the server, an attacker could modify the message sent to the server to include JavaScript code. This would allow them to bypass client-side sanitation controls. This attack would then execute identically to a traditional XSS attack. An example of this attack is shown below:
{“user”:”user1”, "text":"Nothing malicious here<script>alert(1)</script>","type":"message","id":1562869260905}
When viewed by another user, the JavaScript code executed on their machine:
Server Output
In contrast to dealing with user input, many applications are developed to intrinsically trust information that originates from server responses. However, developers should be careful when it comes to trusting websocket responses from the server, as it is possible for attackers to modify these responses before the client receives them. In addition, these modified responses will appear legitimate to the client. If the application trusts these responses, it can lead to serious vulnerabilities.One browser-based game we analyzed controlled player movement through a combination of websocket requests and responses. When moving in the game, players would send a websocket message to the server that contained their new position:
{“player”:140234, “newposition_x”: 155, “newposition_y”: 20}
The server would respond back to the player with a confirmation message that contained their new position. This response would look identical to the request above.
Attempting to send a request from the client with modified newposition_x or newposition_y values would cause the entire request to be ignored by the server. However, by intercepting the response from the server and modifying these positions before they reach the browser, the game would assume that the player desynced from the server. The game would then invoke a special function to fix this apparent desync. This desync routine would place the player wherever was specified in the modified server response. Since the traffic from the client and server appeared legitimate, this vulnerability allowed attackers to teleport around the game world.
Message Forgery
Both the vulnerabilities discussed above occurred due to attackers modifying messages. However, attackers are not limited to only modifying messages - they can also create them. This can cause two potential issues for applications:- Denial of Service (DoS) attacks
- Authorization issues
In a similar manner, if applications are designed to assume that websocket traffic cannot be created by attackers, they may allow access to unauthorized features. For example, if an application assumes that only administrators can create certain messages, it may not properly verify the requesting user. This would allow an attacker to perform unauthorized actions by only sending websocket requests.
Conclusion
So, while websockets offer many advantages over traditional HTTP, they require the same security considerations that must be applied to all traditional traffic. However, because many security libraries do not account for them automatically, developers must ensure that common controls are also applied to any websocket functionality. In particular, developers should take the following steps to secure their websocket implementations:- Always assume user input is malicious and protect against it, even in websocket messages to the server
- Clients that use websockets shouldn’t trust server responses to execute sensitive functionality and servers receiving websocket messages should enforce controls
- Always verify that websocket traffic is validated on the server-side for authorization controls, rate limiting, business logic, and other traditional server-side responsibilities
0 comments:
Post a Comment