I know I cant prevent people from reverse-engineering my protocol but I'd like to take a security-through-obscurity approach to make it as hard as possible.
I have a server/client system that communicates through the network with http style packets.
Example:
Header
Attribute: Value
Attribute2: Other Value
Payload
I would like to make it as hard as possible for anything other than my client to access the network. Pushing problems with them decompiling my assemblies aside - what would be some good things I could do to this network spec that would make it VERY DIFFICULT to understand and make another implementation without the source?
I was thinking some kind of strange hashing approach or some kind of encryption algorithm that would be difficult.
EDIT I'm not trying to protect my assemblies or source-code. I'm trying to prevent someone from, for example, watching my protocol with WireShark or similar and then making their own implementation based on that information.
All right, three cases:
Users can't access server code and can't access client code: Easiest way is to use a pregenerated shared secret stored in the binary, and aes encrypt/decrypt.
Users can access client or server code but not both: Use a public/private key method. You can encrypt using the public key but the private one is needed to decrypt.
Users can access both client and server code: You're screwed.
If you want to improve security, this static key should only be used during session initiation, to generate a new shared secret, which is then used for communication.
Edit: actually, a more easy and safe solution is to use ssl and certificates (it's a mantra that you shouldn't implement your own encryption) Each certificate comes with a secret private key. As long as users don't have access to that you're safe if you verify that the peer has the exact correct certificate.
For having reversed a few network protocols (from MMOs), I can tell you that you will never protect your protocol for very long, I'm sorry.
The best you can do is:
Obfuscate it using a custom algorithm (because it takes longer to reverse than a known one). Using a known encryption scheme offers no protection whatsoever.
Add noise. Try to be very, very confusing. Add random values that make no sense whatsoever. Try to use a dynamic layout for packets. Move fields. Send useless packets. Just like if it were garbage.
Version your protocol, so that two consecutive version are incompatible. That can be hard to do, but it obliges the reverser to re-do the work for every subsequent version.
But these are just ways to slow down attackers. It's certainly not going to stop them.
There are three solutions:
TLS.
SSLv3.
Whatever you cook up.
1 and 2 already work.
I am also in the process of writing a network protocol in C#. I have made use of encryption to secure the protocol. Here is the outlay of how I did it, you might find this useful.
As soon as the client connects the server requests a random UUID from the client, the client encrypts this UUID with a password know to both the server and client.
All packets sent thereafter by the server or client will encrypted using that UUID as a key.
Regarding "I was thinking some kind of strange hashing approach", hashing is usually only used for data verification. i.e. to ensure it was not modified en-route to you.
Hope this helps.
Related
I am trying o figure out how CoAP server handles authentication. DTLS seems to be the only option. However I could not find any clear example of it for .NET. I have also seen a mention about cookie on server side but that is all, no more information.
https://github.com/chkr1011/CoAPnet seems to be a good library. They also have a client example but I sould not find server example of it. Projest seems to have CoAP server as well, however I could not find it in source code.
Can any client send requests to the server if url is known? Is DTLS the way to go? Is there any server/client example of DTLS in C#?
If a java server will also help, have a look at eclipse/californium. We run a sondbox at "californium.eclipse.org" and if you want to "connect" a client, you may just use the "openssl" PSK demo credentials "Client_identity" and "secretPSK".
Can any client send requests to the server if url is known?
That depends on the protocol variant. Without encryption (plain coap), yes. Some projects then use a "token" in the request, to authenticate the request (see ThingsBoard). With encryption (DTLS, coaps), you need valid credentials, e.g. PSK (as above), a x.509 certificate or a Raw Public Key certificate. There are also setups, where only the server authenticates itself using x.509, and the client then uses the already encrpyted communication to authenticate with an other mechanism (e.g. username/password, so very similar to the model, mostly used with https).
The most pain is usually to find implementations, which could be used in the intended/wanted way. Maybe some projects helps you, to adapt the implementation.
Is DTLS the way to go?
In my opinion, yes. The alternative with OSCORE (payload encryption) are currently in development, we will see, if that changes the game.
Is there any server/client example of DTLS in C#?
I don't know that. Maybe you ask that the project you already found. Or ask here CoAP-CSharp
I have the following concern about security in server-client models...
Imagine the following:
I have an C# WinForms client that wants to communicate with a server (PHP GET-POST Requests, Socket or WebSocket in a Console App C# (Net Framework) running on a Debian under Mono, instead of using ASP.NET).
The first problem that arises is that whether the server (written in PHP or C #) must have some kind of control for the anonymous requests that the client generates, for this, we will have to use some type of token generated by the server to every request.
The problem isn't related to the token (my plan is to use HTTPS (PHP) or SSL / TLS + Certificates in WebSockets (C#) for client-server communications at the network level, to avoid Spoofing or MitM).
The problem arises when the server has to give to a "client" (we need to check its validity, that the main concern) a token to allow the client do requests. It would be very easy to any client to give a token from the server (How? Replicating (inverse ingeenering) a client that makes requests to the server to try to obtain valid tokens, at least, as I plan to implement it, hence the need for help).
In what I was thinking, is to generate a md5 or sha hash for the assembly file of the client. So, if anyone tries to replicate those steps, it will be difficult. Because he/she will need to modify the source code of the assembly or make a malicious assembly and obtain the same hash by collision (this is difficult).
I do not know how efficient is this system, so I need you to guide me a bit in this aspect.
I've been looking at OAuth, and I think that this type of implementation is not the one I'm looking for, because this kind of implementations is for the user level (to avoid that another user violates the main user data), not for the client (application).
So if someone can guide on this issue it would be of great help.
You can't authenticate the client, it is not possible. Anything in the client is known to the user (attacker), any secret, anything you have there. The only question is difficulty, but anything you do, it will not be very difficult.
Also in your hashing scheme, what would you do with the hash, send it to the server? Why would a different client have to match the hash, when it can send whatever it wants (ie. the correct hash, as sniffed from the network)?
So again, because the software needs to run on the client machine, anything that runs there or is sent on the network is disclosed to the user, and he can replicate it in a different client. It is not possible to securely prevent this. Also ssl/tls doesn't help here, if you control one of the endpoints (ie.the client).
Imagine if it was possible somehow, software piracy would not be a thing - but it very much is.
I am building a program for myself that will save my passwords. Now I have the following questions. Because I have a lot of computers (one for work, three for myself), I want to keep the passwords in sync with a server. But now my question is what is the safest way to send data over the internet with c#? Is it possible to make the connection so safe that I can send passwords over it? And maybe any suggestions for the app.
Yes, you can make it reasonably secure. First, I would recommend against writing your own protocol stack, simply because it is so incredibly easy to make a simple mistake that would make it trivial to hack the security.
( Obviously there are plenty of already existing services (like 1password, passpack, etc) but I assume you know that already. )
I would recommend that you focus on the syncing and UI and leave the security to alredy proven libraries. One such solution is to use SSH with RSA authentication and known host keys. This is in use on many production sites and AFAIK considered reasonably secure (though there was one hole in one of the most popular implementations, OpenSSH, some years ago that was pretty bad). The SSH protocol can be used as a carrier for all kinds of different protocol, including your own password-syncing protocol (for that you could just use SOAP or JSON-RPC or something similar that there are plenty of libraries for).
You can then integrate directly with C# by using a SSH client library (https://sshnet.codeplex.com was the first Google hit). I have no experience using C# directly to talk SSH, though. What I usually do is to let an existing SSH client (PuTTY, for example) open up a port forward and then use regular TCP sockets. It all depends on how slick you want the sync app, but since you are writing it for yourself only, I would go with the latter.
If you are clever writing your app, you don't need a server part except of your own (for example, SSH implements SFTP for file storage).
A similar idea is to use SSL. If you pre-trust the certificate chain, this can be made secure enough but my experience is that the default SSL socket API in C# is way too much tied into the Windows architecture, making things like custom certificate validation trickier. Using a publicly exposed server to your service (directly of via IIS) also opens up a lot of new attack vectors.
I'm trying to write a set of simple client/server applications in C# that should communicate with each other through custom RPC-like requests/responses. I want to have everything symmetrically encrypted with a pre-shared key (which the user supplied to each endpoint beforehand), and nonces against replay attacks.
I initially planned to simply use a TCP socket with my own message format and run the packets through AES by hand... but then I read about Remoting and thought that it could make the whole RPC-stuff much simpler for me. But I can't figure out how to use it with encryption (I know I could encrypt every marshalled parameter manually, but there's got to be a better way).
I've found some links about using it with the "secure=true" property, but I don't understand how that works. There seems to be no place to input a key or choose an encryption method, so I guess it uses some "automatic" Windows-internal magic that has to be set up by an administrator and probably doesn't work between domains.
Is there any way to use Remoting with this simple encryption scheme, or what else would be the best way to do this? I don't want to use overblown protocol stacks (with SOAP or HTTP-tunneling, or complicated key-exchange mechanisms, or certificates) - I want something that just works out of the box at any two hosts when you type in the same password.
:)
I want to create a webpage with encrypted text on it which a C# program can decrypt. Could I do this?
I have a WebBrowser on a C# form which loads a page and displays a serial code. I don't want anyone to find out this code, therefore that's why I thought about encrypting it. Maybe there's a better way to do this?
Thanks! :)
Do you mean serial code literally, as in a key for some software that should only be viewable by the intended recipient? If this is the case then kudos for putting more thought and effort in, many places send these around unencrypted.
The answer really is that you need SSL. You need the end-user to be able to read it, so they must have all the information necessary to decrypt it. This means you need an encryption method which still works if someone is listening in (if no one is listening in, why are you encrypting it?), so you must either pre-exchange keys or some secret, use public key cryptography, or use something like D-H key exchange.
The only option that's secure if a third party could make changes to your communications as well as eavesdrop on them is if there is some authentication outside the system, or some transitive trust mechanism. Security certificates for SSL perform this exact function.
You could do this all yourself, but you would be reinventing a whole stack of technologies that's present in every web browser. Buy a cert, send the page over SSL.