我正在创建一个允许用户构造复杂SELECT语句的应用程序。生成的SQL是不可信的,完全是任意的。
我需要一种在相对安全的情况下执行不受信任的SQL的方法。我的计划是创建一个只对相关模式和表具有SELECT权限的数据库用户。不受信任的SQL将作为该用户执行。
有什么可能出错?:)
如果我们假设postgres本身没有关键的漏洞,那么用户可能会进行一系列交叉连接并使数据库过载。这可以通过会话超时来缓解。
我觉得有很多可能出错的地方,但我很难列出一个清单。
编辑:
根据到目前为止的评论/回答,我应该注意到,在任何特定时间使用该工具的人数都将非常接近0。
Onerload可能是复杂查询或过多简单查询的结果。
在
postgresql.conf
中设置statement_timeout
可以排除过于复杂的查询也可以避免接收大量的简单查询。首先,您可以设置每个用户的并行连接限制(
alter user
和CONNECTION LIMIT
)。如果你在用户和postgresql之间有一些接口程序,你可以额外地(1)在每次查询完成后添加一些额外的等待,(2)引入CAPTCHA以避免自动DOS攻击
ADDITION:PostgreSQL公共系统函数提供了许多可能的攻击向量。它们可以像select pg_advisory_lock(1)
一样被调用,每个用户都有权调用它们。因此,您应该限制对它们的访问。一个好的选择是创建所有"可调用单词"的白名单,或者更准确地说,创建可以与后面的(
一起使用的标识符。并排除所有包含标识符不在白名单中的类调用构造identifier (
的查询。
除了让用户只选择并撤销对函数的权限之外,还会想到的事情:
只读事务。当事务由
BEGIN READ ONLY
或SET TRANSACTION READ ONLY
作为其第一条指令启动时,它不能写入任何内容,这与用户权限无关。在客户端,如果您想将其限制为一个
SELECT
,最好使用SQL提交函数,该函数不接受捆绑在一个查询中的多个查询。例如,libpq
API的swiss-knifePQexec
方法确实接受这样的查询,在其上构建的每个驱动程序函数(如PHP的pg_query
)也接受这种查询。http://sqlfiddle.com/是一种专门运行任意SQL语句的服务,这可能被视为一种概念证明,它是可行的,而不会整天被黑客入侵或DDos。
问题是,我不确定sql本身在会话超时后是否仍会在后台运行(通过谷歌也找不到太多证据,我自己也没有尝试过)。如果你只限于选择访问,我认为这可能是最糟糕的情况。真正的问题是,如果有一百个用户试图进行复杂的交叉连接,会发生什么?会话超时是否删除查询,这将给数据库带来真正的沉重负载(很容易就足以完全关闭数据库)
用特制的查询在主服务器上保护自己免受DoS攻击的唯一方法(从我的角度来看)是在Postgres数据库上设置一个只读副本和一个特殊的受限用户。这样,主Postgres服务器就不会受到副本查询的影响。
此外,当主数据库由于某种原因出现故障时,您将获得热备用/连续复制数据库。