Why should I use User secrets only in the Development environment? - c#

I have to save keys out of project and repository. For this, I want to use User secrets. But it is written there,
Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example
And I can't understand or find a cause. Why can't I use it in the Production environment?

You can find it in the link you provided to the User Secrets documentation:
The Secret Manager tool doesn't encrypt the stored secrets and
shouldn't be treated as a trusted store. It's for development purposes
only. The keys and values are stored in a JSON configuration file in
the user profile directory.

I think the short answer is that you probably could if you wanted to but that it is not what it is intended for.
My understanding is that the primary purpose of User Secrets is to keep credentials out of source control. In the days before GitHub and the cloud, most developers just stuck any and all credentials in the web.config and it was mostly ok. Then lots of people started using public repositories and AWS and all of a sudden https://www.zdnet.com/article/trufflehog-high-entropy-key-hunter-released-to-the-masses/
There are now a great many different tools out there for managing secrets, which one best suits your needs is a much harder question, but you could consider:
Are you using access controlled source control?
Are you cloud or on-prem for build and deploy?
Who has read access to the live servers?
How sensitive is the data you are storing?
What other applications are running on the server?
I was just poking around in the CreateDefaultBuilder method and found this, which is perhaps relevant:
if (hostingEnvironment.IsDevelopment())
{
Assembly assembly = Assembly.Load(new
AssemblyName(hostingEnvironment.ApplicationName));
if (assembly != (Assembly) null)
config.AddUserSecrets(assembly, true);
}
Obviously you don't have to use the default version and you could add secrets for all the environments, but there it is.

This is a development time only tool. Storing any kind of secret in a file is risky, because you may accidentally check it in. In production, you can for example use environment variables to hold secrets (or any other more secure mechanism.)
While environment variables are one of the most used options in web development there are some reasons why this may not be the best approach:
1.The environment is implicitly available to the process and it's hard to track access. As a result, for example, you may face with situation when your error report will contain your secrets
2.The whole environment is passed down to child processes (if not explicitly filtered). So your secret keys are implicitly made available to any 3rd-party tools that may be used.
All this are one of the reasons why products like Vault become popular nowadays.
So, you may use environment variables, but be aware.

User secrets are basically a JSOn File somewhere in your user directory. That works well on your dev pc. But on a production system, the values should usually be injected through more production ready configuration system(s), like Environment Variables, appsettings.json or a azure keyvault. Envs and appsettings are already activated per default.

Related

ASP.Net core how to secure connection string sensitive data in non Azure hosting

I'm new in ASP.Net core, I try to develop ASP.Net core MVC Web API. I need connect to my database. I no idea where I should put my connection string. I put it in appsettings.json file. But it will expose my database password when i deploy the API to the non Azure hosting. I try secret manager but it seem like just for development stage,not sure I understand right or not. I try to put in Environment variable but it not work when in my IIS hsoting.
May i know how I can secure my sensitive data when deploy to Non Azure hosting. Where should I put?
There is analog of Azure KeyVault it free and open source.You can store there your connection strings and others sensitive data.Also there is client library for .net
Your main choices are:
JSON (unencrypted)
Environment variable (unencrypted)
Azure Key Vault (encrypted)
As you correctly ascertained, JSON will be plain-text and is undesirable as a result, mostly because of source control. If you're working on a closed-source solution, this is less of an issue, though. Once deployed on the server, file permissions can keep the details from prying eyes. User secrets is just JSON. It's better in that it's kept out of your project (so it doesn't get committed to your source control), but it's still stored unencrypted, and yes, it's only for development.
Azure Key Vault is the only built-in option that allows encryption, and thus, is the most secure option. You can use Azure Key Vault whether or not your app is actually hosted in Azure. However, it's not free (though, it's also not very expensive).
Environment variables are what's most commonly used outside of Azure Key Vault. While unencrypted, they're stored on the server (outside your project) and are only visible to users with sufficient privileges on that server. If a malicious actor is able to gain access to an account with privileges to view the environment variables, it could be argued that you have far worse problems than exposing database credentials, already.
If the environment variables are not being seen by your app, there's two things to look at:
Ensure that you've added them as system variables and not user variables. User variables are only accessible by the user logged in while adding them (i.e. you), which is almost assuredly not the same user the web server is running as. Alternatively, you can log in add the web server user to add the variables as user variables. This is common when running under a service account. It adds a questionable degree of extra security as only that one account can see the values, not any admin level account (smaller attack surface).
If using IIS, you must edit the advanced settings of the App Pool, and enable "Load User Profile" from there.
I use "Manage Web secrets" to save db and any other crucial data secret from other developers and team mates
This will help you isolate, various platforms as well
you can read more at
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows

