Secret data/keys in Python script - python

I have some code, that works with my DropBox account via DropBox API with account access token in the code like
token="sdfdsfsdfdsfsf"
dbx = dropbox.Dropbox(token)
I plan to distribute my app with that code, but I don't know, how to protect token value - Python scripts could be easily decompiled and any other people could see my token.
How to protect token in the code, with what ways?
Thank you!

This is indeed a question worth discussing.
We always talk about how to protect our app_key or token in our source code.As a matter of fact,it's really very hard to do this.Especially in your source code which means if your program is decompiled,in any case, your app will be exposed,maybe you encrypt your app_key or token,its role is not very big.
My advice is do not put your real app_key in your source code.So the key to the problem is how to authorize?
Here are serveral plans:
You can store your encrypted key in an external file,and put it on your server or any other VPS, and load it at runtime.The program will get the encrypted key an decrypt it in your program.
Generate your unique token that has privileges for your program.Which means you should build your API key system where you can give keys to your customers.This will protect your dropbox app_key to the greatest extent possible.
IP whitelists.If you deploy your program on the server of your customers.But the premise is that your users are relatively fixed.It will be helpful if your customers are business users,otherwise they're mobile phone users,it will be a bad idea.
Use SSL to prevent hackers from capturing packets.If you want to build your own authorization verification system.To some extent this may effectively protect your interface.
Generate a a temporary token by some of your own methods,maybe you can bind app_key and timestamps together,this temporary token is privileged,but it's just privileged in a very short time.
By the way,you can consult the service provider,perhaps they have already built a set of plans.
Hope this helps.

Related

How to securely store API keys and secrets?

I am building a web application that has some API calls to other services and currently I am just putting these API keys and secrets in variables which is not very secure.
My objective:
To store/secure these API credentials either in the code or store it into the database in encrypted form maybe.
I am currently coding in PHP and I have scripts in python to call these API services. I am planning to do up an API page where users can enter API credentials and it will be encrypted/hashed and stored into the database. But I am not sure if this is the right way or how to go about it.
Any help on this is welcomed. Thank you.
The best way to encrypt things in php is using sodium_crypto_secretbox, which could then be stored in a database. This is still not that secure because you still need to store the secret box key somewhere.
Nowadays most people would shy away from this and use some sort of third party secret storage service. As an AWS user I use Secrets Manager, but there are many other services / products (Hashicorp vault for instance) that provide secret storage and rotation.
Actually you in some levels of security you can't be sure that key is private. First of all hashing is not suitable cause you can't reach api key form its hash so you can't use that api! If you encrypt that api key, there will be a key and an algorithem that you use for your encryption. If this information is likely to be leaked, you can do nothing to stop it! But in general, you trust on some layers of security and you can say store application key in an .env file. I think encrypting can be a good idea for storing keys in database in case of data being leaked by database attacks.

How to store client_secret for serverless apps (Spotipy)

(Note: Now, I know a lot of you might jump ahead and be like "Hey. Duplicate." Please read ahead!)
Background:
My goal is to make a Python app for PC that interacts with Spotify using their python API Spotipy. This obviously brings about the need to store the client_secret for purposes of user authentication. Based on my research, storing this as plaintext anywhere is a big no-no. The other solutions involved encrypting that data (but then, where to store that key). The best solution is apparently to have the authentication request handled by the backend in a server (I being a student, obviously have a million servers at my disposal ;) ...) But seriously, to be clear, I do NOT have a server to host this app on. And I do not want to spend money to buy resources from AWS, or others. Also, to clarify, this is not to be a web application. Is it meant to be downloadable, so that a user can install it, login to Spotify, and voila.
Problem:
Basically, without a server, how do I store this key securely? And based on my usage, is there even a need to store the key securely?
Is it meant to be downloadable, so that a user can install it, login to Spotify, and voila. Basically, without a server, how do I store this key securely?
No secret should reside on the user side. Or the user/hacker will be able to find it sooner or later. More about this here How to store a secret API key in an application's binary?
And based on my usage, is there even a need to store the key securely?
If you work without a server, I see 2 options:
(safe but inconvenient) let the user use their own app ID / Secret,
(risky but convenient) decide to publish your app ID / Secret openly. Since everyone can create Spotify apps for free, there isn't really much that's secret about it, apart from the statistics your app will generate. At least, it shouldn't stop your app from working unless someone decided to use their own time and money to reach the rate limits of your app.
Edit: you might be interested by the Implicit Grant Flow that works without any secret. However it's not implemented yet

Keep a secret key safe in Python

