Where do you put an encryption key on a public facing server? - c#

I am using NServiceBus with MSMQ between my web application and service and I need to be able to encrypt the message payload so that if a message gets queued locally on the web server (service host is down) that sensitive data can't be viewed.
Because the web server is public facing, I am not only required to encrypt data that may be serialized to disk in anyway, but I also cannot store the encryption key on the web server.
I've considered using DPAPI to store the key, but since the key would be stored on the host I don't know yet if that runs afoul of the requirement or not. The other option I have considered is that when the web application starts it could request the key from a service and hold it in memory for the life of the application pool.
I haven't had to work with this level of requirement on encryption before and would like to find out what others are doing and get some feedback on the ideas mentioned above.

Can you use public/private key encryption? Then you only need to public key on the server, and the data is decrypted using the private key elsewhere.

"Because the web server is public facing, I am not only required to encrypt data that may be serialized to disk in anyway, but I also cannot store the encryption key on the web server."
Seems like this is the only constraint to focus on - validate that it is true for starters. It'll rule out DPAPI + local key-store approaches.
It's plausible to deliver the key by service, but that service still has to authenticate the caller. If your server is compromised masquerading as a legitimate caller, observing the call etc. are all possible. In addition if you stored the key only in-memory, that memory is still discoverable in a debugger or memory dump, elevated privilage process etc.
Hardware encryption cards are the only way to overcome the latter scenarios.

You can override the source from which NServiceBus pulls its encryption key - this is described in the docs here: http://docs.particular.net/nservicebus/security/encryption
This way, you can avoid having this sensitive information reside out on the DMZ.

The best place to encrypt is at the queue level. You do this by sending private messages and creating queues that only accept private messages. While you can set the queue privacy level when you create the queue at creation time, I'm not sure if you can configure NServiceBus to send private messages.

Related

.net core encryption: Share secret key between worker process and client

I have a worker process in a virtual machine which must process files sent by clients, and store the results in a database. We do not want this virtual machine (and thus, the worker process) to directly face the Internet. Clients send those files to an intermediate cloud storage, and later the worker processes them in batch, when there are several of them. That means the files could be in the cloud storage during an undetermined amount of time. One of my requirements is that the files must be encrypted while at rest in this storage. We are using the storage as a service, we do not have control over it (and other requirement is that we should not be bound to a cloud provider, so cloud provider specific solution won't do the job).
The approach we want to follow is to encrypt them in the client using a key shared with the worker process (symmetric encryption). They will be encrypted until the worker process picks them up from the storage and decrypts them using the shared key.
We want to use .Net Core 2.0 data protect framework both on the client and the virtual machine, and we need to share the key between this worker process and clients. Reading through the docs, I've seen we can use a Redis key storage provider, but I understand the use case for that is to share the key between different app servers. Also, I am not sure storing the keys in an Internet facing Redis instance is a good idea (because that increases the attack surface).
So, the question is, how can I share the data protect framework generated keys between worker process and client securely?.
Note: there is also another component, a web server, that will face the Internet and will have direct communication with the virtual machine, but this virtual machine won't directly face the Internet for the aforementioned reasons. We may use this web server to communicate the worker process and the clients, but not sure if there is a better approach.
I think you're overcomplicating the issue. Unless encrypting the files on the client is a requirement (you didn't say so), you don't have to.
Send the files from the client to the server over HTTPS, encrypt them on the server, and then send them to the storage.
This way, you don't need to share anything, the server will control the entire process, and you have the option to save the encryption key in any way you want.
If encrypting the files on the client is a requirement, then encrypt them on the client, send them to the server, send the encryption key to the server over HTTPS, store the key on the server in any way you want, and then send them to the storage.
Note: I don't think that the .NET Core Data Protection is the best choice for your scenario. It's much easier to simply use the AES encryption directly.

How to secure a service from being looped through to find out its api key

Let's say we have a WCF web service. and its link is as follows;
http://www.example.com/service/?api=62383581
62383581 is the API key here. How can we secure the service from being looped through to find out its API key?
i think the discussion should be "how to make it difficult" not preventing it, since if you are going to expose your service to Public you are prone to attacks.
The possibilities to make it difficult could be:
if you are providing access to your service to a close set of customers then you can apply IP restrictions on your Server to prevent calls from any other service, again this will prevent any calls from Client side scripts (e.g. JavaScript) and will be open to IP-Spoofing
You can place IP-restrictions in your Service too. in Message Inspector you can verify the IP and if it's not in your range throw an exception to prevent further access.
Use Alpha Numeric API key with inclusion of special characters to make it very complex and difficult to loop through (Brute force) (The best fit i can consider for your scenario)
you can give your client a public key (different for each client) ask them to append some identifier with key e.g. api&customerID and encrypt it with your key since on server side you have the Private key for that specific client and vice verse.. (this contains overhead of encryption decryption)
and if you have man in middle then this can compromise all above.
These are all to make things difficult and may require rethinking depending on your detailed scenario.
Use GUID instead of Int to make it much harder to bruteforce it.
I suppose checking the caller's IP address and preventing the same IP address to make more than n calls per hour would be pointless, since attackers would use spoofing to throw such efforts off.
The only way I can think of is to use either a strong configurable firewall that can detect such attacks, or an Intrusion Prevention System (IPS) such as Winsnort. See also http://www.winsnort.com/index.php?module=News&func=display&sid=41
Any API key contained in a program on an untrusted client can be leaked by definition.

