I am using the following code in c# to download a file from my website:
WebClient webClient = new WebClient();
webClient.Credentials = new System.Net.NetworkCredential("username", "password");
webClient.DownloadFile("http://example.com/file.txt", "file.txt");
The file is only downloaded when certain criteria are met, so I don't want the users to be able to access the files on my site
My corcern is that if a curios users decompiles the code, he will find the password and be able to access all the files on my site.
I've read that a secure way to save the password is to store its hash, but I don't know how to implement it in this example.
What options do I have to keep my password secure and make it impossible for a user to find it?
A sobering reality: You can't protect information contained in your program like this.
A must-do: Choose a username/password that is only for accessing the special files this single program needs - not your "access my whole website" username and password.
But just know that all you are doing is adding a little bit of an obstacle, here; anyone who wants to can examine your program and find the username and password.
The only 'correct' way to do this is to do it based on the user's own credentials; their username and password within your own system, for example. Then you would need to give them access based on that information, and your program would need to prompt them for it.
You simply don't. Users give you passwords to do stuff, not the other way around.
If the user has to prove "certain conditions", then pass proof of those certain conditions to the server, and let it decide whether to allow the download or not.
There is no way to prevent that. If you program is able to access the file under condition X, the user is able to trick the program into condition X and get the file no matter what. You can make it harder, but you can't make it impossible.
If the data are in the program itself you can considered them as already being exposed to users. If the credentials are on the users computer regardless on how many measures you take to combat this there is always a possibility to find a way around it.
What you can do is implement a login form for your program and provide the users with login info. Then when the user enters the login info do a check on the server side if the credentials exist (usually by checking in a database) and if it matches send them the file.
But as always, there is the issue with users just sharing the login info with other people and so on.
Related
Situation:
I have an application where our domain users can register their domain account via an Active Directory interface. They can then unlock their account or reset their password via this application. These two "functionalities", the registration/administration & the unlock/reset, take place on different servers. The whole process of unlocking or resetting uses two-factor authentication via a token app on the mobile phone. The only way to link the token to the app is by scanning a QR code (or typewriting the code) which is shown in the registration process. So far so good.
Now it can happen that we have to reset the mobile phone of a user completely, for example for sending it to repair. Even with a backup, the data in the token app cannot be restored. So far, the only possibility to get the QR code back, is to completely delete the registration in our service and re-register again, thereby generating a new QR code. The process of registration takes a while, as you have to think of several security questions (and answers). This is not very user-friendly.
My task now is to implement a function that allows you to show the QR code. This page can be accessed from the "administration" page each user has for their account. The whole site uses single sign on, which of course makes sense, as you don't want to enter the password every time you want to edit a security question for example.
Problem:
With single sign on, every person can walk up to another user's computer and if it isn't locked, show and scan their QR code, change the security questions so they know the answers, reset the victim's password and log into their account. This has to be prevented of course, as it poses a huge security risk.
My approach was to prompt the user's credentials and check whether the user is the same as via SSO by clearing IE's authentication cache via JavaScript. I use the Windows Security window for the credential validation. This way, I don't have to worry about the AD interface.
To check if it's the same user that logged in, I use a cookie with the username from SSO. Then, in the controller, I check if it's equal to User.Identity.Name. If not, I set the cookie with the username from SSO and the rest of the response:
if (cookie.Value.equals(User.Identity.Name))
{
// do some irrelevant stuff
return View();
}
else
{
Request.Cookies["cookieName"] = User.Identity.Name;
Response.AppendHeader("Connection", "close");
Response.StatusCode = 401;
Response.StatusDescription = "Unauthorized";
Response.Clear();
Response.Write("Unauthorized Access");
Response.End();
}
This works just fine. There is one problem though: If you click on cancel in the Windows Security window, you'll be redirected to a "unauthorized access" page. You can then, however, refresh the page and TADA! Single Sign On logged you in automatically and you or the attacker can therefor see the QR code.
Question:
How can I go around SSO in this specific scenario? So far I have only found solutions saying that I should turn off SSO which would affect the whole application.
Sorry
I know this is a long question, my English might not be clear in some cases and I possibly left out some information unintentionally. Feel free to ask for more information.
I have a winform application that have user login form. I store my users login information in database with 3 parameters: username, hashed password, salt:
salt = random string that will be stored in database for every user
hashed password = MD5(MD5(inputPassword) + MD5(salt))
I want to have check box named Remember me in my login form, that when a user enter the correct information and check it, for the next time user open the program, their user information will be entered automatically, user just need to click login button.
I can't save the entered password directly and next time fill the password textBox with it because i know some softwares that can read textBoxes like this and it's not secure.
Question:
How I can do that without saving user password?
If I need to save some information, How encrypt them?
Is it necessary to change my security policy?
Note that this is Client/Server application and login form created for client side.
You can save the hashed value of password in your local database, and you can have a hidden check box, which tells you that you have filled the info from database which is already hashed and while asking authentication you do not need to hash the password value again.
EDIT If the user tries to enter the password manually then you can clear the text box value and alter the check box checked value, so that you know now the value is not the hashed one.
As per my understand, if you want to have remember me functionality then you should/must have your password stored in any form to authenticate the user.
One way is, have 2 functionality in your product. One to have a Hash and this will be in the database and I think you are doing it currently. Apart from this, also have functionality to Encrypt/Decrypt. When remember me is checked then just save the encrypted value in your app.config file. Now when ever the user opens the application again, check for the encrypted password and decrypt to authenticate user.
User dbw just posted my other approach :)
Hope it helps.
IMHO, this can't be done. If you are encrypting/hashing/salting and saving the password in DB then you can't really get it back in plain text.
Of course, you can trick the user (I will tell you how), but need to define what you want the user to do:
Enter at least password again (every time) even after user has asked to "remember me". This can be done easily, just retrieve the user id and keep password box blank. No tricks. Plain and Simple. Even Google do it for their sites.
Now trick time. Let the user enter the application without password but just username. You can just enter some default value in password box (user will think the password is actually retrieved but you will program such a way that whenever "remember me" option is selected, you will just auti-fill this info) and let the user go in. But this is not good option because potentially anyone using that system will be able to logon to your app. You will have to take a call as per your security requirement.
There is a functionality for this on windows. DataProtector and ProtectedData classes can be used to encrypt binary data based on machine information. You can specify the scope of the encryption to be User based or System based it can come in handy for this.
If you think it's better you can only serialize the Login Token information not the User credentials.
You just encrypt the serialized information and store that anywhere you want. And decrypt and deserialize it when you want to use it on startup.
I think so, yes.
You can check them out here:
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.dataprotector?view=netframework-4.7.2
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?view=netframework-4.7.2
I'll start off by saying that I have no idea if what I want can actually be done. If that's the case, do not hesitate to tell me that I'm dreaming.
I want to create a custom active directory "authenticator" in C#. By that, I mean, I would like that whenever someone logs in, their password stored in the AD is checked first, and then a second step of authentication is performed. Only if both steps pass does the user get to log in.
Now, I imagine the above isn't too far fetched, providing I wanted to integrate this authenticator into a custom product, right?. Am I totally insane for also wondering if this authenticator can be used when, say, logging into Windows itself? Or perhaps a pre-existing product which authenticates against the AD?
If I'm not dreaming, would anyone also know of any good articles/APIs to get me going? The APIs don't have to be free, as I'm willing to part with some cash to get things moving faster.
This is entirely feasible. However I'd like to note that, when issuing a server bind to Active Directory, you're checking the provided username (usually the sAMAccountName) and the password entered in one action. There are a few ways of doing this in C#, but many folks (including myself) have opted to use the System.DirectoryServices and System.DirectoryServices.Protocols namespace.
This is how I currently bind users to Active Directory, which then based on the result of this method, I either display the reason for authorization failure, or I allow them to continue on to their account within the application.
//Define your connection
LdapConnection ldapConnection = new LdapConnection("123.456.789.10:389");
try
{
//Authenticate the username and password
using (ldapConnection)
{
//Pass in the network creds, and the domain.
var networkCredential = new NetworkCredential(Username, Password, Domain);
//Since we're using unsecured port 389, set to false. If using port 636 over SSL, set this to true.
ldapConnection.SessionOptions.SecureSocketLayer = false;
ldapConnection.SessionOptions.VerifyServerCertificate += delegate { return true; };
//To force NTLM\Kerberos use AuthType.Negotiate, for non-TLS and unsecured, use AuthType.Basic
ldapConnection.AuthType = AuthType.Basic;
ldapConnection.Bind(networkCredential);
}
catch (LdapException ldapException)
{
//Authentication failed, exception will dictate why
}
}
If you'd like to go a step further and retrieve properties about this user as well, check out this thread here.
Also, I highly recommend Softerra's LDAP Browser for testing anything LDAP related - it is a wonderful product, and it's free. You can download it from here.
Hopefully that gets you going in the right direction.
I have a winform app that requires me to check whether a page exists on our Wiki or not. However, that query requires a users NetWork credentials to be passed.
I don't want to hardcode my credentials, and I don't want users to have to manipulate the App.config everytime someone else uses it (there's also the issue of them having to expose their password in the App.Config). Is there a way I can get the current user's NT credentials? I don't need to see it (that would be an obvious security issue), I just need it for the following line of code:
HttpWebRequest WikiPageRequest;
WikiPageRequest.Credentials = new NetworkCredential("user", "pass", "dom");
//maybe do something like this
WikiPageRequest.Credentials = GetNTCredentials();
Can you try using CredentialCache.DefaultCredential? That seems to get you the current logged in users credential.
If by "wiki", you mean a deployment of MediaWiki, then sadly you need user id and password.
Unfortunately you cannot get it from Windows, because, even the Windows OS itself does not know the password. It just stores a hash of the password.
By the way, why dont you ask for user id/password for wiki each time the user starts the app?
So, I've been playing with asp:PasswordRecovery and discovered I really don't like it, for several reasons:
1) Alice's password can be reset even without having access to Alice's email. A security question for password resets mitigates this, but does not really satisfy me.
2) Alice's new password is sent back to her in cleartext. I would rather send her a special link to my page (e.g. a page like example.com/recovery.aspx?P=lfaj0831uefjc), which would let her change her password.
I imagine I could do this myself by creating some sort of table of expiring password recovery pages and sending those pages to users who asked for a reset. Somehow those pages could also change user passwords behind the scenes (e.g. by resetting them manually and then using the text of the new password to change the password, since a password cannot be changed without knowing the old one). I'm sure others have had this problem before and that kind of solution strikes me as a little hacky. Is there a better way to do this?
An ideal solution does not violate encapsulation by accessing the database directly but instead uses the existing stored procedures within the database...though that may not be possible.
I'm currently implementing an open source user management system on top of Spring + SpringSecurity, and here's how I'm addressing the lost password problem.
The user's account must have a preregistered email address.
To request a reset, the user enters their account name into a form.
A temporary "reset code" is generated and attached to the account, and emailed to the user embedded in a hyperlink.
On receiving the email, the user clicks the link which takes them to a page to enter their new password.
Before accepting the new password, the reset code (from the link) is checked against the stored code, to make sure it is correct and that it hasn't expired.
This avoids sending a password (in clear) in an email message. And it also protects against one person resetting another person's password just to be a nuisance, because the password reset only takes place after the link has been used.
But it does rely on the user's email account being secure, and in the email not being snooped while in transit. For some applications, this maybe an unacceptable risk.
Another piece of the equation is that you need to be really careful about changing a user's registered email addresses. At the very least, the user must enter their current password with the request to change address ... to prevent against hacking via unattended login sessions.
I recommend adding an additional level of checking, here are some options to choose from.
First you can save the requester's IP address in a database, then when they click the reset link compare that with the IP address of their current machine, if they match then reset the password. If the email is intercepted then the person attempting to reset the password must have a matching IP address.
Use a cookie and store a unique value, maybe a GUID, MD5 hash or something. So when the user makes a password reset request a cookie is stored on their machine and in the database, when the user clicks the link the local cookie must match the database value or they will not be able to reset their password.
In general I am totally against ever sending a password in Email, so I like the password reset link option more than a new plain-text password.