I am aware that these questions has been asked before several times separately, and most of the answers I've found are "Python is not easy to obfuscate, because that's the nature of the language. If you really need obfuscation, use another tool" and "At some point you need a tradeoff" (see How do I protect Python code and How to keep the OAuth consumer secret safe, and how to react when it's compromised?).
However, I have just made a small Python app which makes use of Twitter's API (and therefore needs OAuth). OAuth requires a Consumer Secret, which is to be kept away from users. The app needs that information, but the user should not be able to access it easily. If that information cannot be protected (and I am using obfuscation and protection as synonyms, because I do not know of any other way), what is the point of having a OAuth API for Python in the first place?
The question(s) then are:
Would it be possible to hardcode the secret in the app and then
obfuscate it in an effective manner?
If not, what would be the best way to use OAuth in Python? I have thought of "shipping" the encrypted consumer secret along with the app and using a hardcoded key to recover it, but the problem remains the same (how to protect the key); having the consumer secret in a server, and have the application retrieve it at start up (if information is sent unencrypted, it would be even easier for a malicious attacker to just use Wireshark and get the consumer secret from the network traffic than decompiling the bytecode, plus how could I make sure that I am sending that secret to my app and not to a malicious attacker? Any form of authentication I know would require having secret information in the app side, the problem remains the same); a mixture of both (have the server send the encryption key, same problems as before). The basic problem is the same: how can you have something secret if critical information cannot be hidden?
I have also seen comments saying that one should use a C/C++ extension for those critical parts, but I do not know anything about that, so if that were the answer, I'd appreciate some extra information.
If you want to deploy on servers (or laptop) you own, you can store secrets in env var or files. If you want to deploy to user, suggestion is that you, or your user should register an API key, generate ssl key, or similar.
You can code your own simple symetric crypt fucntion with a lot of data manipulation to make it harder to reverse.
It is unclear why you'd need to ship your OAuth key with the script. That would mean giving anyone access to your Twitter account, whether or not the key itself is obfuscated inside the app.
The more typical scenario is that you develop some Twitter client, and anyone who wants to run it locally will have to input their own OAuth token before being able to run it. You simply do not hardcode the token and require any user to supply the token.

How can I protect my AWS access id and secret key in my python application