Need help in protecting WCF service

I'm developing a WCF Service and wnat to protect this service from unauthorized users. so i'm planning to add parameter "RSAKey" to the service and client (AddIn) will generate and sends the RSAKey with every request and Service will check passed RSAKey for that time for that IP and serves only if it is valid.
But my question here is, if some one decompiles the client (AddIn) though it is fuscated if he could guess of actual function that generating "RSAKey", he can call that method and generate RSAKey and use service without a problem.
So, is there anyway to protect my service to be consumed by valid/allowed clients?
Note:
one big thing to conside is, i want to distribute/give the clients freely for public usage without credentials. But same time want to protect from massive copy/miss usage of service.
Short answer: No.
The problem here is that your client needs to be able to connect. Anybody with a copy of your client and the time/knowledge to do it can figure out how it works, and make their own client that passes back the same thing. They're then free to do whatever they want.
A lot of money gets put into trying to accomplish this type of DRM by big companies, and it's always broken. Obscurity is the only real way this type of thing works (where nobody bothers to break it).
The service itself has to try and protect itself from misuse, either through authentication or through trying to sanity check the calls being made to block whatever it is you're trying to prevent. What you're trying to do isn't really very secure.
(What does this service do that you're so concerned about it, anyway?)
It sounds like your main concern is really "over-usage". If that's the case, then how about implementing some type of limitations on the client calls. You could:
-Limit the number of requests a client makes in a specified time period
-Limit the number of results returned in a single request
Of course, neither of these options will protect you over the long term. Given time, any client will still be able to download the entire DB via your service. By using some limitations, you're at least buying some time to analyze logs and determine if one of your clients is actually being malicious. By logging the requests to the service, it should be pretty easy to determine whether a specific client(s) is doing something evil.
Maybe you can host your WCF service by IIS server, then you can enable the https access and you can get the client IP address too. So you can suspend the access ip for a while if there is a suspected attack.
Leave the RSAKey generation out of the client application. Move it to one assembly that will be used both by site from which the client application is being downloaded and WCF service.
Provide RSAKey when user is about to download the client application. Save the {IP address, generated RSAKey} pair in store common to site from which the client application is being downloaded and WCF service.
Provide the ability to set the RSAKey for the client (so the RSAKey will be attached to each WCF message).
Inspect each message received by the WCF service in order to determine whether it contain RSAKey and whether the key is valid (search for existing {IP address, generated RSAKey} pair in common store).

Flash & C# encryption

I am creating a TCP connect with Flash to a C# daemon.
Now I have come to the part of encryption... I know that Flash is decompilable and so not safe to store private keys on.
I need 2 way encryption because of the messages that have to be send back to the Flash client.
I have been thinking and googling, but cannot find a proper solution yet.
Anybody got an idea??
You'd usually use a hybrid encryption.
Client opens a session on the server, acquiring public key for an asymmetric encryption.
Client generates a key for a symmetric encryption, and sends this key to the server, encrypted with the public key previously acquired.
The rest of the communication is encrypted using a symmetric encryption with they key now known to both client and server.
greetz
back2dos
back2dos' solution will work (and be the easiest) if your connection is SSL/TLS.
If you are forced to use regular sockets (e.g., the server does not have an SSL certificate), then you'll need to do the same by hand. In this case, you'll need to use a Diffie-Hellman key exchange, which enables the creation of a shared secret that is not actually sent over the wire.
Again, if possible, use back2dos' solution. It's a lot easier.

Is it possible to enforce web service calls from known client only?

Scenario:
A publically available Web Service that I have full control over.
But I only want this specific desktop application (my published application) to have access to the Web Service.
I could store a secret password in the desktop client, but that would be easy to crack.
Is there any known implementation that enforces this?
PKI, assymmetric keys?
If the public will have access to copies of this Desktop App, any good reverser will be able to crack it and "imitate" its transactions with the server. It doens't matter how secure is your cryptography, everything you app needs to encrypt/decrypt data is included in the binaries, so the cracker only needs to dig it out of it.
The objective of cryptography is to protect data while it is being transfered, from "middle-man" hackers, but if you have access to anyone of the peers, you can easily crack it.
Your server must never trust what comes from the client side.
[edit resuming]
Despite you cannot 100% guarantee a supposed client to your server is or isn't your App or some "emulator" made by thirdies, you can complicate things to them. Its a common practice in game anti-cheats to sometimes, randomly, make the client App a trick question like "whats the hash of your main.exe from offset A to offset B?" or "from now on packet type 0x07 swaps with packet type 0x5f". Once a fake is detected, server enter in a "silly mode", act malfunctional, and blacklist their IP/account to this mode for several hours so they cannot have sure of what their program is doing wrong.
If you detect someone is building an emulator, make them start all over again: jumble the packet type tables, cryptography tables, change some packet formats and force your clients to update. You won't see crackers bothering you for a while... LOL
WS-Security provides for X509 encryption.
Part of that implementation includes the possibility of only giving specific clients the generated public key. That way, only your selected clients can connect to the service.
The easiest way is message security using client and server certificates. The best way is to import the client certs in your server machines and hard code the client cert thumbprint in the app.config file. The other way is negotiation of certs which I haven't tried before.
If you are using IIS to host the service then client certificates using SSL is another option.
MSDN link on WCF Security.

Categories