Net Core Web API 2.2 Protecting sensitive data

I am developing .Net Core Web API 2.2 project and trying to protect it best I can. This application will be connected to SQL database plus it will be sending emails from the server, and therefore I would like to figure out what is the good way of protecting my sensitive data (such as connection string, database password or even email password for SMTP account).
I have read that it is bad practice storing your passwords in a plain text in your file somewhere and one of the best practices is to use some Microsoft Azure functionality (where you provide some key and it returns you the actual password) that I have not yet used. Furthermore I do not have any subscription with Azure, and for the time being I would like not to go that direction.
Another method proposed by some of you guys was to store all the password to Environmental Variables and simply reference it in the application. I am currently exploring this option, as my app will be hosted on a 'virtual windows server' where I do not have direct access to, and thus it's difficult (without direct access) to get there and set up environmental variables (not even sure if that would be possible).
Finally, so far the best option (in case it will not be possible to use the variables mentioned above), was to actually store connections and passwords directly to appsettings.json file, but to hash them and decrypt on run-time. This option for me is surely feasible; however I wanted to ask (even though this might be quite subjective) you guys, whether this is a correct approach or there is something I have missed that could help me better to protect my application from external threats.
Any suggestions or advices would be more than appreciated as I do not really know now how to proceed.
P.S. I am using VSTS repository to store all the application code, which might be probably (I am guessing) the reason why people suggest to at least hash your passwords when storing them in appsettings.json
The appsettings.json file should never be used for secrets simply because it's committed to source control. That alone makes it a bad choice. However, there is also no capability to encrypt anything in appsettings.json. You could, I suppose, encrypt your secrets via some other means and merely place the ciphertext in appsettings.json manually after the fact, but then you would need some facility to decrypt the secret later, when then means exposing your means of encryption (i.e. your private key), which kind of defeats the entire point. Long and short, don't use appsettings.json.
Environment variables are a compromise solution. Since you manually set them on the server (not in your source control) and they can be made to only be accessible to certain users (restricted access), you get a modicum of security. However, they are also stored plaintext, which means if someone is able access the server to view them, all security is out the window. Environment variables can also be set as part of your CI\D pipeline in DevOps (formerly VSTS), so direct access to the server is not necessarily a prerequisite as long as the service account doing the deploy has the necessary access.
Azure Key Vault is the recommended approach because it's the only built-in config provider that supports encryption, meaning your secrets are encrypted at rest and pretty much secure end-to-end. However, there's nothing uniquely special about Azure Key Vault other than its ready availability. You can conceivably use any type of service that lets store secrets securely; you may just have to write your own config provider to target it.

Where to put Web API endpoints (urls) in an MVC 5 application?

