logo

Inappropriate coding practices - Python


Need

Enforce proper encapsulation in coding practices


Context

  1. Usage of Python 3 for writing and executing Python code

Description

Insecure Code Example

class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password

In the code snippet above, we have a `User` class with two public fields: `username` and `password`. This is considered a vulnerability because it does not respect the principle of encapsulation. Encapsulation is one of the fundamental concepts in object-oriented programming (OOP). It refers to the bundling of data with the methods that operate on that data. Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties' direct access to them. However, in the above code, the `username` and `password` fields are public, meaning they can be accessed and modified directly from outside the class. This can lead to inappropriate or unexpected changes to these fields, leading to potential security risks or bugs in the software. For instance, an attacker could change the `password` field of a `User` object without going through a proper password change procedure (which might involve checking the old password, enforcing password strength rules, etc.). Therefore, it is generally a good practice to make fields private (or protected) and provide public getter and setter methods to access and modify them. This way, you can control and validate how and when these fields are accessed or changed.

Steps

  1. Change the access modifier of the fields to private. This can be done by prefixing the field names with double underscores.
  2. Create getter and setter methods for each field. The getter method will return the value of the field, and the setter method will set the value of the field.
  3. In the setter methods, you can add validation logic to ensure that only valid data is set to the fields.
  4. Replace all direct accesses to the fields with calls to the getter and setter methods.

Secure Code Example

class User:
    def __init__(self, username, password):
        self.__username = username
        self.__password = password

    # Getter method for username
    @property
    def username(self):
        return self.__username

    # Setter method for username
    @username.setter
    def username(self, username):
        self.__username = username

    # Getter method for password
    @property
    def password(self):
        return self.__password

    # Setter method for password
    @password.setter
    def password(self, password):
        self.__password = password

The above code fixes the vulnerability by making the `username` and `password` fields private. This is done by prefixing the field names with double underscores. This ensures that these fields cannot be accessed directly from outside the class, thus respecting the principle of encapsulation. Getter and setter methods are created for each field. The getter method, decorated with `@property`, returns the value of the field. The setter method, decorated with `@field_name.setter`, sets the value of the field. These methods allow controlled access to the private fields. In the setter methods, you can add validation logic to ensure that only valid data is set to the fields. For example, you could check that the `username` is a non-empty string and that the `password` meets certain complexity requirements. Finally, all direct accesses to the fields are replaced with calls to the getter and setter methods. This ensures that the fields are always accessed in a controlled manner, further enhancing the security of the code.


References

  • 138 - Inappropriate coding practices

  • Last updated

    2023/09/18