Sensitive information in source code - Credentials - Python
Need
Protection of sensitive information in source code
Context
- Usage of Python 3 for writing Python code and running Python applications
- Usage of Django for building web applications
Description
Insecure Code Example
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
SECRET_KEY = 'mysecretkey'
API_KEY = 'myapikey'
The above code is a common configuration in Django's `settings.py` file. The `DATABASES` dictionary is used to configure the database parameters including the database name, user, password, host, and port. The `SECRET_KEY` is a secret unique key for each Django project. It is used for cryptographic signing and should be kept safe. The `API_KEY` is a key used for API access. However, this code is vulnerable because it contains sensitive information - the database credentials, secret key, and API key are all hard-coded into the source code. This is a serious security issue because anyone who has access to this source code can see these credentials and potentially misuse them. This can lead to unauthorized access to the database, misuse of the API, and other potential security breaches. To mitigate this vulnerability, sensitive information like this should be stored in environment variables or secure secret management systems, not in the source code.
Steps
- Remove sensitive information like usernames, passwords, API keys, and secret keys from the source code.
- Use environment variables to store sensitive information. This way, the sensitive data is not exposed in the code.
- Use a secure method to load these environment variables into your application. For example, you can use the 'os' module in Python to load these variables.
- For Django applications, you can use packages like 'python-decouple' to separate the parameters from the source code.
- Never commit sensitive information to version control systems. If you have already done so, make sure to remove it from the history.
- Consider using secret management systems or services for handling sensitive data in a more secure and organized manner.
Secure Code Example
# settings.py
import os
from decouple import Config, Csv
config = Config()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': config('DB_PORT'),
}
}
SECRET_KEY = config('SECRET_KEY')
API_KEY = config('API_KEY')
The above code has been modified to remove the sensitive information from the source code and instead, it is now being loaded from environment variables. The `os` module in Python is used to load these variables. However, for Django applications, it is recommended to use packages like 'python-decouple' to separate the parameters from the source code. In the code, `config` is an instance of the `Config` class from the `decouple` module. This instance is used to fetch the environment variables. The `config` function is used to fetch the value of the environment variable. If the environment variable is not set, a `ValueError` will be raised. For example, `config('DB_NAME')` fetches the value of the 'DB_NAME' environment variable. This way, sensitive data like database credentials, secret keys, and API keys are not exposed in the code. Remember to never commit sensitive information to version control systems. If you have already done so, make sure to remove it from the history. Consider using secret management systems or services for handling sensitive data in a more secure and organized manner.
References
Last updated
2023/09/18