A Fortify security review informed us of some path manipulation vulnerabilities. Most have been obvious and easy fixes, but I don't understand how to fix the following one.
string[] wsdlFiles = System.IO.Directory.GetFiles(wsdlPath, "*.wsdl");
"wsdlPath" is input from a textbox. Is this something that just can't be fixed? I can validate the path exists, etc. but how is that helping the vulnerability?
If the data is always obtained from a text box whose contents are determined by the user, and the code runs using the permissions of that user, then the only threat is that of the user attacking themselves. That is not an interesting threat.
The vulnerability which the tool is attempting to alert you to is that if low-trust hostile code can determine the contents of that string then the hostile code can mount an attempt to discover facts about the user's machine, like "is such and such a program that I happen to know has a security vulnerability installed and unpatched?" or "is there a user named 'admin' on this machine?" and so on.
You should never feed anything directly into OS API's unfiltered. You should sanitize the input, make sure it doesn't contain paths (ie "../../../somefile" And make sure it truncates long names, and contains only valid filename characters (for instance, there have been various bugs relating to international characters).
With that code, any user that is authenticated and authorized to use that function, is able to access the file system on the server. The access will be done using the credentials of the service account that runs the web application.
Depending on how the returned data is used, a malicious user might be able to get more information or make the server behave in a way that was not intended.
You should limit the set of allowed paths to only consist of one or a few carefully selected directories. Use the functions in the Path class to combine strings into paths - they take care of things like a user entering c:\allowedpath\..\windows\system32 for you.
This kind of scenarios needs encoding and decoding to make sure that data is not manipulated anywhere. Because while decryption if data is changed you will get the wrong results.
You can create your encoding and decoding. I did it using RijndaelManaged and PasswordDeriveBytes classes provided by System.Security.Cryptography;
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!
Thank you for looking into this! My boss asked me about the following: We are in a library and we have online access to journals. When someone requests access to a journal, we log them on. If this has to be done for a whole class of students, it takes quite some time.
Let's assume we have a Csharp application. The application is in the C:/Program Files/ folder together with some kind of configuration file that contains the credentials and URLs and so forth. Since the files are in the C:/Program Files/ directory, a regular user will not have access to copy/manipulate any of the files. Using the CSharp SecureString class, the credentials would be safe. However, as soon as the application opens the browser and uses HttpWebRequest to send a POST request to log us in, the data would not be safe anymore.
Is this correct? A regular user can start an executable and could gain access to the POST data in the browser or can maybe impersonate the browser to get the POST request data.
If this is the case, I have two questions. The second one may be a question about opinions but the first one shouldn't be.
Is there any way to do what my boss wants me to do safely without ever giving anyone access to the credentials?
Is this a bad idea and should not be done at all?
I am also happy about "You should not do this, because..." answers, because this would also solve the problem for me if I can convince her of this.
Thank you!
Edit:
Sorry for the lack of information: Different accounts are used. Most of the time, it would be the student's own domain account. We also have a generic domain account we sometimes use in the library for classes to have the computers already logged in when the class arrives to speed things up. So this is a well known account. Of course entering the credentials in front of the patron as we do now is in no shape, way or form secure either.
It is a provably unsolvable problem. Since the user's machine, in your setup, needs to know the sensitive information, there is no way for you to prevent that machine's user from also knowing that sensitive information. The only way to prevent the user from accessing it is to ensure that the sensitive data is never on the client's machine.
Pretty much any "good" solution is going to require some sort of cooperation with the site in question, which you presumably won't have. Good solutions would involve having a server only you control (with the "real" credentials) log in, and then provide some sort of temporary token or session ID to the user to use for a period of time, and that would expire after a short while.
Another option is to never have the user directly access the site, but rather always access a server you control which will redirect all traffic (that you consider valid) over to the other system. While this is an option that would be possible without any cooperation from the 3rd party, it likely wouldn't be terribly trivial to implement.
I just stumbled across the fact that the Password property of WPF PasswordBoxes is not bindable for security reasons, which makes using them quite cumbersome in a MVVM context.
Answers like https://stackoverflow.com/a/1493330/3198247 suggest that otherwise, the password might be stored in plain text in memory at runtime, which would be a bad idea since it could potentially be read by malware.
However, I still don't seem to understand the reason in general or that answer. There, it says Keeping your password in plain text on the client machine RAM is a security no-no.. However, the password is in memory as soon as it is typed as I'm able to access it from code.
So why would malware not be able to read it directly from the textbox? Am I missing another point here?
edit: To clarify, esp. w/ regards to Sheridan's answer: Assume a PasswordBox where a user types "pw" as his password. Then, clearly "pw" is in memory as I can retrieve it via PasswordBox.Password. Why is it then insecure to additionally be able to bind it to a string property of a ViewModel? Then, "pw" would at most be contained in two strings, but as far as I can see, this should not make it any more or less secure. Or is the point really to "remind" the programmer that the PW should not be stored for longer than needed?
Have a read of this answer
Why is char[] preferred over String for passwords?
I know it is java but I believe the same rule apply. But depending on the level of security required for your system it should be enough. Theres always ways that malware will obtain information e.g. keylogging but theres only so much you can do.
You are missing something.
Plain passwords should never be stored in a database. Instead, passwords are encrypted and then stored in the database. When a user tries to log in, they type their text which you should immediately encrypt and compare to the encrypted password from the database.
Therefore, we never see the unencrypted password, either in the database, or the code.
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 need to scramble the names and logins of all the users in a UAT database we have. (because of the data protection act)
However, there is a catch.
The testers still need to be able to login using the hashed login names
so if a user login is "Jesse.J.James" then the hash should be something like
Ypois.X.Qasdf
i.e. approximately the same length, with the dots in the same place
so MD5, sha1 etc would not be suitable as they would create very long strings and also add their own special characters such as + and = which are not allowed by the validation regex.
So I'm looking for some suggestions as to how to achieve this
I guess I need to rollmy own hashing algorith
anyone done anything similar?
I am using c# but I guess that is not so important to the algorithm
thanks alot
ADDED -
Thanks for all the answers. I think I am responsible for the confusion by using the word "Hash" when that is not what needed to be done
Testers should NOT be logging in as legitimate users. That would clearly violate the non-repudiation requirement of whatever data protection act you're working under.
The system should not allow anyone to log in using the hashed value. That defeats the whole purpose of hashing!
I'm sorry I am not answering your specific question, but I really think your whole testing system should be reevaluated.
ADDED:
The comments below by JPLemme shed a lot of light on what you are doing, and I'm afraid that I completely misunderstood (as did those who voted for me, presumably).
Part of the confusion is based on the fact that hashes are typically used to scramble passwords so that no one can discover what another person's password is, including those working on the system. That is, evidently, the wrong context (and now I understand why you are hashing usernames instead of just passwords). As JPLemme has pointed out, you are actually working with a completely separate parrallel system into which live data has been copied and anonymized, and the secure login process that uses hashed (and salted!) passwords will not be molested.
In that case, WW's answer below is more relevant, and I recommend everyone to give your up votes to him/her instead. I'm sorry I misunderstood.
You do not need to hash the data. You should just randomize it so it has no relation to the original data.
For example, update all the login names, and replace each letter with another random letter.
I think you are taking the wrong approach here. The idea of a hash is that it is one-way, noone should be able to use that hash to access the system (and if they can then you are likely still in violation of the data protection act. Also, testers should not be using real accounts unless those accounts are their own.
You should have the testers using mock accounts in a separated environment. By using mock accounts in a separate environment there is no danger in giving the testers the account information.
Generally speaking, it is ill advised to roll your own encryption/hashing algorithms. The existing algorithms do what they do for a reason.
Would it really be so bad to either give the testers an access path that hashed the user names for them or just have them copy/paste SHA-1 hashes?
Hashes are one-way, by definition.
If all you are trying to protect from is casual perusal of the data (so the encryption level is low), do something simple like a transposition cypher (a 1-1 mapping of different characters to one another -- A becomes J, B becomes '-', etc). Or even just shift everything by one (IBM becomes HAL).
But do recognize that this is by no means a guarantee of privacy or security. If those are qualities you are looking for, you can't have testers impersonating real users, by definition.
Did this recommendation go through your organization's auditing department? You might want to talk to them if not, it's not at all clear the scheme you're using protects your organization from liability.
Why not use a test data generator for the data that could identify an individual?
Creating test data in a database
To give you some more information:
I need to test a DTS package that imports all the users of the system from a text file into our database. I will be given the live data.
However, once the data is in the database it must be scrambled so that it doesnt make sense to the casual reader but allows testers to log in to the system
thanks for all the answers. I think you are almost certainly right about our test strategy being wrong.
I'll see if I can change the minds of the powers that be