Aller au contenu

Insecure password storage

Stockage non sécurisé des mots de passe

Description

Le stockage non sécurisé des mots de passe peut entraîner la compromission des comptes. La vulnérabilité est le résultat du stockage des mots de passe à l'aide de méthodes non sécurisées qui sont susceptibles d'accès non autorisés ou de compromission.

L'exemple suivant montre le stockage non sécurisé des identifiants de mots de passe dans les cookies :

response.addCookie(new Cookie("password", password));

Recommandation

Pour stocker en toute sécurité les identifiants de compte, considérez les recommandations suivantes :

  • Pour Android, utilisez AccountManager pour stocker les identifiants de compte.
  • Pour iOS, utilisez keychain pour stocker les identifiants de compte.
import android.accounts.Account
import android.accounts.AccountManager
import android.content.Context

fun saveCredentials(context: Context, accountType: String, username: String, password: String) {
    val accountManager = AccountManager.get(context)
    val account = Account(username, accountType)
    accountManager.addAccountExplicitly(account, password, null)
}

fun getCredentials(context: Context, accountType: String, username: String): String? {
    val accountManager = AccountManager.get(context)
    val accounts = accountManager.getAccountsByType(accountType)
    for (account in accounts) {
        if (account.name == username) {
            return accountManager.getPassword(account)
        }
    }
    return null
}
import Foundation

func saveCredentials(username: String, password: String) {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: username,
        kSecValueData as String: password.data(using: .utf8)!,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
    ]

    SecItemDelete(query as CFDictionary)
    SecItemAdd(query as CFDictionary, nil)
}

func getCredentials(username: String) -> String? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: username,
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne
    ]

    var dataTypeRef: AnyObject?
    let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)

    guard status == errSecSuccess, let data = dataTypeRef as? Data else {
        return nil
    }

    return String(data: data, encoding: .utf8)
}
import 'package:flutter/services.dart';

class CredentialService {
  static const platform = MethodChannel('credentialChannel');

  static Future<void> saveCredentials(String username, String password) async {
    try {
      await platform.invokeMethod('saveCredentials', {'username': username, 'password': password});
    } on PlatformException catch (e) {
      print("Failed to save credentials: '${e.message}'.");
    }
  }

  static Future<String?> getCredentials(String username) async {
    try {
      return await platform.invokeMethod('getCredentials', {'username': username});
    } on PlatformException catch (e) {
      print("Failed to get credentials: '${e.message}'.");
      return null;
    }
  }
}

Liens

Normes

  • OWASP_MASVS_L1:
    • MSTG_STORAGE_2
  • OWASP_MASVS_L2:
    • MSTG_STORAGE_2
  • PCI_STANDARDS:
    • REQ_2_2
    • REQ_3_6
    • REQ_3_7
    • REQ_6_2
  • OWASP_MASVS_v2_1:
    • MASVS_STORAGE_1
    • MASVS_STORAGE_2
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_6_7
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • CNIL_FOR_DEVELOPERS:
    • DEVELOPERS_4_1_2
  • HIPAA_CONTROLS:
    • SECURITY251
    • SECURITY212
    • SECURITY213