specifically, i'm talking about from the point of view of a node.js server. it's hard to test this in node.js because http.client validates content-length.
can a client lie about a body's content-length, at least at the point it reaches http.createServer().on('request')?
Can a client send a body that is larger than content-length? I don't think this is possible as it is most likely checked at the parser level, but i want proof.
Can a client send a body that is smaller than content-length? I think this may be true.
i'm worried about malicious users that may not use a well-behaved http client.
Of course it's possible. You could simply open a TCP socket connection to whatever IP/port a web server is running on and write anything you'd like there. Of course well-behaved clients don't do this, but there's nothing stopping a client from doing so.
However, this tends to be whatever HTTP stack your using on the server's problem, in this case node. It needs to 1) not blindly read in (huge) content-length bytes as that could crash the server miserably and 2) make sure (for reasonable-sized requests) that the client isn't lying.
In the case of node, it's visible right about here: https://github.com/joyent/node/blob/master/deps/http_parser/http_parser.c#L1471
Just try it and see ;-)
it depends
of course you can send a wring content length, the question is what does the client do with it.
there are script or server clients that may attempt to download your content and get completely messed up.
most browsers seem to have some error tolerant behaviour implemented however there are many differenet implementations.
i remember having a old ie keeping the socket open never closing it. this ended up in a never ending page load.
some netscape browser seem to be totally dependent on the right content length.
a good idea is to leave content-legths away. this should work on every browser.
Related
I've got an odd situation. A 3rd party software package is sending notifications to my REST webservice. Unfortunately it has a bug and the incoming HTTP requests are damaged to the point where they are not valid HTTP. Consequently Nodes HTTP parser refuses to accept them and closes the connection.
I have reported the bug but I don't know how long until there is a fix. It could be tomorrow, it could be never.
In the meantime I'd like to get it working anyway. Fortunately the damage is minor and easily repaired. If I could just replace 2 bytes in the incoming data before it gets to Nodes parser, all would be well in the world.
Unfortunately I can't seem to find a way to do it. Node always gets the first crack at the data and rejects it. I've gotten close - I can get the raw socket when it's opened and attach to its "data" event, thus at least seeing the data as it comes in, but it's already too late to modify it.
Any ideas on how to accomplish this?
I have website X which runs a websocket server (socket.io, all based on node.js) and feeds clients with live data.
Now, competitor Y started connecting to our websocket server and straight out stealing data from it, displaying it also live on their website.
I've made numerous attempts at blocking their IPs, but they'll just keep changing it within a matter of minutes. (All kinds of AWS / cloud hosting providers). I check the referrer header, user-agent, accept-language, pretty much anything but all of that is spoofable and they do this already.
The websocket connections are proxied through nginx, if that helps.
What would you do?
Client X (the website) or client Y (the competitor) is meaningless. It's just a client. There is no reliable (i.e. impossible to hack) way to distinguish them unless you restrict IPs (which you already know that it fails). That's because client Y can easily construct a HTTP request/Websocket connection from scratch so that it looks like client X. And there's more: going down that road might be a waste of time and other resources. Eventually you will be hacked. The question is: which company has more resources to withstand this fight? :)
Authentication doesn't change much. Because client Y can authenticate as well. It's just instead of fighting with IPs you fight with user credentials. It might be easier though. You should try it.
So IMHO all in all what you end up with is constant monitoring and reactions. If they break law/agreements then you should sue them. If they don't then you can try this guerilla warfare. You might win eventually, who knows.
You could verify the Origin header in the websocket request matches the origin of your clients. However, I'm not sure if it's possible to fake this header at all.
An Authentication subsystem is a well-known solution to this problem to a large degree.
I've seen this issue happen on multiple machines, using different languages and server-side environments. It seems to always be IIS, but it may be more widespread.
On slower connections, characters are occasionally missing from the response body. It happens somewhere between 25% and 50% of the time but only on certain pages, and only on a slow connection such as VPN. A refresh usually fixes the issue.
The current application in question is .NET 4 with SQL Server.
Example:
<script>
document.write('Something');
</script>
is being received by the client as
<scrit>
document.write('Something');
</script>
This causes the JavaScript inside the tag to instead be printed to the page, rather than executing.
Does anyone know why this occurs? Is it specific to IIS?
Speaking generally, the problem you describe would require corruption at the HTTP layer or above, since TCP/IP has checksums, packet lengths, sequence numbers, and re-transmissions to avoid this sort of issue.
That leaves:
The application generating the data
Any intermediate filters between the application and the server
The HTTP server returning the data
Any intermediary HTTP proxies, transparent or otherwise
The HTTP client requesting the data
The user-agent interpreting the data
You can diagnose further based off of a network capture performed at the server edge, and at the client edge.
Examine the request made by the client at the client edge to verify that the client is making a request for the entire document, and is not relying upon cache (no Range or If-* headers).
If the data is correct when it leaves the server (pay particular attention to the Content-Length header and verify it is a 200 response), neither the server nor the application are at fault.
If the data is correct as received by the client, you can rule out intermediary proxies.
If there is still an issue, it is a user-agent issue
If I had to psychically debug such a problem, I would look first at the application to ensure it is generating the correct document, then assume some interloper is modifying the data in transit. (Some HTTP proxy for wan-acceleration, aggressive caching, virus scanning, etc...) I might also assume some browser plugin or ad blocker is modifying the response after it is received.
I would not, however, assume it is the HTTP server without very strong evidence. If corruption is detected on the client, but not the server, I might disable TCP Offload and look for an updated NIC Driver.
I was under the impression that since a TEARDOWN request releases resources that are normally allocated when a SETUP is made, a TEARDOWN request was only necessary after the SETUP request.
However, I just had an Android device that sent a TEARDOWN immediately after receiving the response to a DESCRIBE request (before the SETUP request, the Session: parameter of the request was empty).
This was unexpected, and I was not able to have a confirmation, even by re-reading the RFC, if this is legit or not.
Can anybody provide information on this? Ideally with am official reference...
Servers should typically be prepared to talk to various clients, and it is a good idea to design servers error prone: clients might send weird commands and servers should reasonably respond. TEARDOWN stops streaming, so it makes no sense to issue it before SETUP, however it is still legit to send this command without SETUP, the server receiving it would just have nothing to do, no resources to free. It is up to server to decide whether to respond with 200 OK, or another status indicating that command makes no sense in this context (e.g. the provided session identifier is not valid).
so I have this TCP connections between my server and client, and anyone can connect to my server. But I want to make sure that the client is really using MY client application and not just faking messages from a fake TCP client. What would be the ways to do that, check that the connection really is from my game client?
Thanks!
EDIT
If I'm gonna use TLS, can I solve that problem?
There will probably not be a complete solution to your problem, since whatever you do, the other party might always take your program, run it in a monitored environment, manipulate the runtime data and let it use its "secure" network protocol. Since the client application is in uncontrollable hands, you can never be sure that it is your own program.
Baby example: My application runs your application and plays back the data to your server, and forwards your response back to the application. How can you tell?
That said, it might be a very promising "99%" approach to use SSL and hardcode the client's private key into the application -- with some trickery you can try and make it hard to find (e.g. see how Skype does it). If you then also build integrity checks into your program that figure out whether anyone is manipulating the memory or debugging into your program, you can try and make it a bit harder for a potential adversary. (But note that you will always have to ship the private key with your application, so it isn't really safe from discovery.)
Others have suggested useful answers to your question, but I'm going to suggest another approach. Re-examine your requirements.
Ask yourself why you want to know the identity of the client program. Is it so that you can trust your client program more than you trust 3rd-party client programs?
If you need to trust the identity or integrity of software that you have already shipped to your customers, I claim your security model is broken. Once the software runs on a client's PC, you should assume it is evil, even if you originally wrote it.
Any status, any command, any data whatsoever that comes from the network must be checked before it is relied upon.
My default response is to use a challenge/response authentication.
After connection, send a random number from the server to the client
The client then computes, using a hash/key/.... a response message and returns that to the server
If the response matches the servers computation, your chances of authenticity are better. Note though that a reverse engineer of your client will leave this method open to fraud.
You could use a public/private key pair in order to verify that you are who you say you are.
http://en.wikipedia.org/wiki/RSA#Signing_messages