Saltar a contenido

Personally Identifiable Information (PII) Leakage

Fuga de información de identificación personal (PII)

Descripción

La información de identificación personal (PII) es, de acuerdo con la Publicación Especial 800-122 del NIST, un término colectivo para cualquier información que pueda utilizarse para distinguir o rastrear la identidad de una persona, como el nombre, el número de seguro social, la fecha y el lugar de nacimiento, el apellido de soltera de la madre o los registros biométricos; y cualquier otra información que esté vinculada o sea vinculable a una persona, como la información médica, educativa, financiera y de empleo.

En el contexto de la seguridad móvil, la fuga de PII se produce cuando la información PII en texto claro se registra en los registros de la aplicación o en un archivo de lectura global, lo que la hace accesible a todas las aplicaciones en el dispositivo del usuario.

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Suponiendo que tiene campos EditText para nombre de usuario y contraseña en su diseño
        // con los identificadores 'usernameEditText' y 'passwordEditText' respectivamente

        loginButton.setOnClickListener {
            val username = usernameEditText.text.toString()
            val password = passwordEditText.text.toString()

            // Registra las credenciales del usuario
            Log.i("UserCredentials", "Username: $username, Password: $password")

            // Realice la lógica de inicio de sesión aquí
            performLogin(username, password)

            // Limpia los campos EditText después de iniciar sesión
            usernameEditText.text.clear()
            passwordEditText.text.clear()
        }
    }
}
import UIKit
import os.log

class ViewController: UIViewController {

    @IBOutlet weak var usernameTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Realice cualquier configuración adicional después de cargar la vista.
    }

    @IBAction func loginButtonTapped(_ sender: UIButton) {
        guard let username = usernameTextField.text, !username.isEmpty,
              let password = passwordTextField.text, !password.isEmpty else {
            // Maneje el nombre de usuario o contraseña vacíos
            return
        }

        // Registra las credenciales del usuario
        os_log_info("Username: %@, Password: %@", log: .default, type: .info, username, password)

        // Realice la lógica de inicio de sesión aquí
        performLogin(username, password)

        // Limpia los campos de texto después de iniciar sesión
        usernameTextField.text = ""
        passwordTextField.text = ""
    }
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Login Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatelessWidget {
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  final logger = Logger(
    printer: PrettyPrinter(),
    output: FileOutput('login_log.txt'),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login Page'),
      ),
      body: Padding(
        padding: EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: _usernameController,
              decoration: InputDecoration(
                labelText: 'Username',
              ),
            ),
            SizedBox(height: 10.0),
            TextField(
              controller: _passwordController,
              decoration: InputDecoration(
                labelText: 'Password',
              ),
              obscureText: true,
            ),
            SizedBox(height: 20.0),
            ElevatedButton(
              onPressed: () {
                _login(context);
              },
              child: Text('Login'),
            ),
          ],
        ),
      ),
    );
  }

  void _login(BuildContext context) {
    final username = _usernameController.text;
    final password = _passwordController.text;

    // Registra las credenciales del usuario como información
    logger.i('Username: $username, Password: $password');

    // Realice la lógica de inicio de sesión aquí
    performLogin(username, password)

    // Limpia los campos de texto después de iniciar sesión
    _usernameController.clear();
    _passwordController.clear();

    // Opcionalmente, puede navegar a otra pantalla o realizar otras acciones después de iniciar sesión correctamente
  }
}

Recomendación

  • Al guardar PII/PHI localmente, asegúrese de que estén cifrados y que las claves de cifrado se almacenen en el KeyChain.
  • El acceso a la información PII debe estar protegido por autenticación biométrica.
  • Si corresponde, evite almacenar la información PII en la memoria caché local; en su lugar, consúltela desde los servidores backend.
  • Elimine de forma segura la PII/PHI cuando ya no exista una necesidad empresarial para su retención en el dispositivo.
  • Considere cifrar y/o aplicar funciones hash a los datos PHI/PII antes de guardarlos en el dispositivo.
  • Proporcione a los usuarios una manera de retirar su consentimiento para la retención de sus datos PHI/PII.
  • No almacene en caché los datos PII/PHI.
  • Minimice el uso de bibliotecas de terceros y API que acceden a los datos del usuario.
  • Algunas jurisdicciones pueden requerir que proporcione una política de privacidad para acceder a la información personal.
  • Si es necesario registrar información PII, establezca el nivel de registro en debug para que la PII no aparezca en los registros de la aplicación de producción.
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Suponiendo que tiene campos EditText para nombre de usuario y contraseña en su diseño
        // con los identificadores 'usernameEditText' y 'passwordEditText' respectivamente

        loginButton.setOnClickListener {
            val username = usernameEditText.text.toString()
            val password = passwordEditText.text.toString()

            // Registra las credenciales del usuario
            Log.d("UserCredentials", "Username: $username, Password: $password")

            // Realice la lógica de inicio de sesión aquí
            performLogin(username, password)

            // Limpia los campos EditText después de iniciar sesión
            usernameEditText.text.clear()
            passwordEditText.text.clear()
        }
    }
}
import UIKit
import os.log

class ViewController: UIViewController {

    @IBOutlet weak var usernameTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Realice cualquier configuración adicional después de cargar la vista.
    }

    @IBAction func loginButtonTapped(_ sender: UIButton) {
        guard let username = usernameTextField.text, !username.isEmpty,
              let password = passwordTextField.text, !password.isEmpty else {
            // Maneje el nombre de usuario o contraseña vacíos
            return
        }

        // Registra las credenciales del usuario
        os_log_debug("Username: %@, Password: %@", log: .default, type: .info, username, password)

        // Realice la lógica de inicio de sesión aquí
        performLogin(username, password)

        // Limpia los campos de texto después de iniciar sesión
        usernameTextField.text = ""
        passwordTextField.text = ""
    }
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Login Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatelessWidget {
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  final logger = Logger(
    printer: PrettyPrinter(),
    output: FileOutput('login_log.txt'),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login Page'),
      ),
      body: Padding(
        padding: EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: _usernameController,
              decoration: InputDecoration(
                labelText: 'Username',
              ),
            ),
            SizedBox(height: 10.0),
            TextField(
              controller: _passwordController,
              decoration: InputDecoration(
                labelText: 'Password',
              ),
              obscureText: true,
            ),
            SizedBox(height: 20.0),
            ElevatedButton(
              onPressed: () {
                _login(context);
              },
              child: Text('Login'),
            ),
          ],
        ),
      ),
    );
  }

  void _login(BuildContext context) {
    final username = _usernameController.text;
    final password = _passwordController.text;

    // Registra las credenciales del usuario como información
    logger.d('Username: $username, Password: $password');

    // Realice la lógica de inicio de sesión aquí
    performLogin(username, password)

    // Limpia los campos de texto después de iniciar sesión
    _usernameController.clear();
    _passwordController.clear();

    // Opcionalmente, puede navegar a otra pantalla o realizar otras acciones después de iniciar sesión correctamente
  }
}

Enlaces

Estándares

  • OWASP_MASVS_L1:
    • MSTG_ARCH_12
  • OWASP_MASVS_L2:
    • MSTG_ARCH_12
  • GDPR:
    • ART_32
    • ART_25
  • PCI_STANDARDS:
    • REQ_3_2
    • REQ_3_3
    • REQ_3_5
    • REQ_3_6
    • REQ_3_7
    • REQ_4_2
    • REQ_6_2
  • OWASP_MASVS_v2_1:
    • MASVS_STORAGE_1
    • MASVS_STORAGE_2
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • HIPAA_CONTROLS:
    • SECURITY251
    • SECURITY212
    • SECURITY213