如果你使用Hasura,请检查!应检查的安全措施设定清单
这篇文章是GraphQL Advent Calendar 2021(GraphQL日历2021年版)的第13天的文章。
首先
有一个名为Hasura的GraphQL服务器,它可以自动从DB表创建GraphQL API。
如果你想知道”Hasura是什么?”,希望你能阅读以下的文章。
Hasura 提供了许多设置来保护 API 免受各种攻击。 在本文中,我们将总结在使用 Hasura 运行 GraphQL 服务器时应配置的安全设置,并将其整理为一个检查清单。 大部分内容已经在文档中写明了,但由于缺乏日语信息并且在实际运行中发现了一些文档中没有提到的内容,所以我们在本文中也包含了这些内容。 我们希望使用 Hasura 的用户能再次检查本文的内容,作为安全检查的参考。
在撰写时的Hasura版本
翻译为中文的意思是:本地部署和云端版本通用。
在这里,我们将谈论Hasura提供的Cloud版和使用Heroku进行部署,或使用Docker·Kubernetes自行托管的情况下,共同需要考虑的检查点。
✅ Hasura管理者密钥是否已设置?
可以防止的事情
・对GraphQL端点的非法请求。
在任何情况下都不能选择不设置 Hasura 管理员密钥。
如果不进行这个设置,只要知道GraphQL服务器的端点,任何人都可以随心所欲地操作Hasura实例。无论如何,首先要设置Hasura Admin Secret。顺便提一句,云版本默认已经设置好了。
为了进行设置,请设置环境变量名为HASURA_GRAPHQL_ADMIN_SECRET。请确保此值从环境变量中获取,并确保不可从Git存储库中查看。
✅ 对于资源的CRUD操作,是否分配了适当的角色?
可以避免的事情 de
举个例子,我们来考虑一个具有认证功能的应用程序。数据库中有一个名为Articles的表,用于管理与已认证用户相关联的文章。如果忘记进行权限设置,客户端可以篡改任何其他用户的文章信息。
为了避免这种情况的发生,需要设定一条规则,即只有具有用户角色且身份信息ID与Articles表的user_id匹配的情况下,才允许进行更新操作。
为了预防个人信息泄露的风险,就像发现GraphQL采用服务可以获取任意列的弱点一样,应该确认所有表的CRUD操作是否被授予适当的权限。
权限设置可以通过[数据]->[目标表]->[权限]来进行。
在这里,给数据库表授予权限有几种方法可供选择。
✅ 没有任何检查
如果想要给用户角色授予对Articles表进行SELECT操作的权限,可以设置CRUD操作的授权。
例:操作不包含需要从其他地方保密的记录的表,如主表等。
✅ 设定自定义检查
只有当用户角色为User且x-hasura-user-id与Article表的user_id相匹配时才允许进行UPDATE操作,就像之前所说的那样,您可以自定义规则。
可以进行设置的事项 de
共通的含义通常指的是人们之间共同的特点、经验或观点。
- テーブルカラムへの操作権限の付与(Column Permissions)
在这里插入
列のデフォルト値を設定すること
您可以像为数据库设置默认值一样,在每个角色的INSERT操作中设置默认值。通过使用”from session variable”,您可以从请求头中的会话变量”x-hasura-**”中读取值,并将其设置为INSERT时的默认值。
仅限后台的客户访问限制。
只有在将backend仅限制为INSERT mutation且满足以下条件时,才能访问设置的角色。
请将以下内容用中文进行本地化翻译,只需一种选择:
在请求头中
-
- 「x-hasura-use-backend-only-permissions」がtrue
- 「x-hasura-admin-secret」が設定されている場合
查询
限制可获取的行数
赋予集计查询权限
您可以设置是否将聚合模式对角色进行公开。
在这里,聚合模式是指一个方便的集合解析器的集合,该解析器返回总和(sum)或平均值(avg)等聚合操作,与基本的CRUD解析器一样,还会自动生成用于聚合的模式。
默认为false。
更新
更新前的条件检查
在更新之前,可以进行配置,只允许与“id”匹配的请求进行UPDATE。
更新后的条件检查
在更新后,可以进行以下设置:”只允许id与x-hasura-user-id匹配的请求进行更新操作”。
列预设值的设定(默认值)
您可以像INSERT的Column presets一样设置默认值。设置方法也是相同的。
删除
没有特别的
关于 (补充) Action (远程模式) 的权限
Action・Remote Schema只能设置允许执行该操作的角色。因此,无法进行详细的权限设置,例如”只允许在头信息的ID和输入的ID相同时执行”。
因此,在连接到API服务器的请求体`session_variables`字段中,含有`x-hasura-role`和`x-hasura-user-id`的值,需要在连接的GraphQL服务器和RESTful服务器上执行详细的限制。您需要使用这些值来编写授权处理。
{
"session_variables":
{
"x-hasura-role": "user",
"x-hasura-user-id": "635efa22-d373-3dc8-285f-490d0b80e0da",
}
}
✅ Hasura GraphQL的CORS域名是否已设置?
可以预防的事情 de
请确认是否流出了包含个人信息的日志记录?
可以避免的事情
通过设置环境变量HASURA_GRAPHQL_ENABLED_LOG_TYPES或启动选项–enabled-log-types,可以控制Hasura服务器(如Heroku或Docker容器日志)的日志输出。
如果您在设置日志类型时选择了”query-log”,请务必注意。此日志类型会将来自客户端的请求中包含的所有GraphQL查询信息记录在日志中。
换句话说,如果执行了带有包含可以识别个人信息的参数的输入/输出查询或变更操作,所有个人信息都将被记录在日志中。
除非有特殊情况,我们应该避免将日志类型设为查询日志,因为一旦服务器遭到入侵,或是与内部监视工具(如NewRelic)有关联,如果工具出现问题,就会导致数据泄漏风险。
在Hasura Cloud中的情况下
以下是使用 Hasura Cloud 时需要检查的要点。
✅ API限制已经设置了吗?
可以防止的事情
・由于操作错误、查询设计错误导致服务器可用性受到侵害,服务器宕机
✅ 深度限制
您可以在一次请求中指定查询的嵌套深度。
在GraphQL查询中,可以通过递归嵌套将”Users”表中的”Articles”子表关联起来,再从中获取”Users”的数据…
如果没有指定嵌套深度,则可能受到恶意查询或查询设计错误的影响,给数据库服务器带来负载,并可能导致最糟糕的情况下宕机。
为了防止嵌套过深,我们应该对其进行限制。
✅ 节点限制
您可以在一次请求中指定要获取的节点数量。
有关节点的详细说明,请参阅https://docs.github.com/ja/graphql/guides/introduction-to-graphql#node 和相关文章。
✅ 请求速率限制(每分钟请求数量)
您可以限制每个单位时间(分钟)内来自同一客户端的请求数。
-
- IP Address
-
- X-hasura-user-id
- その他自分で設定したx-hasura-**のセッション変数
通过组合这些条件,您可以进行更详细的设置。
✅ “允许列表是否已设置?”
可以避免的事情 de
无论是否进行设置,我认为都可以。您可以使用“Allow list”功能来限制可以执行的GraphQL查询。
您可以从之前执行的查询中选择并指定要限制的查询。
如果有不想被攻击的查询,请进行相应的设置。
默认安装的安全措施
✅ SQL注入
由于Hasura生成的SQL是通过libpq的execParams或execPrepared来执行的,因此会遵循Postgres的转义规则进行转义。因此,即使有恶意的SQL嵌入在查询/突变中,也不会被执行。
请参考GitHub上的链接:https://github.com/hasura/graphql-engine/issues/5251。
总结
至此,我们介绍了使用Hasura时需要检查的安全措施设置清单。
由于Hasura相对较新,所以未来将会进一步增强其功能(个人希望增加继承角色的自由度)。
如果Hasura的版本更新公告发布了,请务必检查其中与安全性变更和功能添加相关的部分。