- From: Frode Børli <frode@seria.no>
- Date: Tue, 24 Jun 2008 22:31:06 +0200
>> It is worth spending months improving the implementation here, if it >> saves only one minute of work for each of the millions of web >> developers out there, in the future. > > Alright, point taken. You're of course absolutely right with that :) > I agree, it would be very convenient to basically set up and control a > web app in a single connection. However, I think there are valid use > cases for just the opposite set up as well. So, if we use a HTTP > handshake, we should provide two ways. Agree >> If it is impossible to use HTML, then it is absolutely required that >> Session ID is added as a standard header - since that will be the only >> way of linking the generated HTML with the separate persistent >> connection. You can't assume that an application server or the web >> server will be able to parse the cookie, since the cookie format is >> different for each programming language/application. > > This depends on the layer where the session management takes place. > For example, PHP's existing session handling system already uses > cookies. So, a hypothetical future "PPHP" version of PHP could extend The PHP *script* decides how to encode session identifiers, not the PHP-engine. PHP has a default cookie variable called PHPSESSID that many php-scripts use but many PHP-applications implement their own session handling. If the Session ID was implemented trough headers, it would have the following benefits: 1. Many more links in the chain between the browser and the server side script can utilize session id; for example a load balancer will easily see which internal server to pass requests to. 2. Session ID is not available for client side scripts - and makes session hijacking much more difficult. (Today they are accessible trough document.cookie) 3. Server side logic can be implemented in many more layers for connecting requests to an actual user session. 4. Statistics tools can much more easily identify unique visitors, as Session ID potentially could be logged in log files. I am sure there are more advantages. > the session system to support this. > This feature couldn't be implemented in the afromentioned "few lines > of perl" though. SessionID header only need to be implemented on the client side for HTML5 browsers. Server side scripting languages can immediately read headers and set headers - but it would be an advantage if PHP (and others) was updated to use SessionID-header as default for request from browsers supporting HTML5. >>The HTTP 101 Switching Protocols can be sent by the server, without >>the client asking for a protocol change. The only requirement is that >>the server sends 426 Upgrade Required first, then specifies which >>protocol to switch to. The protocol switched to could possibly be the >>one proposed in the beginning of this thread. > > I don't see how we could use 426 as a notification that the client > should open a WebSocket connection. 426 is still an error code, so if > you send it as the reply to the initial GET request, you can't be sure > the HTML file you pushed gets interpreted the correct way. While this > would probably work, it would be semantically unclean at best. I am not a HTTP protocol wizard, but I have read that something similar is done for starting HTTPS-communications, and I believe the same procedure can be used for WebSocket. > PROPOSAL: Turning an existing HTTP connection into a WebSocket connection: > > If the server sends a Connection: Upgrade header and an Upgrade header > with a "WebSocket" token as part of a normal response and if the > resource fetched established a browsing contest, the client must not > issue any other requests on that connection and must initiate a > protocol switch. > After the switch has finished, the client would expose the connection > to the application via a DefaultWebSocket property or something > similar. > > An exchange could look like this: > > C: GET /uri HTTP/1.1 > C: Host: example.com > C: [ ... usual headers ... ] > C: > > S: HTTP/1.1 200 OK > S: Content-Type: text/html > S: [ ... usual headers ... ] > S: Upgrade: WebSocket/1.0 > S: Connection: Upgrade > S: > S: [ ... body ... ] > > C: OPTIONS /uri HTTP/1.1 > C: Host: example.com > C: Upgrade: WebSocket/1.0 > C: Connection: Upgrade > C: > > S: HTTP/1.1 101 Switching Protocols > S: Upgrade: WebSocket/1.0 > S: Connection: Upgrade > S: > > C/S: [ ... application specific data ... ] > > Because the connection would be same-origin pretty much per > definition, no access checks would be needed in that situation. > > Would something like this be doable and wanted? This is exactly what I was trying to describe :) >>> Consider the following scenario: >>> >>> Bob and Eve have bought space on a run-of-the-mill XAMPP web hoster. >>> They have different domains but happen to be on the same IP. Now Eve >>> wants do bruteforce Bob's password-protected web application. So she >>> adds a script to her relatively popular site that does the following: >> >> So Bob will DDOS his own server? And my proposals allows using >> hostnames OR ip-addresses in the DNS TXT record, so unless Eve add her >> own IP-address to the DNS then Bob can't create scripts that are >> allowed to access her hostname. > > I'm sorry, if my wording was unclear. I was talking about a typical > shared hosting setup where customers get FTP access to a directory > where they can upload pages and scripts but for example no shell > access. Bob and Eve would have different directories on the same > server. Requests to their sites would go to the same port on the same > IP. The server would use the Host header to determine which request > goes to which site. In the scenario, Eve would try to attack Bob's > application. This is possible today using a very simple java applet. The java applet does not even have to be trusted to perform a pure TCP-connection and the applet can be scripted using javascript via liveconnect. I don't believe it is a problem at all. >> Why could he not just do a local connect to the port? Besides; if you >> have login access to the same server as your target - there are a lot >> much more efficient ways to find access information. > > Eve could connect directly. However, then her IP would be in Bob's > logs and she could be shut down quickly. If she makes the detour over > a client-side scripts, only IPs of random visitors of Eve's website > would be logged. 1. The security restrictions require a script to be downloaded from the same IP as her own website. From this Eve will know that another user on the same shared host is performing the attack. 2. If she can see that attacks are being made from her own IP address, she would know exactly as much as in point 1. In either case, it is impossible to tell if its Bob or John on the same server that performs the connections. >>> 2) Forge HTTP requests on that connection with Bob's site in the Host >>> header and bruteforce the password. The Browser can't do anything >>> about this, because it treats the TCP connection as opaque. The >>> firewall just sees a legitimate HTTP request on a legitimate port. >> >> Still, that is more easily done if you are sitting on the local server >> using the server side script. Also the connections will be many times >> faster locally than all connections from outside users combined. > > See above. See above:) >>> If Bob checks his logs, he will see requests from IPs all oer the >>> world. Because Eve has control about the Referrer and >>> Access-Control-Origin headers, there is no trace that leads back to >>> her. She might even have send the headers with forged values to shift >>> suspicion to another site. >> >> No trace leads back to Bob if he sits locally either (it would >> probably be more confusing). >> >> Perhaps the protocol should send another header stating the origin of >> the script that started the request? > > For HTTP-based connections, this is exactly what Access-Control-Origin is doing. > For pure TCP connections, this would not be possible, because, after > all, they wouldn't be pure anymore :) The script doing the connection either must be downloaded from Bobs server, or must be mentioned in Bobs' domain TXT-records - or perform the connection by downloading an xSocket file over HTTP first, and he will have a very good clue on finding the source of the attack and also stopping the attack because he would have to actively enable it in the first place. >>> Note that the web hoster doesn't need to support WebSocket server side >>> in any way for this to work. >> The web hoster will not allow a shared hosting customer to create >> programs that listen on arbitrary ports on the server, so for >> TCPConnection this is not an issue. > The web hoster may not, but the interface on the browsers would still work. Anyway, see my comment above. This attack is already possible using java applets and can only be initiated from the server that is being attacked. A low traffic shared server can never initiate millions of attacks world wide, and the odds of the evil attacker being on exactly the same server as the site being attacked is very low. >> A big problem here is that we are discussing two separate things in >> the same threads. TCPConnection is one suggestion, WebConnection is >> another. > > I agree. This attack would only work on pure TCP connections, not on > HTTP-based connections. I believe TCP connections are secure - unless ofcourse in the improbable case that the attacker has a user account on your server. > If I see it correctly, we have the following proposals currently: > > - Client-initiated HTTP 101, access checks via Access Control (The > original proposal) > - Client-initiated HTTP 101, access checks via DNS/XSocket The two above is essentially the same, just different security mechanisms. > - "Server-initiated" HTTP 101 on an exisiting connection, no checks necessary > > - Pure TCP, access checks via DNS/XSocket > > Is this correct? This is correct. I believe there is one more proposal involving a very simple handshake (allows client to connect to any port on any server, but the handshake must succeed). > I think we should decide if we should continue the discussion about a > HTTP-based or a pure TCP connection or if we should include both. I vote for these: 1. TCPConnection using DNS and/or xSocket. 2. Server initiated WebSocket trough the existing channel that the page was sent trough (via document.webSocket for example). 3. Since AJAX requests basically are page requests, the server should be able to initiate a websocket also on AJAX requests - effectively making it client initiated and server approved. Should we start new discussion threads for these? >> My DNS record security framework will work for both implementations. > For pure TCP connections, I don't see how it would alleviate the > attack above. I think the XSocket proposal would solve the problem > though. See above. TCP connections to Server A can only be performed is client script is downloaded from Server A or if Server A has made an xSocket file available over HTTP, or if DNS records indicate that scripts downloaded from hostname of Server B can connect to Server A. > For HTTP-based connections, it would work, but I think Access Control > would solve the same problems and would be much easier to implement > and control. Notice that the xSocket implementation does not require any changes to the existing server side to enable pure TCP - only an xSocket file sent over normal HTTP. The same applies to the DNS-method, which probably mostly will be used for very high traffic websites. A simple server side script can perform any security checks neccesary before providing a xSocket file, so I think it is easier to implement. The xSocket file can also be extended to accomodate future ideas (being XML-based).
Received on Tuesday, 24 June 2008 13:31:06 UTC