Seguridad en banca electrónica
Este tema lo conozco bastante bien pues ha sido uno de los puntos de discusión que suelo tener con algunos colegas en instituciones financieras (y no todos opinan lo mismo que yo, he de decirles).
El problema
El problema de los ataques Man-in-the-Middle era algo que se veía venir y sólo era cuestión de tiempo antes de que los tokens tradicionales sucumbieran ante ataques más complejos (como referencia aquí está la primera y segunda parte de un artículo que escribí hace un par de años para bankinfosecurity.com; hay que registrarse para leerlos).
La razón de que aún con un token que emula un OTP (con contraseñas dinámicas) puedan acceder ilegalmente a nuestras cuentas bancarias es simple; veamos por qué:
El cliente establece un canal de comunicación con el Banco (encriptado) y a través de este canal efectúa transacciones (línea continua).
Sin embargo, también es posible que el cliente sea engañado y en vez de establecer un canal seguro con el Banco lo establece con un delincuente. Éste a su vez establece otro canal con el Banco y realiza operaciones distintas a las que desea el cliente con las claves de acceso que captura en el momento (línea punteada).
Por ejemplo, mediante un ataque se redirecciona al usuario a un sitio web apócrifo, por ejemplo, a través de una liga dentro de un correo electrónico. El sitio parece idéntico al del Banco ante el usuario y a través de éste se capturan todas las claves de acceso (incluyendo la clave del token); las transacciones fraudulentas se realizan de forma automática y en tiempo real, estableciendo una conexión adicional con el Banco desde el sitio del delincuente.
Así que hemos invertido mucho en recomendaciones a los clientes y en cerrar sitios de phishing, pero los delincuentes tienen aún otra forma de ataque que es mucho más difícil de detectar y de evitar. Veamos con mayor detalle cómo es que se conecta el usuario al banco:
Observen que ningún canal seguro termina en el cliente, sino en la computadora del éste. Es en este equipo donde el usuario teclea el código de seguridad de su token. Ese paso es importante, pues asume que la computadora del usuario "es segura". A través de código malicioso un delincuente puede capturar códigos de seguridad de un token en tiempo real y reutilizarlos para realizar transacciones fraudulentas. También puede modificar el comportamiento del navegador o redireccionar la conexión a otro sitio, aún cuando el usuario teclee correctamente el sitio del Banco (esta técnica es común en spyware).
Así que tenemos un gran problema: Asegurar la computadora del usuario, con toda la diversidad de equipos, de software, de capacidades y de restricciones legales para hacerlo.
Algunas soluciones probadas
Anteriormente había dado yo una primera solución: extender el canal seguro fuera del equipo e implementar autenticación de 2 vías con un secreto compartido. Esto se puede lograr por ejemplo con una tarjeta inteligente con llaves precargadas y un lector con teclado propio. Lo importante es que todas las operaciones se realicen fuera de la computadora (operaciones criptográficas en el chip de la tarjeta inteligente y el ingreso de un PIN para realizar la operación a través de un teclado alterno (el del lector de la tarjeta).
De esta manera, para la autenticación se puede usar criptografía de llave pública (muchas tarjetas inteligentes incluyendo tarjetas de crédito/débito con chip soportan algoritmos de llave pública como RSA) y para asegurar el canal se pueden encriptar y firmar digitalmente las transacciones.
Una implementación adecuada de este esquema daría un nivel de seguridad equivalente al del esquema Chip & Pin, que se utiliza en el Reino Unido; en otras partes de Europa como en Francia utilizan esquemas similares en compras con tarjetas de pago.
Otra solución equivalente consiste en el uso de un token distinto, de los llamados challenge-response. Estos tokens son similares a una pequeña calculadora. Un ejemplo:
Aquí el usuario ingresaría todos los datos de la transacción junto con el código de seguridad a través de su equipo inseguro, pero mediante un protocolo que combine estos datos con el código de seguridad. Por ejemplo:
- El usuario teclea los datos de la transacción en el sitio Web.
- El usuario teclea en su dispositivo los últimos 4 dígitos de la cuenta destino con los primeros 6 dígitos del monto y esto genera un código de seguridad en su token.
- El usuario teclea también este código de seguridad en el sitio web y ejecuta la transacción
- El banco valida los datos de la transacción con el código de seguridad del token (un delincuente podría ver los datos pero no modificarlos porque el código de seguridad no correspondería; tampoco puede generar un código de seguridad para una transacción fraudulenta porque no tiene el token.
- Si los datos de la transacción y el código de seguridad son correctos el banco acepta la transacción.
¿Y que hay de los tokens utilizados actualmente por los bancos? ¿Deben ser reemplazados en su totalidad?
Debemos considerar que en varias partes del mundo se han entregado ya una buena cantidad de tokens más sencillos. Estos tokens están sincronizados a través de una semilla con un servidor central en el Banco y típicamente poseen una pequeña pantalla que muestra códigos de seguridad de entre 6 y 8 dígitos, los cuales que cambian cada vez que se presiona un botón (evento) o bien cada cierto intervalo de tiempo. Ejemplos:
Aquí voy a hacer un breve paréntesis para dejar en claro algo que considero importante (uno de los puntos donde he encontrado opiniones diversas entre instituciones financieras). Algunas Instituciones Financieras e incluso algunos proveedores de tokens han entrado en una discusión sobre si un sistema es mejor que el otro (cambio por evento vs. cambio por tiempo). Al menos en México la discusión inició a raíz de que una institución que utiliza tokens por evento empezó a sufrir ataques donde se engañaba al usuario para teclear el código de seguridad que proporciona el token. Ciertamente, al no expirar por tiempo el valor podía ser usado con mayor tranquilidad por los delincuentes, mientras que el valor de un token por tiempo expiraría en un lapso relativamente breve (típicamente entre 1 y 2 minutos).
Actualmente los atacantes utilizan esquemas donde, de forma automatizada, reutilizan los valores de token capturados inmediatamente después de que los obtienen (es decir, prácticamente en tiempo real), así que no se salva ningún esquema. Peor aún para los tokens de tiempo, dado que existe una ventana de tiempo durante la cual el valor es válido, un delincuente puede realizar varias transacciones fraudulentas durante ese periodo en vez de una sola, como en el caso del token por evento (asumiendo claro, que la institución pide el token para confirmar cada transacción. Si sólo lo usa para autenticar una sola vez al usuario el delincuente puede hacer cuantas transacciones desee una vez que se ha autenticado, independientemente del esquema). Por esta razón pienso que la discusión sobre si un tipo de tokens es mejor que otro es irrelevante, además las vulnerabilidades más graves están a nivel del protocolo en ambos casos y no a nivel de la tecnología.
Regresando a la pregunta de si podemos reutilizar tokens tradicionales (por tiempo o por evento) en un esquema más seguro, permitiendo a las instituciones financieras mantener su inversión y evitando que los clientes tengan que obtener un nuevo dispositivo y aprender un nuevo procedimiento, la respuesta es sí (al menos en teoría).
Antes de ver una propuesta de solución a este problema debemos estar conscientes de que sea cual sea el esquema, hay requerimientos que no podemos dejar a un lado si queremos garantizar la integridad y autenticidad de las transacciones por banca electrónica:
- Que cada transacción se valide
- Que los datos de cada transacción formen parte de la información utilizada por el algoritmo criptográfico para cifrar o autenticar la transacción
- Que el proceso de cifrado/generación de códigos de autenticación se realice fuera de la computadora del cliente, idealmente en un dispositivo externo, cerrado y con medidas contra alteraciones (podemos decir que la mayoría de los tokens y tarjetas inteligentes del mercado son suficientemente seguros al respecto)
Tenemos entonces:
- D= 4 últimos dígitos del número de cuenta destino
- V= 6 dígitos del código de validación del token que corresponden al evento o tiempo de la transacción
- S= 6 dígitos con el secreto adicional
De cierta manera en la tabla se deben de relacionar todos los valores de una forma en que al atacante le resulte por lo menos complicado adivinar alguno o varios de estos valores.
veamos un ejemplo de lo que podría servir como una tabla con estas características:
_ 0 1 2 3 4 5 6 7 8 9
0 8 1 0 5 3 9 4 2 6 7
1 9 3 2 1 0 4 5 8 7 6
2 1 4 3 0 9 5 7 6 2 8
3 3 9 1 8 5 6 2 7 0 4
4 2 0 4 6 7 8 1 5 9 3
5 6 7 9 2 4 0 3 1 8 5
6 4 6 8 7 1 3 9 0 5 2
7 5 2 7 3 8 1 6 9 4 0
8 0 5 6 4 2 7 8 3 1 9
9 7 8 0 9 6 2 0 4 3 1
Bien, observen que cada fila y cada columna tiene a los 10 dígitos (0 al 9) exactamente una vez. Ya sé, se parece a una tabla de Sudoku ;-) pero el término correcto es Cuadro Latino y fue acuñado por Leonhard Euler.
Un cuadro latino se refiere a una tabla de n x n elementos donde existen n diferentes elementos y cada elemento se repite exactamente una vez en cada columna y fila. Por esta característica, si conocemos el número del eje X (por ejemplo el 3) y un valor dentro de este mismo eje X (por ejemplo el 7) podemos obtener el valor correspondiente al eje Y (6 en nuestro ejemplo); de igual forma, si conocemos el número sobre el eje Y y un valor central en este eje podemos conocer el número.
Sin embargo, noten que si sólo conocemos el valor central es imposible conocer el valor de cualquiera de los ejes. Por ejemplo, si el valor central es 3, no hay manera de saber cuál fue la combinación de ejes pues todo eje X está relacionado con un eje Y a través del valor 3.
Excelente. Vamos a probar nuestro esquema con el token y nuestro secreto adicional.
Sea S= 146739 y V= 247410, el Banco genera un cuadro latino de 10 x 10 dígitos (0 al 9) con distribución aleatoria y lo envía al cliente, el cliente toma los valores del eje X (horizontal) del token (V) y los valores del eje Y (vertical) de S, y regresa al Banco los valores centrales correspondientes a cada dígito de V y S, leyéndolos de izquierda a derecha. Con la tabla anterior en nuestro ejemplo el número que regresaría el cliente, T, con los valores centrales de la tabla, es el siguiente: 270897.
Listo, El Banco, dado que conoce S y los valores centrales, puede también obtener V y validarlo con su servidor de autenticación de tokens; un atacante en medio puede capturar T, pero a partir de ese dato no tiene manera de conocer V ni S. Nuestro esquema sin embargo, tal como está, tiene aún un pequeño detalle: el atacante sólo tiene que repetir los valores que envíe el cliente para autenticarse de forma válida ante el Banco; realmente no le importa cuales sean los valores reales de V y S porque puede efectuar un ataque de repetición de mensaje.
¿Podríamos usar el mismo esquema para transmitir los datos de la cuenta destino? No exactamente. La mayoría de la gente que utiliza banca electrónica no transfiere dinero a más de 10 cuentas, por lo que si usáramos este valor como uno de los ejes un atacante podría obtener fácilmente el valor del otro eje (el secreto) con sólo capturar algunas transacciones (en especial si transferimos dinero con frecuencia a una misma cuenta, cosa que mucha gente hace). A diferencia de V, nuestros números de cuenta no cambian destino (D) no cambian, y ahí radica el problema.
Una aparente solución a este problema podría ser que el Banco relacione números aleatorios con cada cuenta destino que se haya prerregistrado, pero tenemos un problema con los clientes que tengan pocas cuentas prerregistradas (menos de 10 por ejemplo), ya que sería trivial para un atacante adivinar cuál número se está usando en uno de los ejes y regresaríamos al problema descrito anteriormente. La solución por lo tanto tiene que ser un poco más compleja que esto.
Dado que que el número de cuenta incluso se podría adivinar, no tiene caso insistir en mantenerlo secreto, lo que tendríamos que hacer es relacionar ese número de cuenta destino con un valor como el del código de verificación (que ahora sí podemos enviar de forma segura) con alguna fórmula y pedirle de nuevo algún tipo de confirmación al usuario de manera que no sea viable generar un nuevo código de validación para una cuenta distinta de la del cliente por alguien realizando una ataque del tipo MITM.
La propuesta es la siguiente:
- El Banco pide los datos de la transacción (nombre, número de cuenta destino, monto destino, etc.) y el cliente se los da a través de su portal de banca electrónica.
- El Banco pide el código de validación del token (V) protegido a través del esquema del cuadro latino con un secreto adicional (S) que comparte con el cliente, y el cliente lo envía como se le pide.
- El Banco reordena los números de ambos ejes y presenta el nuevo cuadro latino al cliente. El reordenamiento debe realizarse de forma que al volver a aplicar el paso anterior, el cliente en vez de obtener T obtiene 6 dígitos de los cuales los primeros 4 coinciden con los últimos 4 dígitos del número de cuenta destino (C), y los últimos 2 dígitos son dígitos aleatorios elegidos por el Banco para la confirmación final.
- El cliente aplica de nuevo la validación con V y con S en el cuadro latino, si los primeros 4 dígitos resultantes coinciden con C, entonces continúa, de lo contrario detiene el proceso.
- Finalmente, una vez que el cliente validó que su transacción es la correcta, en el mismo cuadro latino modificado, identifica en el eje vertical los 2 últimos dígitos (aleatorios que seleccionó el Banco) y en el eje horizontal los primeros 2 dígitos de su código secreto S y envía los 2 dígitos correspondientes en el centro.
- El Banco verifica que los dígitos correspondan con su cálculo propio (él conoce tanto los 2 dígitos aleatorios como los 2 primeros dígitos de S). Si coinciden, da por buena la transacción y la aplica.
_ 0 1 2 3 4 5 6 7 8 9
0 8 1 0 5 3 9 4 2 6 7
1 9 3 2 1 0 4 5 8 7 6
2 1 4 3 0 9 5 7 6 2 8
3 3 9 1 8 5 6 2 7 0 4
4 2 0 4 6 7 8 1 5 9 3
5 6 7 9 2 4 0 3 1 8 5
6 4 6 8 7 1 3 9 0 5 2
7 5 2 7 3 8 1 6 9 4 0
8 0 5 6 4 2 7 8 3 1 9
9 7 8 0 9 6 2 0 4 3 1
- Tanto el Banco como el cliente conocen S= 146739; además el cliente tiene un token estándar de 6 dígitos que está sincronizado (por evento o por tiempo) con un servidor de autenticación del Banco.
- El cliente envía al banco los datos de la transacción, número de cuenta 1234561234563768 (C=3768), con un monto de 5000 pesos a nombre de "Fulanito de Tal".
- El Banco pide al cliente autenticarse con un cuadro latino aleatorío (CL) que le envía al cliente (para nuestro ejemplo ese cuadro es el de arriba), utilizando el valor validación del token (V) y el secreto S. El cliente calcula T=CL(V,S) = CL(247410,146739) = 270897; el cliente envía T al banco.
- El Banco obtiene V=270897 a partir de S y de T, usando T=CL(V,S). Autentica al usuario con V y su servidor de autenticación, si la autenticación es válida prosigue, si no detiene el protocolo mandando un error en valor del token.
- El Banco reordena los valores de los ejes X y Y, y presenta el nuevo cuadro al cliente (ver ejemplo al final del procedimiento), de forma que cuando éste aplique de nuevo el procedimiento del paso 3., obtenga los últimos 4 dígitos de la cuenta destino (C = 3768) y 2 dígitos aleatorios seleccionados por el Banco a los que llamamos (A= 29 en nuestro ejemplo).
- El cliente aplica el procedimiento del punto 3. al nuevo cuadro y verifica que obtiene C y 2 dígitos aleatorios (A), de no ser así asume un ataque MITM, detiene la operación y notifica al Banco. Si los valores conciden procede con el protocolo.
- El cliente calcula por último en el nuevo cuadro los valores resultantes de usar los 2 dígitos aleatorios (A=29) en el eje Y y los primeros 2 dígitos de la clave secreta S (14), y los envía al Banco. A este valor lo llamaremos R (R=20 en nuestro ejemplo).
- El Banco hace el cálculo por su cuenta (dado que también conoce A y S); si los valores coinciden da por autorizada la transacción y la ejecuta, de lo contrario suspende la transacción y envía un mensaje de error.
_ 9 6 8 4 0 3 2 1 5 7
2 8 1 0 5 3 9 4 2 6 7
6 9 3 2 1 0 4 5 8 7 6
9 1 4 3 0 9 5 7 6 2 8
7 3 9 1 8 5 6 2 7 0 4
3 2 0 4 6 7 8 1 5 9 3
1 6 7 9 2 4 0 3 1 8 5
4 4 6 8 7 1 3 9 0 5 2
5 5 2 7 3 8 1 6 9 4 0
0 0 5 6 4 2 7 8 3 1 9
8 7 8 0 9 6 2 0 4 3 1
Es importante notar que S tiene ahora una restricción: los dígitos en S no se deben de repetir. ¿Por qué? Bueno, si V fuera igual a 111111 (el toquen podría llegar a generar un valor con dígitos idénticos) y S= 222222, no hay manera de generar un nuevo cuadro porque no hay reordenamiento posible que nos permita cumplir con los requerimientos del paso 5. Pero si S tiene todos sus dígitos distintos (ej. 012567), el reordenamiento en los valores de los ejes siempre es posible, aún cuando V tenga todos sus dígitos idénticos.
Aclarado este punto revisemos por qué a un atacante se le dificulta efectuar un MITM. Ya habíamos analizado que para un atacante no es viable obtener V a partir de T sin conocer S. De todas formas para la autenticación en sí el atacante no necesita conocer V; simplemente reenvía T al Banco para que acepte la autenticación en el paso 4.
Ahora bien, el atacante quisiera que ese depósito fuera a dar a otra cuenta, así que modifica los datos que envía el cliente en el paso 2. Todo va bien hasta el paso 5; el Banco genera un cuadro con ejes reordenados conforme a S, V, C y un par de dígitos aleatorios (A). el atacante no puede ignorar aún al cliente y continuar el protocolo por su cuenta, puesto que no conoce S y por la misma razón, aunque conocería los números aleatorios de acuerdo a los valores que modificó, no puede enviar al Banco un código de cierre (R) que sea válido. Tendría que adivinar y la probabilidad de encontrar un código correcto es de 1 en 100.
Pero por otro lado, si decide continuar el protocolo no tiene manera de generar un reordenamiento que le asegure que el cliente no va a detectar la intromisión y además que envíe un código válido al Banco para que certifique la transacción, ya que aún conociendo él el número de cuenta destino original, no conoce ni S ni V, y el número de combinaciones posibles en el reordenamiento es del orden de 1.31x10^13, mucho peor que tratar de adivinar él mismo el código de cierre de la transacción (R).
¿Ventajas y desventajas? Una gran ventaja de este protocolo es que le permite al cliente saber si hay o no una intromisión en el paso 6. Aquí no hay otra posibilidad pues de haber tecleado mal T o haber leído mal S o V en el cuadro el Banco mandaría de inmediato un error en el paso 4. y detendría el protocolo. El Banco es quien no puede estar seguro si una confirmación es errónea en el paso 8 a causa de un error o de una intromisión, pero con que una de las partes esté seguro de esto es suficiente, en todo caso la transacción se suspende por cualquier intromisión o error.
Otra ventaja es que el protocolo no requiere el canal encriptado, de hecho el cliente directamente es quien realiza las operaciones en su cabeza (con ayuda del cuadro latino claro), por lo que las operaciones se hacen incluso fuera de una computadora que pudiera estar comprometida, tal como lo revisamos en los requerimientos de un esquema efectivo previamente.
La gran desventaja que yo veo es que aún es demasiado complejo para muchos usuarios de banca electrónica (está diseñado como para geeks). Uno no sólo tendría que ser rápido al leer del token y del cuadro (sobre todo en los casos de tokens sincronizados por tiempo), es casi un hecho que el cliente tendría que estar apuntando en algún lado todos estos valores hasta completar el paso 7 (a menos que tenga una excelente memoria).
Otra desventaja es que obviamente el protocolo que propongo no ha sido analizado con detalle por expertos en criptografía (considero que conozco bastante del tema pero no me considero un experto). Hasta donde veo el protocolo proporciona un nivel de seguridad adecuado, pero se tienen que analizar cosas como la cantidad de información que se filtra con cada reuso de el valor secreto S y si no hay maneras de reducir los ataques actuales (fuerza bruta) para determinar el reordenamiento adecuado por parte del atacante o reducir la probabilidad de adivinar incorrectamente el código de cierre (R).
Como conclusión, yo diría que es posible reutilizar los tokens para autenticación segura de transacciones con protocolos como este, pero dudo de que sea viables implementarlos a gran escala. Quizás este protocolo pueda servir como base para cubrir otras necesidades, pero en lo personal preferiría pagar el costo extra de un token challenge-response.
Fuente: http://candadodigital.blogspot.com/2007/11/seguridad-en-banca-electrnica.html




