I'm helping create an MVC 5 web application. Its models are being provided via a Web API. Currently, the endpoints for the Web API are hard-coded into our controllers:
public HomeController() {
string baseUrl = "http://webApi.example/api/";
string endpoint1 = "endpoint1/{0}";
}
Obviously this is not the best approach. However, I'm not entirely sure where exactly we should put them. One of the challenges is the different environments the application will have to 'pass' through on its way to Production. For example, it must work 'as is' (with minimal configuration) in a development environment, QA, and ultimately production.
We've considered a few approaches, such as using the Web.config file. But that means we'd have to edit it in each and every environment ... and what if there's 30 development environments? Or 300? We've also considered reading things from the Windows Registry, under a special Key. This could be easily ported to all environments and supplied a 'generic' solution.
However, reading from the registry seems like bad idea (with no proof to tell me that it is or isn't).
So, what architect, strategy, or method could be used to create a valid configuration solution?
I've been using a Web.config for development, beta and production for years.
You certainly could store the setting in the registry, although a Web.config would be easier (editing the registry seems like more of a hassle). The one benefit to using the registry is in the event of sensitive information (e.g. service account password). This would allow the infrastructure team or server administrators to keep the password (registry key value) secret while letting developers deploy Web.config changes freely. In your case it's just a simple URL so who cares?
Either way you're going to be storing the same number of values (either you have 30 different Web.config files or you have 30 different registry entries). However, if you get to the point of having 30 different environments you're probably not going to be hand rolling these configuration entries. You're probably at the scale of having continuous integration and deployments actually powered by software where the values would be dynamic based upon the deployment settings.

Best way to save authentication token?

I've been working on implementing an api in c#. The implementation is going well, but I did come across a concern.
When my library has authorized against the api I have a auth_token which I use for consequent queries to the webservice.
The token needs to be kept between program runs as it stays the same for the user (although I do check if it is still valid when the application starts).
For testing purposes I basically just save the token into a text file which is kept in the root directory of the app.
This works fine, but is this the best way?
Not sure the user will appreciate that it gets saved in a cleartext file (even if it is on his own pc).
So, what is general practice for saving tokens like this?
I would use the Windows Data Protection There are numerous examples around on how to use it from C#. It uses a user specific key to encrypt the data. Only the user themselves can decrypt it. Also be sure to secure the data during transmission between the server and the client.
Create a settings file for your project in the project properties, add a AuthToken property to the known settings (probably at the user level), then use:
Properties.Settings.Default.AuthToken = userAuthToken;
If you think they'll want it hidden, encrypt or encode the userAuthToken so it is less obvious.
You can verify if the api is used under asp.net or windows environment ( it's enough to check if Request is null) and on the first case use a cookie, on the latter save it on a registry key.
That may work in a local app or running the CI locally, but if you are in DevOps (Azure) your test app will reside in your VM bin folder. After every deployment your bin folder gets wiped out so the token you saved in your bin files is gone. Perhaps the best way to save it will be encrypted in one of your DevOps environment variables in your release pipeline so you don't loose it. When running locally you can save it anywhere.

how to secure my windows application in C# from piracy without using database?

I am developing a windows application for my client, in .NET Framework 3.5, using C#.
There is no need of any database in my application.
I want to secure my application by making a registration process at the time of installation, where the user will be asked to enter a registration key, which should be machine dependent, otherwise the user can copy the installation folder and distribute to others, which i don't want to happen.
Please suggest me, how to achieve this.
Thanks,
Bibhu
I believe you will need a registration service.
When the user registers (they'll need to be online), their registration 'code' is sent to your registration service along with their machine details / other identification (username?).
Your service verifies this & returns a key which can be decrypted by your app using their machine details / identification. Your service also marks that registration code as 'used' so that no one else can get a valid key by using it.
The application stores the valid key in registry, or even config. It won't work on another machine because it is specific to the machine details.
my suggestion is this ways:
1)you can create a registery key after registration and in start up of your app check this registery key.
2)you can create a web service (over local network or internet) and on startup check if this version is registerd or not
3)create a custom file and store a hashed value based on machine and in startup of you app check this file
in every 3 way do not forget OBFUSCATION
There is no way to guarantee software is secure. Even registering over a network can be faked with the use of packet analyzers. In securing software, all you can do is make it slightly inconvenient for professionals, difficult for dabblers, and impossible for people with no knowledge. Generally, it's accepted that obfuscation is not a good protection, because someone will eventually figure it out and publish it anyway.
Also keep in mind that the more secure you make your program, the less usable legitimate users are likely to find it. It's a hard balance to strike between usability, security, and the value of what you lose if security is broken. There is no hard and fast 'right' way to secure something.
For machine dependent information, you can gather information about the hardware on that system, hash it somehow, and store the value somewhere, and then check it at the launch of the program each time. It's not fool-proof, but it allows some security fairly easily.

Categories