web-dev-qa-db-ja.com

MySQLベースのWebセッションデータテーブルを保護する方法

次の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

だから私は、ユーザーが他のセッションデータを例えばSQLインジェクション。 MySQLのビュー、手順、またはこのようなものを使用してそれを保護したいと思います。それを行うための一般的で安全な方法はありますか?これとリモートシェルでは、独自のセッションデータではなく、ファイルとSQLとSQLセッションを除いて、サーバー上で何かを上書きすることが難しいため、これは一般的なことだと思うので、読み取り専用のように書き込みます自分の行だけに。

単一列、単一行のデータセットを作成します。

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

空の文字列を挿入します。

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

それで、ビューを作成できます。この場合、MySQLユーザーとして「frontuser」を使用しています。

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 ;

セッションを挿入する方法:

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());

セッションの確認方法

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;

そのため、SessionViewビューにSELECT、UPDATE、およびINSERTのみを許可します。キーはランダム化されており、すべてのキーを抽出する方法がないため、セッションを作成できますが、すべてを参照することはできません。

3
Andrew Smith

データベースにセッションデータを保存する最大のセキュリティ脅威の1つは、攻撃者がSQLインジェクションを使用してセッションidを取得し、パスワードハッシュをクラックする代わりにそれを使用して認証できることです。解決策は、セッションIDを暗号化することです。 MySQLのaes_encrypt()は、ECBモードであっても、このデータ型の悪い選択ではありません。セッションIDはランダムであるため、暗号化キーで繰り返されるプレーンテキストを心配する必要はありません(通常、CBC +ランダムIVでこの問題が解決されます)。デプロイメントによっては、ハッシュセッションIDの方が簡単な場合があります。

暗号化キーはどこかに保持する必要があり、攻撃者はSQLインジェクションでload_file() MySQL関数を使用して暗号化キーを読み取ることができる可能性があることに注意してください。 Webアプリケーションが使用するMySQLユーザーアカウントで_file_privs_が無効になっていることを確認します。

ただし、data自体は機密性が高いかもしれません。その場合、これも暗号化する必要がある可能性があり、aes_encrypt()はこのタイプのデータには適していません。 CBC + Random IVは良い選択です。 MySQLではクエリのスタックが許可されていないため、攻撃者がセッションレコードを挿入することはできません。これがMS-SQLの場合、この攻撃を心配する必要があります。

6
rook