Search code examples
pythonmysqlsecuritycredentials

How to store MySQL credentials in python project, that users not only from my pc will use later?


I have the following code:

class Server:
    def __init__(self):
        #server credentials
        self.ip = "192.168.1.182"
        self.user = "bank_user"
        self.password = "*mypass*"
        self.port = 3307
        self.database = "bank"
    def connect_to_server(self):
        try:
            self.mydb = mysql.connector.connect(
                host = self.ip,
                user = self.user,
                password = self.password,
                port = self.port,
                database = self.database
                )
            self.mycursor = self.mydb.cursor()
            print("✓ Server connection estabilished")
            rlist = [True]

The problem is, I don't want to store it in my code because I feel that it's not safe I'm creating a banking app (just for fun) so it will be used as .py->.exe later by users not only from my pc. I shouldn't be stored in a config file or a plaintext file, because if someone gets the credentials he can basically log into the MySQL database and modify all of the data. So no:

  • Enviromental variables
  • Plaintext/ config file
  • It should work on any pc (I'm using pytoexe to convert my python file to exe, so that everyone can run the app) I'm new to stackoverflow so forgive me if I wrote sth wrong

I thought about creating a password encryption, but anyone who gets the decryption key can decrypt the password. I also thought about creating my own encryption method, but anyone who gets to my code can just use the decrypting function and execute it for example: decryptor("encryptedpassword")


Solution

  • Right, anyone who gets your code can extract the MySQL password and connect using any other client. They can do any SQL query according to the privileges you granted that MySQL user.

    Even if you compile using pytoexe, a skilled person could use a debugger or simply the strings tool to extract the password.

    If you encrypt, they can decrypt. If you try to invent your own encryption algorithm, assume they can decrypt it more easily. I assume you are not an accomplished Ph.D. in applied cryptography, so any novel encryption method you think of will surely be easier to crack than state of the art encryption tools.

    There are two common methods to solve this problem:

    1. Don't give them the MySQL password. The application you give them has no MySQL connection. The application makes HTTP requests to a web service that you develop. The code in your web service implements specific SQL they can execute. This is where you enforce business rules about what they can access. This is by far the most popular solution.

    2. Give them the MySQL password, but restrict the SQL they can execute. Privileges alone only give you limited control, so you need to create a layer of stored routines and views in the MySQL database. They should be able to access the stored routines and views, but the user cannot access the underlying tables. The routines and views have privileges to do that. Therefore the users can only do what you have allowed them to do in those routines and views.

    There could also be a solution using a proxy such as ProxySQL. This would involve writing filters in the proxy so clients would not be allowed to run queries except those you want them to run. The advantage would be that the client application thinks it's connecting to a MySQL Server, but it's really connecting to the proxy. But I think it would be easier to write a web service than to write a whole application's business logic in a proxy.

    I suppose one could also use MySQL's query rewrite plugin to do something similar, but I've never seen anyone do that successfully.