I am writing a script that sends emails using the smtplib. I want to store the username and password so that the user doesn't have to enter it every time and I've found many posts about it, but none to the point.
I don't think I need a database to store one username and password (encrypted), but I don't know where to go to.
I was skimming through passlib's documentation, but it seems to return only boolean values and I'd need the password and username.
Any ideas on how to store them?
I don't know the circumstances but for now I can recommend keyring
The Python keyring lib provides a easy way to access the system
keyring service from python. It can be used in any application that
needs safe password storage.
You have to set the credentials once in the user account. The user gets access to the password. It's always best practice to have a service user. You will reach the operating systems level of security.
Related
When connecting to PostgreSQL using Psycopg2 user name and password must be supplied to reach the database. When I'm working in my computer keeping password of my local database as plain text is not a problem.
But when I want to use this script in another computer I need to hide credentials. How this can be done ?
Any help appreciated
h.
The easiest way to hide credentials is to not store them on the public machine. Use the getpass module to prompt future you for your password.
I want to have Python send a mail automatically after certain events occur. In my script I have to enter a password. Is there any way to encrypt my password and use it in this script?
Please give an example as I am not an expert in python. I have seen few answers on this topic but those aren't discussed completely, just some hints are given.
The script needs the password in plain text to send the email. You could encrypt it, but then you also have to provide a way to decrypt it on the fly.
Let me illustrate with some pseudo code.
Right now you have something like this:
password = 'supersecret'
send_mail(password=password)
If you encrypt the password it would look something like this:
encrypted_password = 'kasdjhfkauedsjflh'
encryption_key = 'allyourbase'
send_mail(password=decrypt(encrypted_password, encryption_key)
As you can see, it doesn't really make any difference.
Encryption basically tries to rely on one (and only one) secret.
That is, one piece of data that is known to those who want to communicate but not to an attacker.
In the past attempts have been made to e.g. (also) keep the encryption algorithm/implementation secret, but if that implementation is widely used (in a popular cryptosystem) those attempts have generally fared poorly.
In general that one secret is the password. So that even if the attacker knows the encryption algorithm, he cannot decrypt the traffic if he doesn't know the password.
As others have shown, encrypting a password and giving a script the means to decrypt it is futile if the attacker can get hold of the script. It's like a safe with the combination of the lock written on the door.
On the other hand as long as you can keep your script secret, the key in it is secret as well.
So if you restrict the permissions of your script such that only the root/administrator user can read or execute it, the only way for an attacker to access it is to have cracked the root/administrator account. In which case you've probably already lost.
The biggest challenges in cases like these are operational.
Here are some examples of things that you should not do;
Make the script readable by every user.
Store the script where it can by read be a publicly accessible web-server.
Upload it to github or any other public hosting service.
Store it in an unencrypted backup.
Update: You should also consider how the script uses the password. If it sends the password over the internet in cleartext, you don't have much security anyway.
My way is to use the keyring, simply using yagmail you can have passwordless scripts by using the keyring (full disclose: I'm the developer of yagmail).
E.g. to send an email:
import yagmail
yag = yagmail.SMTP()
yag.send(contents = ["See picture below", "/local/path/to/img.png"])
To get this done, first install (below) and then register your email into the keyring once by using:
yagmail.register('myemail', 'mypass')
If you also put a .yagmail file in your home (~) folder containing your username, you can use yagmail.SMTP() in your script and safely login.
Install:
pip install yagmail # python 2
pip3 install yagmail # python 3
Ironically, I also have made gittyleaks, you can use it to discover username/passwords/email in a git repo, including all history :)
I know the best practise is to hash user passwords, and I do that for all my other web apps, but this case is a bit different.
I'm building an app that sends email notifications to a company's employees.
The emails will be sent from the company's SMTP servers, so they'll need to give the app email/password credentials for an email account they allocate for this purpose.
Security is important to me, and I'd rather not store password that we can decrypt, but there seems like no other way to do this.
If it makes any difference, this is a multi-tenant web app.
What's the best way in python to encrypt these passwords since hashing them will do us no good in trying to authenticate with the mail server?
Thanks!
Note: The mailserver is not on the same network as the web app
I've faced this issue before as well. I think that ultimately, if you are stuck being able to produce a plain-text password inside your app, then all of the artifacts to produce the password must be accessible by the app.
I don't think there is some encryption-magic to do here. Rely on file-system permissions to prevent anyone from accessing the data in the first place. Notice that your SSH private key isn't encrypted in your home dir. It is just in your home dir and you count on the fact that Linux won't let just anyone read it.
So, make a user for this app and put the passwords in a directory that only that user can access.
I would strongly recommend using BCrypt. There are lots of advantages to the algorithm, and most implementations handle all of these questions for you.
As described in this answer:
Bcrypt has the best kind of repute that can be achieved for a cryptographic algorithm: it has been around for quite some time, used quite widely, "attracted attention", and yet remains unbroken to date.
I've written up a detailed article about how to implement BCrypt in python as well as other frameworks here: http://davismj.me/blog/bcrypt
basically, I want to have a login box, and the option to remember the password next time you log in. I know there are encryption modules out there, but they require a password to work in the first place. is there a way to get the password the user used to log into the computer, and use that to encrypt the password for my application?
so in a nutshell, how do I store a password securely for later use.
I'm using python 3, and my program needs to be crossplatform.
Sounds like you need Keyring: https://pypi.python.org/pypi/keyring
There is no way out. If the application does not ask the user for a password, then it is not securely storing passwords, it's only doing... "things". In that case, don't give the user a false sense of security, use cleartext.
A notable exception is the GNOME login keyring (and equivalent on other platforms) not asking for a password, but it uses a trick: it encrypts data with your login password and decrypts them with the same when you enter it at startup.
If you are developing a web application with a local client, consider using OAuth instead of passwords.
You cannot get the password the user used to log in to the computer.
And, if you could, you would not want to store it.
In fact, the OS doesn't even have the user's password. The OS has a hash of it, and when the user logs in, it hashes what the user types and checks that it matches.
Also, if you ask the user to log in with their system password, any savvy user is going to immediately mistrust your app and refuse to use it. Make them create a password, and then login with that, not their system password. And don't save the password, save a hash, just like the OS does.
If you want to verify that they've been authenticated by the OS… well, you already know that, or they couldn't have logged in to run your app. (If you're building a network server that allows remote login based on local accounts, that's a different story, but it's not relevant to your use case, and complicated, so I won't get into it here.)
If you want to allow someone to "stay logged in", you don't do that by saving their password. Instead, you create some kind of hard-to-fake "session key" when they log in, and store that somewhere. They don't have to log in again until you destroy the session key (which you do when they log out).
The one exception to "never store passwords" is when you need to act as a "proxy" for the user to some other application that needs their password. A well-designed application will provide a way for you to proxy the login properly, but many applications are not well-designed. Web browsers have to do this all the time, which is why most web browsers have a "remember my password at this site" checkbox.
In this case, you do want to store passwords, ideally encrypted by the OS on your behalf (e.g., using OS X's Keychain APIs), or, if not, encrypted by you code using some key that's generated from the user's "master password" (which you don't store).
Unfortunately, there is no real shortcut to learning how to design for security—or, rather, there are all kinds of shortcuts, and taking any one of them means your entire system ends up insecure and all the work you put into trying to secure it ends up useless.
The easy solution is to use complete off-the-shelf solutions.
If you want to design things yourself, you need at least a basic grounding in all of the issues. Start with one of Bruce Scheneier's "pop" books, Secrets and Lies or Beyond Fear. Then read his Practical Cryptography on designing cryptosystems, and Applied Cryptography on evaluating crypto algorithms. Then, once you realize how much you don't know and how important it is, learn everything you need for your problem, and then you can think about solving it.
I have a Python script that is connecting to the database. To that, obviously, I need the password. I need to hide it somewhere.
My problem is that this code is stored in a folder that everybody who has access to the server can look. So, if I write this password encrypted in a file, in the code will appear the key to discover it and people can figured it out.
So, please, if anyone has an idea..
You're using a scripting language and accessing a database directly with a password. No matter what you do, at some level that password is going to be easily accessible. Obscuring it doesn't really buy you much.
You have to rely on the machine's security and permissions, and perhaps the database (restricting access from that particular machine and user).
Don't store the database connection credentials in the Python file at all. Instead, store them in a secure place, readable only by the user account that the script will run under.
For example, create a user account for running this job, and create a file in that user account's home directory (readable only by that user) called database.ini and put the database connection string and password there. Then use the Python ConfigParser class in the standard library to read the file in.
Then the job can be always run under that user account. You can also run it under your account by putting a database.ini file in your home directory with the correct credentials, but anyone who doesn't have the credentials cannot run it.
Check out this question. They suggest encoding the password in base64 (outside of the script) then including that string in the script and converting it back before you make the connection
Just to reinforce what Brian said, if a program runs automatically (i.e., without the opportunity to prompt the user for a password), any program that runs under the same user authority has the same access to any password. It's not clear what else you could do. Perhaps if the (trusted) operating system on the client machine could certify to the host that it was being accessed by a program run from a particular path, the host could be told "Only open the database to /var/lib/tomcat/bin/tomcat on appserver.example.com". If you accomplish all that, an attacker would have to compromise the tomcat executable to get to the database.
A more advanced idea is to do the mysql authentication manually. That is, learn the mysql protocol (it's a standard handshake with a challenege and a response) and do the procedure yourself. This way, you never send the password directly.