Secure password storage
Scope: managed applications, mobile applications, and ordinary applications.
1. Subsystems that interact with external resources, such as email, web services, and FTP resources, must request and pass authentication data: a username and password.
2. To reduce the risk of unauthorized access to passwords, avoid storing passwords or any other sensitive information in the infobase. File infobases provide the weakest level of protection, as files can be easily copied by any user. In client/server infobases, only DBMS administrators have access to the databases.
Therefore, it is best to pass user credentials immediately without saving them to the infobase.
3. In some cases, this approach might not be feasible:
- Forcing users to re-enter their credentials for every operation has a negative impact on the user experience, while client-side caching does not help much.
- Interactions with external resources must be handled on the server side, regardless of user activity within the application.
In these scenarios, it is acceptable to store passwords and sensitive information in the infobase, but users should be informed about the risks. Keep in mind that this method does not eliminate all security concerns, as unauthorized access is still a possibility.
3.1. Avoid storing passwords and other sensitive information in attributes of metadata objects that are used in everyday operations. Instead, use a separate metadata object, such as an information register, to store this data. Ensure secure access by managing permissions within the 1C:Enterprise access rights system.
3.2. For configurations that embed Standard Subsystems Library (SSL), use a secure password vault to solve the following tasks:
- Prevent users from accessing passwords stored in metadata object attributes. When kept in the secure vault, passwords can only be retrieved and written in privileged mode.
- Safeguard data by storing it in a secure format that prevents unauthorized access.
- Avoid exposing passwords during data exchanges by excluding the secure vault from exchange plans.
To manage the secure password vault, use procedures and functions in the Common module: WriteDataToSecureStorage, ReadDataFromSecureStorage, and DeleteDataFromSecureStorage. For more information, see comments to these functions and the SSL documentation (Core > How to use the subsystem in development > Secure password vault).
3.3. Avoid storing passwords in form attributes. Instead, access them only on the server side just before using them. Otherwise, when a form with a masked input field is opened, the password is sent from the server to the client openly, risking exposure to unauthorized users. Make sure to enable privileged mode right before calling functions rather than inside them to prevent passwords from being received or written in a session with any rights. The calling code that accesses specific passwords must implement security measures.
To mask a password, use the following code in the OnCreateAtServer event handler:
SetPrivilegedMode(True);
Passwords = Common.ReadDataFromSecureStorage(Object.Ref, "Password, SMTPPassword"); // Password and SMTPPassword are data map keys in a secure vault.
SetPrivilegedMode(False);
Password = ?(ValueIsFilled(Passwords.Password), ThisObject.UUID, "");
SMTPPassword = ?(ValueIsFilled(Passwords.SMTPPassword), ThisObject.UUID, "");
In the OnWriteAtServer event handler:
If PasswordChanged Then
SetPrivilegedMode(True);
Common.WriteDataToSecureStorage(CurrentObject.Ref, Password);
SetPrivilegedMode(False);
Password = ?(ValueIsFilled(Password), ThisObject.UUID, "");
EndIf;
If SMTPPasswordChanged Then
SetPrivilegedMode(True);
Common.WriteDataToSecureStorage(CurrentObject.Ref, SMTPPassword, "SMTPPassword");
SetPrivilegedMode(False);
SMTPPassword = ?(ValueIsFilled(SMTPPassword), ThisObject.UUID, "");
EndIf;
where Password and SMTPPassword are form attributes. If a password was previously saved in the application, assign a unique form ID to the corresponding attribute to emulate password availability. If a new password is entered, write it to the object and rewrite the form attribute with a unique ID.