Web 应用程序的受限 PostgreSQL 权限
Restricted PostgreSQL permissions for web app
目标
创建三个用户的数据库并限制他们的权限(我只是想出声,所以我的用户分离也有待更正):
- 超级用户 - 此用户允许对数据库进行最初始的配置。创建应用程序数据库,创建其他用户,设置他们的权限。默认
postgres
超级用户为我工作,所以这个就完成了。
- 管理员 - 此用户只能访问在配置期间创建的数据库。管理员可以CRUD所有表中的所有数据,也可以CRUD表等"Superuser for only this database"类型的情况。更新应用程序时,管理员是自动化工具用来处理数据库迁移的用户。
- 应用程序用户 - 此用户最终是支持网络应用程序功能的用户。请注意,这与网页上的用户等无关 - 这是服务器用来 运行 查询、插入和删除数据的用户。我明确地不希望此用户能够修改任何内容的权限,也不希望create/destroy表或索引或任何结构。
我试过的
首先,查看(总体来说非常出色的)PostgreSQL 文档,page on Grant 几乎让我感到不解。在花了几个小时阅读有关 PostgreSQL 角色和特权的内容后,我通常感到困惑。我认为通过更多的工作,我将能够为管理员用户确定我想要的内容,但我仍然停留在 "app user" 上。我已经了解了这么多(命名和密码都只是占位符):
$ psql -U postgres
postgres=# CREATE USER "app-admin" WITH PASSWORD 'password';
CREATE ROLE
postgres=# CREATE USER "app-user" WITH PASSWORD 'password';
CREATE ROLE
postgres=# CREATE DATABASE "test-database" WITH OWNER "app-admin";
CREATE DATABASE
postgres=# \c "test-database"
You are now connected to database "test-database" as user "postgres".
test-database=# DROP SCHEMA "public";
DROP SCHEMA
test-database=# CREATE SCHEMA "app" AUTHORIZATION "app-admin";
CREATE SCHEMA
这就是我不确定的地方。我觉得我想避免的答案是 "revoke everything by default then enumerate all the privileges you'll need at all the different levels on all the different objects"。我试图避免这种情况,因为我直接不知道我在那里需要什么。如果这最终成为答案,那么我只需要蹲下并阅读更多内容,但通常当我开始沿着这样的道路走下去时,我会错过一些东西。
问题
如何限制 app-user
的权限,使他们无法修改任何结构数据(例如,无法添加或销毁表)但能够连接行并对行执行任何操作(行级安全性甚至没有在我的雷达上)。这种一般的特权模型是否与 PostgreSQL 所期望的并不真正同步?如果我必须遍历那个 "grant" 页面上的每个选项来完成这样的事情,我觉得我错过了一些东西——无论是我最初做这件事的动机还是我做这件事的方式去吧。
上下文
我正在尝试构建我的第一个端到端网络应用程序。我已经完成了足够多的通用软件开发和 Web 应用程序开发,现在我正在尝试理解我通常每天认为理所当然的部分。我正在尝试设置 PostgreSQL 服务器,同时牢记 principle of least privilege。
支线任务
我还没有在我刚刚加入开发团队的 Web 应用程序上看到这样做,尽管它们通常很小而且使用不多。这样做真的有什么用吗?有没有人有令人信服的理由来说明为什么要做这样的事情,或者为什么这是一个坏主意或无效的主意?我的假设是,如果我最终以 SQL 注入漏洞告终,这将减轻损害,因为数据库用户的访问权限将受到限制。这是误导了吗?
我发现的有关该主题的精彩文章:
- http://www.ibm.com/developerworks/opensource/library/os-postgresecurity/index.html
- PDF 警告: https://wiki.postgresql.org/images/d/d1/Managing_rights_in_postgresql.pdf
- https://www.digitalocean.com/community/tutorials/how-to-use-roles-and-manage-grant-permissions-in-postgresql-on-a-vps--2
- http://blog.2ndquadrant.com/auditing-users-and-roles-in-postgresql/
我先回答你的“支线任务”问题:
您的担心和担忧是完全正确的,每个设计应用程序的人都应该考虑同样的事情。其他的都是草率和粗心。
为了减轻成功的 SQL 注入攻击可能造成的损害,您绝对应该采用最小特权原则。
设置符合您要求的系统应该非常简单。
我将使用您示例中的对象名称,但我将使用下划线而不是减号。最好在对象名称中仅使用小写字母、下划线和数字,因为这会让您的生活更轻松。
/* create the database */
\c postgres postgres
CREATE DATABASE test_database WITH OWNER app_admin;
\c test_database postgres
/* drop public schema; other, less invasive option is to
REVOKE ALL ON SCHEMA public FROM PUBLIC */
DROP SCHEMA public;
/* create an application schema */
CREATE SCHEMA app AUTHORIZATION app_admin;
/* further operations won't need superuser access */
\c test_database app_admin
/* allow app_user to access, but not create objects in the schema */
GRANT USAGE ON SCHEMA app TO app_user;
/* PUBLIC should not be allowed to execute functions created by app_admin */
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin
REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
/* assuming that app_user should be allowed to do anything
with data in all tables in that schema, allow access for all
objects that app_admin will create there */
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT SELECT, USAGE ON SEQUENCES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT EXECUTE ON FUNCTIONS TO app_user;
但是,如果您采取最不认真的原则,您应该单独授予 table 权限,例如不允许 app_user
到 DELETE
和 UPDATE
中的数据 table,因为用户不需要这样做。
对于 Web 应用程序,我将权限分为三个角色,每个角色都继承其前身。
- 只读 - 用于 SELECT 查询和函数调用
- 插入 - 用于 INSERT 语句
- 更新和删除 - 这些主要用于管理,因为 public 面向前端的应用程序通常不会修改或删除数据
这样,即使某些黑客设法进行 SQL 注入,他也仅限于所使用角色的权限,通常只有 SELECT 或 INSERT。
我的 Web 应用程序通常不需要更具侵入性的权限,例如 CREATE、DROP、TRUNCATE 等,因此我不会向 Web 应用程序授予这些权限。
在极少数情况下,第二个角色需要更新或删除某些内容,我要么授予它对特定 table 的权限,要么将代码放入使用 [=11= 创建的函数中].
/** role_read is read-only with SELECT and EXECUTE */
CREATE ROLE role_read;
/** role_read_add adds INSERT */
CREATE ROLE role_read_add;
/** role_read_add_modify adds UPDATE and DELETE */
CREATE ROLE role_read_add_modify;
GRANT USAGE ON SCHEMA <schema> TO role_read;
/** for existing objects */
GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO role_read;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA <schema> TO role_read;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA <schema> TO role_read;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT SELECT ON TABLES TO role_read;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT SELECT ON SEQUENCES TO role_read;
/** role_read_add inherits from role_read */
GRANT role_read TO role_read_add;
/** for existing objects */
GRANT INSERT ON ALL TABLES IN SCHEMA <schema> TO role_read_add;
GRANT ALL ON ALL SEQUENCES IN SCHEMA <schema> TO role_read;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT INSERT ON TABLES TO role_read_add;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT ALL ON SEQUENCES TO role_read_add;
/** role_read_add_modify inherits from role_read_add */
GRANT role_read_add TO role_read_add_modify;
/** for existing objects */
GRANT UPDATE, DELETE ON ALL TABLES IN SCHEMA <schema>
TO role_read_add_modify;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT UPDATE, DELETE ON TABLES TO role_read_add_modify;
目标
创建三个用户的数据库并限制他们的权限(我只是想出声,所以我的用户分离也有待更正):
- 超级用户 - 此用户允许对数据库进行最初始的配置。创建应用程序数据库,创建其他用户,设置他们的权限。默认
postgres
超级用户为我工作,所以这个就完成了。 - 管理员 - 此用户只能访问在配置期间创建的数据库。管理员可以CRUD所有表中的所有数据,也可以CRUD表等"Superuser for only this database"类型的情况。更新应用程序时,管理员是自动化工具用来处理数据库迁移的用户。
- 应用程序用户 - 此用户最终是支持网络应用程序功能的用户。请注意,这与网页上的用户等无关 - 这是服务器用来 运行 查询、插入和删除数据的用户。我明确地不希望此用户能够修改任何内容的权限,也不希望create/destroy表或索引或任何结构。
我试过的
首先,查看(总体来说非常出色的)PostgreSQL 文档,page on Grant 几乎让我感到不解。在花了几个小时阅读有关 PostgreSQL 角色和特权的内容后,我通常感到困惑。我认为通过更多的工作,我将能够为管理员用户确定我想要的内容,但我仍然停留在 "app user" 上。我已经了解了这么多(命名和密码都只是占位符):
$ psql -U postgres
postgres=# CREATE USER "app-admin" WITH PASSWORD 'password';
CREATE ROLE
postgres=# CREATE USER "app-user" WITH PASSWORD 'password';
CREATE ROLE
postgres=# CREATE DATABASE "test-database" WITH OWNER "app-admin";
CREATE DATABASE
postgres=# \c "test-database"
You are now connected to database "test-database" as user "postgres".
test-database=# DROP SCHEMA "public";
DROP SCHEMA
test-database=# CREATE SCHEMA "app" AUTHORIZATION "app-admin";
CREATE SCHEMA
这就是我不确定的地方。我觉得我想避免的答案是 "revoke everything by default then enumerate all the privileges you'll need at all the different levels on all the different objects"。我试图避免这种情况,因为我直接不知道我在那里需要什么。如果这最终成为答案,那么我只需要蹲下并阅读更多内容,但通常当我开始沿着这样的道路走下去时,我会错过一些东西。
问题
如何限制 app-user
的权限,使他们无法修改任何结构数据(例如,无法添加或销毁表)但能够连接行并对行执行任何操作(行级安全性甚至没有在我的雷达上)。这种一般的特权模型是否与 PostgreSQL 所期望的并不真正同步?如果我必须遍历那个 "grant" 页面上的每个选项来完成这样的事情,我觉得我错过了一些东西——无论是我最初做这件事的动机还是我做这件事的方式去吧。
上下文
我正在尝试构建我的第一个端到端网络应用程序。我已经完成了足够多的通用软件开发和 Web 应用程序开发,现在我正在尝试理解我通常每天认为理所当然的部分。我正在尝试设置 PostgreSQL 服务器,同时牢记 principle of least privilege。
支线任务
我还没有在我刚刚加入开发团队的 Web 应用程序上看到这样做,尽管它们通常很小而且使用不多。这样做真的有什么用吗?有没有人有令人信服的理由来说明为什么要做这样的事情,或者为什么这是一个坏主意或无效的主意?我的假设是,如果我最终以 SQL 注入漏洞告终,这将减轻损害,因为数据库用户的访问权限将受到限制。这是误导了吗?
我发现的有关该主题的精彩文章:
- http://www.ibm.com/developerworks/opensource/library/os-postgresecurity/index.html
- PDF 警告: https://wiki.postgresql.org/images/d/d1/Managing_rights_in_postgresql.pdf
- https://www.digitalocean.com/community/tutorials/how-to-use-roles-and-manage-grant-permissions-in-postgresql-on-a-vps--2
- http://blog.2ndquadrant.com/auditing-users-and-roles-in-postgresql/
我先回答你的“支线任务”问题:
您的担心和担忧是完全正确的,每个设计应用程序的人都应该考虑同样的事情。其他的都是草率和粗心。
为了减轻成功的 SQL 注入攻击可能造成的损害,您绝对应该采用最小特权原则。
设置符合您要求的系统应该非常简单。
我将使用您示例中的对象名称,但我将使用下划线而不是减号。最好在对象名称中仅使用小写字母、下划线和数字,因为这会让您的生活更轻松。
/* create the database */
\c postgres postgres
CREATE DATABASE test_database WITH OWNER app_admin;
\c test_database postgres
/* drop public schema; other, less invasive option is to
REVOKE ALL ON SCHEMA public FROM PUBLIC */
DROP SCHEMA public;
/* create an application schema */
CREATE SCHEMA app AUTHORIZATION app_admin;
/* further operations won't need superuser access */
\c test_database app_admin
/* allow app_user to access, but not create objects in the schema */
GRANT USAGE ON SCHEMA app TO app_user;
/* PUBLIC should not be allowed to execute functions created by app_admin */
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin
REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
/* assuming that app_user should be allowed to do anything
with data in all tables in that schema, allow access for all
objects that app_admin will create there */
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT SELECT, USAGE ON SEQUENCES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_admin IN SCHEMA app
GRANT EXECUTE ON FUNCTIONS TO app_user;
但是,如果您采取最不认真的原则,您应该单独授予 table 权限,例如不允许 app_user
到 DELETE
和 UPDATE
中的数据 table,因为用户不需要这样做。
对于 Web 应用程序,我将权限分为三个角色,每个角色都继承其前身。
- 只读 - 用于 SELECT 查询和函数调用
- 插入 - 用于 INSERT 语句
- 更新和删除 - 这些主要用于管理,因为 public 面向前端的应用程序通常不会修改或删除数据
这样,即使某些黑客设法进行 SQL 注入,他也仅限于所使用角色的权限,通常只有 SELECT 或 INSERT。
我的 Web 应用程序通常不需要更具侵入性的权限,例如 CREATE、DROP、TRUNCATE 等,因此我不会向 Web 应用程序授予这些权限。
在极少数情况下,第二个角色需要更新或删除某些内容,我要么授予它对特定 table 的权限,要么将代码放入使用 [=11= 创建的函数中].
/** role_read is read-only with SELECT and EXECUTE */
CREATE ROLE role_read;
/** role_read_add adds INSERT */
CREATE ROLE role_read_add;
/** role_read_add_modify adds UPDATE and DELETE */
CREATE ROLE role_read_add_modify;
GRANT USAGE ON SCHEMA <schema> TO role_read;
/** for existing objects */
GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO role_read;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA <schema> TO role_read;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA <schema> TO role_read;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT SELECT ON TABLES TO role_read;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT SELECT ON SEQUENCES TO role_read;
/** role_read_add inherits from role_read */
GRANT role_read TO role_read_add;
/** for existing objects */
GRANT INSERT ON ALL TABLES IN SCHEMA <schema> TO role_read_add;
GRANT ALL ON ALL SEQUENCES IN SCHEMA <schema> TO role_read;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT INSERT ON TABLES TO role_read_add;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT ALL ON SEQUENCES TO role_read_add;
/** role_read_add_modify inherits from role_read_add */
GRANT role_read_add TO role_read_add_modify;
/** for existing objects */
GRANT UPDATE, DELETE ON ALL TABLES IN SCHEMA <schema>
TO role_read_add_modify;
/** for future objects */
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema>
GRANT UPDATE, DELETE ON TABLES TO role_read_add_modify;