¿Cómo asegurar la tabla de datos de sesión web basada en MySQL?

3

Tengo el siguiente esquema de sesión de MySQL:

CREATE TABLE 'SessionData' (
  'id' varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  'data' text COLLATE utf8_unicode_ci,
  'date' datetime DEFAULT NULL,
  PRIMARY KEY ('id'),
  KEY 'date' ('date')
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Por lo tanto, quiero evitar que los usuarios lean datos de cada sesión a través de, por ejemplo, Inyección SQL. Quiero asegurarlo usando la vista de MySQL, el procedimiento o algo así. ¿Hay alguna forma común y segura de hacerlo? Creo que es algo común, ya que con esto y el shell remoto es difícil sobrescribir cualquier cosa en el servidor, excepto por sus propios datos de sesión, pero no los archivos y la sesión de SQL y SQL, por lo que es como de solo lectura, pero con escritura solo a su propia fila.

Hago una columna única, conjunto de datos de una sola fila:

CREATE TABLE 'SessionId' (
  'id' varchar(50) COLLATE utf8_unicode_ci DEFAULT '',
  UNIQUE KEY 'id' ('id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Inserto una cadena vacía en ella:

INSERT INTO SessionId (id) VALUES ('');

Entonces puedo crear una vista. En este caso, está utilizando "frontuser", como usuario de MySQL.

DELIMITER $$
DROP VIEW IF EXISTS 'SessionView'$$

CREATE ALGORITHM=UNDEFINED DEFINER='root'@'%' SQL SECURITY DEFINER VIEW 'SessionView' AS (
SELECT
  'SessionData'.'id'   AS 'id',
  'SessionData'.'data' AS 'data',
  'SessionData'.'date' AS 'date'
FROM ('SessionId'
   JOIN 'SessionData'
     ON (('SessionId'.'id' = 'SessionData'.'id'))))$$

DELIMITER ;

Cómo INSERTAR sesión:

INSERT INTO SessionView (id, 'data', 'date')
VALUES (
    HEX(AES_ENCRYPT("Cookie Value", "Random Key from Config")),
    HEX(AES_ENCRYPT("128bit random block + Session Data", "Random Key from Config")),
    NOW());

Cómo verificar la sesión

BEGIN;
UPDATE SessionId SET id = HEX(AES_ENCRYPT("Cookie Value", "Random Key from Config"));
SELECT AES_DECRYPT(UNHEX('data'), "Random Key from Config") FROM SessionView;
UPDATE SessionId SET id = '';
COMMIT;

Por lo tanto, solo otorgo SELECT, UPDATE e INSERT a la vista SessionView. Dado que las claves están aleatorizadas y no hay forma de extraer todas las claves, puedo crear la sesión pero no puedo examinarlas todas.

    
pregunta Andrew Smith 17.07.2012 - 19:47
fuente

1 respuesta

6

Una de las mayores amenazas de seguridad al almacenar datos de sesión en la base de datos es que un atacante puede usar la inyección SQL para obtener la sesión id y usarla para autenticar en lugar de descifrar un hash de contraseña. La solución es cifrar el ID de sesión. El aes_encrypt() de MySQL no es una mala elección para este tipo de datos a pesar de su modo ECB. Debido a que la identificación de la sesión es aleatoria, no tiene que preocuparse por un texto simple repetido con su clave de cifrado (CBC + Random IV generalmente resuelve este problema).

Tenga en cuenta que debe mantener la clave de cifrado en algún lugar y que un atacante podría leerla usando la función load_file() MySQL con inyección SQL. Asegúrese de que file_privs esté deshabilitado para la cuenta de usuario de MySQL que usa su aplicación web.

Sin embargo, el data en sí mismo puede ser sensible. Si ese es el caso, entonces es posible que también sea necesario cifrarlo, y aes_encrypt() sería una mala elección para este tipo de datos. CBC + Random IV es una buena opción. MySQL no permite el apilamiento de consultas, por lo que a un atacante nunca se le permitirá insertar un registro de sesión. Si esto fuera MS-SQL, entonces tendría que preocuparse por este ataque.

    
respondido por el rook 17.07.2012 - 19:58
fuente

Lea otras preguntas en las etiquetas