I'm making an application in Python and using Amazon Web Services in some modules.
I'm now hard coding my AWS access id and secret key in *.py file. Or might move them out to an configuration file in future.
But there's a problem, how can I protect AWS information form other people? As I know python is a language that easy to de-compile.
Is there a way to do this?
Well what I'm making is an app to help user upload/download stuff from cloud. I'm using Amazon S3 as cloud storage. As I know Dropbox also using S3 so I'm wondering how they protects the key.
After a day's research I found something.
I'm now using boto (an AWS library for python). I can use a function of 'generate_url(X)' to get a url for the app to accessing the object in S3. The url will be expired in X seconds.
So I can build a web service for my apps to provide them the urls. The AWS keys will not be set into the app but into the web service.
It sounds great, but so far I only can download objects with this function, upload doesn't work. Any body knows how to use it for uploading?
Does anyone here know how to use key.generate_url() of boto to get a temporary url for uploading stuff to S3?
There's no way to protect your keys if you're going to distribute your code. They're going to be accessible to anyone who has access to your server or source code.
There are two things you can do to protect yourself against malicious use of your keys.
Use the amazon IAM service to create a set of keys that only has permission to perform the tasks that you require for your script. http://aws.amazon.com/iam/
If you have a mobile app or some other app that will require user accounts you can create a service to create temporary tokens for each user. The user must have a valid token and your keys to perform any actions. If you want to stop a user from using your keys you can stop generating new tokens for them. http://awsdocs.s3.amazonaws.com/STS/latest/sts-api.pdf
Specifically to S3 if you're creating an application to allow people to upload content. The only way to protect your account and the information of the other users is to make them register an account with you.
The first step of the application would be to authenticate with your server.
Once your server authenticates you make a request to amazons token server and return a token
Your application then makes a request using the keys built into the exe and the token.
Based on the permissions applied to this user he can upload only to the bucket that is assigned to him.
If this seems pretty difficult then you're probably not ready to design an application that will help users upload data to S3. You're going to have significant security problems if you only distribute 1 key even if you can hide that key from the user they would be able to edit any data added by any user.
The only way around this is to have each user create their own AWS account and your application will help them upload files to their S3 account. If this is the case then you don't need to worry about protecting the keys because the user will be responsible for adding their own keys after installing your application.
I've been trying to answer the same question... the generate_url(x) looks quite promising.
This link had a suggestion about creating a cloudfront origin access identity, which I'm guessing taps into the IAM authentication... meaning you could create a key for each application without giving away your main account details. With IAM, you can set permissions based on keys as to what they can do, so they can have limited access.
Note: I don't know if this really works, I haven't tried it yet, but it might be another avenue to explore.
2 - Create a Cloudfront "Origin Access Identity"
This identity can be reused for many different distributions and keypairs. It is only used
to allow cloudfront to access your private S3 objects without allowing
everyone. As of now, this step can only be performed using the API.
Boto code is here:
# Create a new Origin Access Identity
oai = cf.create_origin_access_identity(comment='New identity for secure videos')
print("Origin Access Identity ID: %s" % oai.id)
print("Origin Access Identity S3CanonicalUserId: %s" % oai.s3_user_id)
You're right, you can't upload using pre-signed URLs.
There is a different, more complex capability that you can use called GetFederationToken. This will return you some temporary credentials, to which you can apply any policy (permissions) that you like.
So for example, you could write a web service POST /upload that creates a new folder in S3, then creates temporary credentials with permissions to PutObject to only this folder, and returns the folder path and credentials to the caller. Presumably, some authorization check would be performed by this method as well.
You can't embed cloud credentials, or any other credentials, in your application code. Which isn't to say that nobody ever accidentally does this, even security professionals.
To safely distribute credentials to your infrastructure, you need tool support. If you use an AWS facility like CloudFormation, you can (somewhat more) safely give it your credentials. CloudFormation can also create new credentials on the fly. If you use a PaaS like Heroku, you can load your credentials into it, and Heroku will presumably treat them carefully. Another option for AWS is IAM Role. You can create an IAM Role with permission to do what you need, then "pass" the role to your EC2 instance. It will be able to perform the actions permitted by the role.
A final option is a dedicated secrets management service, such as Conjur. (Disclaimer: I'm a founder of the company). You load your credentials and other secrets into a dedicated virtual appliance, and you define access permissions that govern the modification and distribution of the credentials. These permissions can be granted to people or to "robots" like your EC2 box. Credentials can be retrieved via REST or client APIs, and every interaction with credentials is recorded to a permanent record.
Don't put it in applications you plan to distribute. It'll be visible and they can launch instances that are directly billable to you or worst..they can take down instances if you use it in production.
I would look at your programs design and seriously question why I need to include that information in the app. If you post more details on the design I'm sure we can help you figure out a way in which you don't need to bundle this information.

i *must* store third party credentials in my database. best way?

My app must read an SSL url from a third party. How do I best store the third party credentials in my own database, which protects the third party credentials from being compromised? Consider both absolute security and practicality. One-way hashing the credentials is not useful as I must restore credentials to plaintext for the SSL call. I'm using python on google app engine, and my app authenticates with google credentials.
encrypt credentials using e.g. AES and save the encryption key somewhere else (just moves the problem), or derive it from the credentials and keep the algorithm secret (just moves the problem)
encrypt credentials using a synchronous stream cipher, derive the (not)entropy from the credentials and keep the algorithm secret (just moves the problem)
on a separate web app dedicated to storing third party credentials, provide a SSL url to receive the third party credentials, this url is accessed with google credentials (same as my app) and can use authsub or something to transfer authorization to the other web app. this sounds more secure because its harder to hack a trivially simple webapp, and if my complex main app gets compromised the third party credentials aren't exposed.
what do you think about all approaches?
How are the credentials being used? If their use is only triggered by the original owner (eg. you're storing a bank card number and they're making their 2nd purchase) then they can provide a password at that point which is used as your encryption key. You would then never need to store that key locally and the database content alone is useless to an attacker.
It's a difficult task, and no approach will save you the trouble to make sure that there is no weak link. For starters, I wouldn't know if hosting on Google is the best way to go, because you will be forfeiting control (I really don't know if App Engine is designed with the required level of security in mind, you should find that out) and probably cannot do penetration testing (which you should.)
Having a separate small application is probably a good idea, but that doesn't save you from having to encrypt one way or the other the credentials themselves in this smaller app. It just buys you simplicity, which in turn makes things easier to analyze.
I personally would try to design the app so the key changes randomly after each use, having a kind of one time pad approach. You don't specify the app in enough detail to see if this is feasible.
If you need to reversably store credentials there simply is no solution. Use AES and keep the secret key under well paid armed guard.
If your using windows I would check out the Cred* Win32 API (advapi32.dll) it would at least allow you to punt key management to windows syskey where TPM and or bootup passphrase can provide protection against low level compromise (stolen disk drives)
Obviously if your application or the security context within which it runs is compromised none of the above would be of much help.
A decent book that covers this sort of situation is Cryptography In The Database.

Categories