今日のほとんどの Web アプリケーションには、少なくともいくつかの基本的なセキュリティ戦略が必要です。たとえば、パスワードで保護されたコンテンツを提供するサイト、管理者のバックエンドのみを備えたサイト、ブログや個人雑誌、電子商取引サイト、企業イントラネットなどです。
この種の Web アプリケーションを構築するための最も一般的な設計方法は、セキュリティ ポリシーを Web アプリケーションのビジネス ロジックに統合することです。つまり、特定のユーザーが次のアクセス許可を持っているかどうかはアプリケーション次第です。データベース内の特定のデータにアクセスします。このシナリオでは、データベースの役割は、データを保存し、要求に応じてデータを提供することだけです。つまり、Web アプリケーションがデータベースに特定の情報を提供するよう命令すると、データベースはユーザーの権限を確認せずにそのコマンドを直接実行します。
この記事では、Oracle の組み込みセキュリティ機能を活用してデータベース レベルでアプリケーション セキュリティ ルールを強制し、アプリケーション全体のセキュリティを向上させる方法を学びます。副次的な利点として、データベース内で直接データ アクセスを保護すると、アプリケーションのセキュリティが向上するだけでなく、複雑さの軽減にも役立ちます。
データベース側のセキュリティの必要性
Web アプリケーションからのデータ アクセスの制御についてはどうでしょうか?ほとんどの場合、問題はありません。特に、関連するデータがミッションクリティカルまたは極秘でない場合には、これは良い解決策です。この方法は、多くの書籍やオンライン リソースで使用されています。実際、ある人気のある PHP/MySQL の本では、「ユーザーを追加したり、複雑な権限を追加したりすると、続行する前にさらに多くの情報のチェックが必要になり、MySQL の実行速度が遅くなる可能性がある」ため、アプリケーションごとに複数のデータベース ユーザー アカウントを作成することを明示的に推奨していません。确实如此;但是,在放弃将安全性整合到数据库逻辑中的想法前可能要考虑几件事情。我们来看以下示例。
假设创建一个内容管理系统 (CMS)。其中使用数据库来存储网站上发布的内容。大部分数据是公开的,允许匿名 Web 用户读取;但只允许编辑更改数据。使用单一数据库帐户访问和修改数据库中的记录,并通过用口令保护仅管理员可以访问的页面的访问权限用 PHP 代码控制安全性。
如果 Web 应用程序的公共端遭受了一个诸如公共搜索表单(即编码不够严密的表单)上的 SQL 注入的攻击,则该入侵者可能能够对该公共帐户可以访问的数据库对象执行任意 SQL 语句。当然,就这里的情形而言,执行 SELECT 语句不会造成什么大问题,这是因为数据本来就是公共的。但由于公共权限和管理权限使用同一数据库帐户,因此入侵者还能执行 UPDATE 和 DELETE 语句,甚至是从数据库中删除表。
怎么才能防止该情况的发生呢?最简单的方法就是彻底限制公共数据库帐户修改数据的权限。我们来看看 Oracle 是如何解决这个问题的。
Oracle 安全性基本概述
Oracle 数据库为 Web 开发人员提供了控制数据访问的许多方法,从管理对特定数据库对象(如表、视图和过程)的访问到控制个别行或列的数据的访问。很显然,对 Oracle 每个安全特性或可用选项的讨论超出了本文的范围。在这里,我们将不涉及过多细节,而仅介绍 Oracle 数据访问安全性的最基本方面: 验证和用户帐户、权限、角色
验证和用户帐户。 与其他数据库一样,请求访问 Oracle 的每个用户(数据库帐户)必须通过验证。验证工作可以由数据库、操作系统或网络服务来做。除基本的验证(口令验证)外,Oracle 还支持强验证机制,如Kerberos、CyberSafe、RADIUS,等等。
角色。 Oracle 角色是一个权限的有名集。尽管可以直接授予用户帐户权限,但使用角色可以极大简化用户管理,尤其是需要管理大量用户时。创建易管理的小角色,然后根据用户的安全级别授予用户一个或多个角色,这样做的效率非常高。更不用说修改权限变得如何简单了 — 只需修改角色关联的角色即可,无需修改每个用户帐户。
为了简化新用户创建初期的工作,Oracle 自带了三个预定义的角色:
CONNECT 角色 — 该角色使用户可以连接数据库以及执行基本的操作,如创建自己的表。默认情况下,该角色不能访问其他用户的表。
RESOURCE 角色 — RESOURCE 角色与 CONNECT 角色相似,但它允许用户拥有较多的系统权限,如创建触发器或存储过程。
DBA 角色 — 允许用户拥有所有系统权限。
使用中的授权和权限
在本部分中,我们将讨论如何使用 Oracle 的授权和权限来提高本文开头部分讨论的那个简单 CMS 示例的安全性。假定,提供给应用程序用户的内容存储在 WEB_CONTENT 表中。
首先,创建该表。启动 Oracle 数据库特别版,以系统管理员身份登录。如果还没有释放示例 HR 用户,请将其释放。按照特别版安装附带的入门指南中的指示操作。请注意,默认情况下,HR 用户被赋予 RESOURCE 角色。在这里,赋予该用户 DBA 角色,这样就可以使用该帐户管理 CMS 应用程序的数据库方面了。当然,不会使用 HR 用户帐户进行在线访问,只用它管理数据库。
现在,可以使用对象浏览器或通过执行 SQL Commands 窗口创建新表。下面是创建该表的代码:
<ccid_code>CREATE TABLE WEB_CONTENT ( page_id NUMBER PRIMARY KEY, page_content VARCHAR2(255) );</ccid_code> ログイン後にコピー |
由于该表是使用 HR 用户帐户创建的,因此该表归 HR 帐户所有并位于 HR 模式中,并且在明确授予其他用户访问该表的权限前,其他用户无法访问该表。如果不信,可以创建一个新用户,用该用户访问 WEB_CONTENT 表试试。
现在,创建两个新用户,CMS_USER 和 CMS_EDITOR。最终,将授予 CMS_USER 对 WEB_CONTENT 表的只读权限,并将该用户用作为匿名 Web 用户提供内容的数据库帐户。CMS_EDITOR 帐户将在该表上拥有更多权限,将被用作 CMS 编辑的帐户(该帐户需要更改和维护该表中的数据)。
可以使用 XE 的图形界面或通过执行以下命令创建新用户:
<ccid_code>CREATE USER cms_user IDENTIFIED BY cms_user; CREATE USER cms_editor IDENTIFIED BY cms_editor;</ccid_code> ログイン後にコピー |
(出于简化的目的,此处的口令与用户名对应。)
为了让这两个帐户都登录数据库,我们需要赋予它们 CONNECT 角色。为此,在 XE 图形界面的 Administration/Database Users 部分选中用户信息下的 CONNECT 复选框,或执行以下命令:
<ccid_code>GRANT CONNECT to cms_user; GRANT CONNECT to cms_editor;</ccid_code> ログイン後にコピー |
现在,如果尝试以 CMS_USER 或 CMS_EDITOR 用户登录并试图从 WEB_CONTENT 表读取数据 (select * from hr.web_content;),将遇到以下错误:
ORA-00942:table or view does not exist
为了访问数据或仅是看到表,需要授予 CMS_USER 和 CMS_EDITOR 帐户对 WEB_CONTENT 表的只读权限:
<ccid_code>GRANT SELECT on hr.web_content to cms_user; GRANT SELECT on hr.web_content to cms_editor;</ccid_code> ログイン後にコピー |
以上代码使这两个帐户可以对 WEB_CONTENT 表执行 SELECT 语句。如果尝试执行其他语句,则会遇到错误。例如,插入一行:
INSERT INTO hr.web_content (page_id,page_content) VALUES (1,'hello world');
将产生错误消息:
ORA-01031:insufficient privileges;
要允许 CMS_EDITOR 更改该表的内容,需要授予以下权限:
GRANT INSERT,UPDATE,DELETE on hr.web_content to cms_editor;
从现在起,CMS_EDITOR 帐户可以对 WEB_CONTENT 表执行 INSERT、UPDATE 和 DELETE 语句。
您看,这有多简单!可见通过角色管理权限是更有效的方法。如果使用的 Oracle 数据库不是 XE,可以执行如下操作:
创建角色:
<ccid_code>CREATE ROLE reader; CREATE ROLE writer;</ccid_code> ログイン後にコピー |
授予角色权限:
<ccid_code>GRANT SELECT ON web_content TO reader; GRANT INSERT,UPDATE,DELETE ON web_content TO writer;</ccid_code> ログイン後にコピー |
赋予用户角色:
<ccid_code>GRANT reader TO cms_user; GRANT reader TO cms_editor; (they need to read too) GRANT writer TO cms_editor;</ccid_code> ログイン後にコピー |
READER ロールの定義を変更すると、その変更はそのロールを持つすべてのユーザー アカウントに影響することに注意してください。権限がユーザーに直接付与されている場合は、各ユーザー アカウントを個別に更新する必要があります。
上記の手順を完了すると、匿名 Web ユーザーによって要求されたすべてのデータベース接続に CMS_USER アカウントを使用し、パスワードで保護された管理ページによって開始された接続に CMS_EDITOR アカウントを使用するように PHP アプリケーションを構成できます。これで、たとえパブリック Web フォームが侵害されたとしても、CMS_USER アカウントには読み取り専用権限しかないため、データベースへの影響は最小限に抑えられます。
結論
この記事では、Oracle データ アクセス セキュリティの最も基本的な機能のいくつかを簡単に紹介しました。さらに、Oracle には、Virtual Private Database (VPD) やタグ セキュリティなど、Web アプリケーションのセキュリティを次のレベルに引き上げる機能が他にも数多くあります。 PHP のコンテキストにおけるデータベース セキュリティ問題の詳細については、私の OTN 記事「PHP アプリケーションのデータ セキュリティの向上」を参照してください。