I'm working on a project that is going to replace legacy software on our manufacturing floor. One of my concerns is that currently, config files, script caches, etc are all plain text, stored on the system that the user is using. A lot of this stuff is going to get pushed off to limit access network locations, but things like config files stay local. It's already been an issue with users thinking that they know what they're doing with the system, and modifying the config files. I don't want this happening any more in the new software. How should I prevent this? Encryption? Do some sort of signing/checksum with a database lookup? What kind of features does C#/.NET offer to help me out with this?
UPDATE: Just to address some things that were brought up in comments, every user on the manufacturing floor has admin access to the system they're working on. This isn't likely to change soon as most of the security comes from limiting access to folders on the network, web services, and databases. Permissions would be ideal, I agree, but I have to work in the environment that I'm provided. I plan to bring it up in a meeting that I have with IS to see if this is a possibility, but assume for now that this will be on a system where the user has full access.
This isn't a C# coding issue, it's a system configuration issue. Set up the machine such that the users have normal (non-admin) accounts. Set the file permissions on the config files you're worried about so that anyone (including your app running as current user) can read the config files, but only an admin can write the config files. Finally, don't give the users the admin password. ;>
If your app needs to be able to write the the config files also, you'll have to add code to transition into admin mode within your app, preferably only around the write operation.
To prevent the average end-user from modifying config files by hand, you could simply sign the config file using the SHA of its contents concatenated with some secret factor known only by the program. This is obviously not a true or perfect secret, but it's enough to prevent simple tampering by end-users.
Basically (pseudo-code):
function isValidConfig(configPath, signaturePath) {
return readFile(signaturePath) == SHA(readFile(configPath) + secret)
}
function writeConfig(contents, configPath, signaturePath) {
writeFile(configPath, contents)
writeFile(signaturePath, SHA(contents + secret))
}
Short of decompiling the program, they won't be able to tamper with the config. I assume you don't have l33t crax0rs on your manufacturing floor...
This seems like a good job for a Digital Signature. A Digital signature will provide integrity and authentication of your data. Meaning the digital signature will detect if the data (config file) has been changed, and that the data originated from a trusted source. A digital signature is created by performing a hash of the data and then encrypting the hash with a private key from a public/private pair. The Application will decrypt the encrypted hash, calculate hash of the data, and compare the decrypted hash to the calculated hash. If the hashes match the data is valid. If they do not match the data has been altered.
.Net contains these functions in DSACryptoServiceProvider.VerifyHash
Of course if you do not want to go through the hassle of creating a public/private key pair you could just go with a simple hash of the config file to make sure it hasn't been altered.
The really important question is; what are you going to do when the application detects an altered config file?
Are you going to have the application quit, lock out certain functions, send an e-mail to you, try to obtain a good copy of a config file? These actions are referred to as the penalty for failing the integrity check. Right now your application is not performing integrity checks on the config file, but when you add the check you will need to decide the best course of action for a failure.
An option is for you to move as much as you can from the config file to either IsolatedStorage or even better to the database. It would be highly unlikely that a typical user would know how to access them.
I'd keep the files in some kind of structured storage, be it isolated storage, slightly encrypted ZIP file or something like our SolFS virtual file system (also encrypted). The secondary benefit of having one file is that it can be copied for backup easily.
I'm not an expert in local security but maybe you could use file system permissions to prevent use access to a given folder or file.
Then, if you application needs to access this file, you will have to launch your application with different windows account that has the right to modify your file.
Related
I have Created a C# Desktop Windows form Application and I have created a setup for that. In the C:\Programs files app folder I have a JSON file. I need to protect it from accessing by anyone (I need to protect the data). What should I do?
You can't. If the intruder have access to the computer with the Administrator rights (or even more - a physical access to the hardware), then any protection will be useless.
You can use some kind of encryption, code obfuscation and some anti-debugging techniques to make it harder to retrieve the data, but qualified intruder with the appropriate access level will be able to access the data in the moment when you will decrypt it.
The only working way is to completely remove the secret data from the client's computer and move it to the your secure server alongside with the processing of such a data. So, client sends the inputs to your server, the server performs the processing using the secret data and sends back ready-to-use results.
First of all: it's impossible to make it un-breakable - I won't argue on this. Then you can simply encrypt it with a simple Blowfish algorithm and keep the key hardcoded.
You can use a more secure algorithm if you want so.
Easiest solution is to use a binary serialization format instead of json. This will make it much harder to understand and decode. Or just hardcode the data instead. Most people lack the knowledge to do anything meaningfull with a binary chunk of data, or an assembly for that matter.
A more complicated solution would be to sign the data, as this would allow you to only hardcode the key. A related alternative is Encryption. Encryption is sufficient but not necessary for ensuring the integrity of the data, but is not really more difficult to apply, see encrypting data.
Whatever you do you cannot really prevent a sufficiently determined and knowledgeable attacker. It is possible to decompile the program and extract or replace any secrets therein. The only truly secure way would be to prevent access to the files in the first place, by moving it to the web for example.
I had a similar requirement and decided to encrypt the data.
I used the package "AuthenticatedEncryption" (available from NuGet ) and could hard-code the key in my code.
NuGet: https://www.nuget.org/packages/AuthenticatedEncryption/
Guthub: https://github.com/trustpilot/nuget-authenticated-encryption
I can do this, as my main purpose is more to make the data unreadable to users and I don't expect it to be unbreakable.
Even so, I change the key every few releases.
For my ~70Kb JSON file I only load it once at the start of the program, so performance is not a problem. Not that I anyway notice anything!
In my application I need to read an encrypted file that is distributed with the app. I also need to connect to a download service using a password. My conundrum is where to store the passwords for these resources? In other languages, such as C++, I would just have stored them in the code. However, as there are tools that can disassemble C#, such as JetBrains DotPeek, that is not secure.
Below are the solutions I have thought of so far, but I don't think any of them are secure:
Store the passwords in the code: No good because C# can be disassembled.
Store the passwords in an encrypted external resource: No good, because then you need to store the password for that!
Ask the user for the password on first use (which they have been told by other means): No good, I think, because don't you still need to store it for subsequent use?
Store them in a C++ dll: No good, because what is to stop anyone else calling the function in that dll?
Hide and encrypt the passwords in the code: For example, don't call it password and use multiple levels of encrypting it. This would make it difficult for someone who was just text searching the code, but wouldn't stop someone prepared to debug the program to find out how the resources were accessed. No good.
Obfuscate the code base to prevent disassembly: Possibly this might work. Is it secure? Does anyone do it?
What is the normal solution to this quite typical problem?
Note: if you want the authentication to be done 100% offline, there is no truly secure way since someone that has access to the computer has access to all of it content.
First off, cpp CAN be decompiled as per this SO answer. It's just ugly as hell.
Why not just use a database which would store hashed passwords ? When the user wants to read the file or download from the service, you ask him for a password then hash it and match it with the hashed version stored in your database. The matching would of course be done over a secure protocol.
Here is a tutorial about ASP.NET auth. You may read it just to understand the way they store the password and match it.
Keep in mind that obfuscation/multiple levels of encryption won't stop someone really determined.
You haven't mentioned my answer at all in your post. Do you dislike this approach or did you not think of it ?
edit: regarding the file, since the user must not be allowed to decrypt it you could have an other "key" stored in the database. When the user authenticates with their password you retrieve the key from the database and decrypt the file. this way the user never sees the key for the file.
As per Vytautas Plečkaitis's suggesstion: you could use the has of your application as an authentication token to retrieve the password for the file from the database. The idea is good from a user-friendly point of view since it allow the user to not have to give any password but it means that the "key" to the database is the same for every instance of your application (crack it once, you cracked them all). Also, this means that to obtain the key to your application all you have to do is get the hash of your executing exe ... i'm nto a security expert (not even close to that) so i dont know how secure that is but i'm not sure that it's the best idea.
To me the password/hash/database pattern is the best, especially since it has been used over and over again for years. This is the built-in method for .NET Core authentication
Did a quick search and found this gem Encrypting app.config File which could be an option for you, just store those credentials inside the app.config. What you'd be doing here is encrypting sections of your configuration file.
You cannot encrypt the entire - it's a
configuration section group, which contains configuration sections.
The aspnet_regiis will only encrypt configuration sections - so you
need to selectively encrypt those parts you need, like this:
cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
aspnet_regiis.exe -pef "system.serviceModel/bindings" .
aspnet_regiis.exe -pef "system.serviceModel/services" .
etc.
With this, you can encrypt what you need easily - what isn't too
important, can be left in clear text.
Word of warning: since it's aspnet_regiis, it expects to be dealing
with a web.config file - copy your app.config to a location and call
it web.config, encrypt your sections, and copy those encrypted
sections back into your own app.config.
Or write your own config section encrypter/decrypter - it's really
just a few lines of code! Or use mine - I wrote a small
ConfigSectionCrypt utility, come grab it off my OneDrive - with full
source (C# - .NET 3.5 - Visual Studio 2008). It allows you to encrypt
and decrypt sections from any config file - just specify the file name
on the command line.
Here is the link to the said OneDrive https://1drv.ms/u/s!AtQ29cmdYW3QgnnBpcHRRCc4_mop and it is currently active.
I am searching for a function that allows me to put a dialog-window(w/ a password query) before the folder is accessed. Is there such a function? Also, this would be great if this protection is there before any program, even Windows Explorer/cmd.exe are allowed to access those files. Is that possible to make?
I'm not using something like IOContainer, passwd. protected ZIPs or any other things that are too slow, because I guess 20GB in one file are a bit overkill and it would take ages to decrypt that file. Is there maybe a VFS solution for C# which supports password protection and can be used as a normal filesystem or folder on the disk?
Thanks!
There exist two options. The simpler one is to have a virtual file system mapped from the file. Our product, SolFS (OS edition), does exactly what you are asking in the second part of your question - it provides a container with optional encryption, which is exposed as a virtual drive so that access to the contents is transparent. Decryption in such systems is done in pages, so 20GB-large file won't be decrypted in whole as you worry.
Another option is to employ a filesystem filter driver, which will intercept requests for directory opening, and will ask the user for a password. This approach is possible (we even have a product for this, called CallbackFilter), but there are two drawbacks in it: first, it's not impossible to remove the driver, leaving the data unprotected. And the second problem is that if you ask the user for a password in a callback, while the OS is waiting for access to the directory, you can end up in a deadlock or a timeout while the user is thinking.
With these two limitations in mind something like SolFS is the preferred and recommended approach.
PS: and we have free non-commercial licenses as well.
I am using C# to make a program which requires a password, and those passwords would be saved in a file. The problem is, I want the program to have access to the file, but not the user. How exactly can I do that? (With GUI, DOS or C#)
Hmmm.. the bottom-line answer here is that there is no way that you can prevent a determined and skilled user from accessing the data - the only thing you can do is make it difficult for him/her.
Here are some possible strategies you might consider for this: Each of these methods requires a different level of skill for the user to obtain the data. The first is almost certainly the hardest to crack.
Encrypt the file - use the .NET ProtectedData class
As in dasblinkenlight's answer, create the file under a different user account
Use Protected Storage
The main problem with this approach is that the password file is stored locally. No matter where you put it, if the legitimate program can read it, any user running with the same permissions can get it too. All you can do is to try to hide it, but that will only give you security though obscurity.
For normal desktop applications that store credentials locally, you should use a hash function on the password given, store that hash, and when authenticating users again, hash their input and compare hashes instead. Never encrypt user passwords, never store passwords as plain text.
In case some "curious" users peek at that file, all they have would be a hash that they have to crack to make any value of it. A determined user will always be able to do that, given enough time, but normally most people are scared at it.
You can create a crypto algorithm so other programs can't open it.
I'd like to bind a configuration file to my executable. I'd like to do this by storing an MD5 hash of the file inside the executable. This should keep anyone but the executable from modifying the file.
Essentially if someone modifies this file outside of the program the program should fail to load it again.
EDIT: The program processes credit card information so being able to change the configuration in any way could be a potential security risk. This software will be distributed to a large number of clients. Ideally client should have a configuration that is tied directly to the executable. This will hopefully keep a hacker from being able to get a fake configuration into place.
The configuration still needs to be editable though so compiling an individual copy for each customer is not an option.
It's important that this be dynamic. So that I can tie the hash to the configuration file as the configuration changes.
A better solution is to store the MD5 in the configuration file. But instead of the MD5 being just of the configuration file, also include some secret "key" value, like a fixed guid, in the MD5.
write(MD5(SecretKey + ConfigFileText));
Then you simply remove that MD5 and rehash the file (including your secret key). If the MD5's are the same, then no-one modified it. This prevents someone from modifying it and re-applying the MD5 since they don't know your secret key.
Keep in mind this is a fairly weak solution (as is the one you are suggesting) as they could easily track into your program to find the key or where the MD5 is stored.
A better solution would be to use a public key system and sign the configuration file. Again that is weak since that would require the private key to be stored on their local machine. Pretty much anything that is contained on their local PC can be bypassed with enough effort.
If you REALLY want to store the information in your executable (which I would discourage) then you can just try appending it at the end of the EXE. That is usually safe. Modifying executable programs is virus like behavior and most operating system security will try to stop you too. If your program is in the Program Files directory, and your configuration file is in the Application Data directory, and the user is logged in as a non-administrator (in XP or Vista), then you will be unable to update the EXE.
Update: I don't care if you are using Asymmetric encryption, RSA or Quantum cryptography, if you are storing your keys on the user's computer (which you must do unless you route it all through a web service) then the user can find your keys, even if it means inspecting the registers on the CPU at run time! You are only buying yourself a moderate level of security, so stick with something that is simple. To prevent modification the solution I suggested is the best. To prevent reading then encrypt it, and if you are storing your key locally then use AES Rijndael.
Update: The FixedGUID / SecretKey could alternatively be generated at install time and stored somewhere "secret" in the registry. Or you could generate it every time you use it from hardware configuration. Then you are getting more complicated. How you want to do this to allow for moderate levels of hardware changes would be to take 6 different signatures, and hash your configuration file 6 times - once with each. Combine each one with a 2nd secret value, like the GUID mentioned above (either global or generated at install). Then when you check you verify each hash separately. As long as they have 3 out of 6 (or whatever your tolerance is) then you accept it. Next time you write it you hash it with the new hardware configuration. This allows them to slowly swap out hardware over time and get a whole new system. . . Maybe that is a weakness. It all comes down to your tolerance. There are variations based on tighter tolerances.
UPDATE: For a Credit Card system you might want to consider some real security. You should retain the services of a security and cryptography consultant. More information needs to be exchanged. They need to analyze your specific needs and risks.
Also, if you want security with .NET you need to first start with a really good .NET obfuscator (just Google it). A .NET assembly is way to easy to disassemble and get at the source code and read all your secrets. Not to sound a like a broken record, but anything that depends on the security of your user's system is fundamentally flawed from the beginning.
Out of pure curiosity, what's your reasoning for never wanting to load the file if it's been changed?
Why not just keep all of the configuration information compiled in the executable? Why bother with an external file at all?
Edit
I just read your edit about this being a credit card info program. That poses a very interesting challenge.
I would think, for that level of security, some sort of pretty major encryption would be necessary but I don't know anything about handling that sort of thing in such a way that the cryptographic secrets can't just be extracted from the executable.
Is authenticating against some sort of online source a possibility?
I'd suggest you use a Assymmetric Key Encryption to encrypt your configuration file, wherever they are stored, inside the executable or not.
If I remember correctly, RSA is one the variants.
For the explanation of it, see Public-key cryptography on Wikipedia
Store the "reading" key in your executable and keep to yourself the "writing" key. So no one but you can modify the configuration.
This has the advantages of:
No-one can modify the configuration unless they have the "writing" key because any modification will corrupt it entirely, even if they know the "reading" key it would takes ages to compute the other key.
Modification guarantee.
It's not hard - there are plenty of libraries available these days. There're also a lot of key-generation programs that can generate really, really long keys.
Do take some research on how to properly implement them though.
just make a const string that holds the md5 hash and compile it into your app ... your app can then just refer to this const string when validating the configuration file