天天看点

PostgreSQL PL/Perl 钩子安全性分析

plperl 是postgresql支持的函数语言之一。

在使用plperl时,可以使用plperl提供的钩子功能,满足一些特殊场景的需求。

钩子分2种,一种是加载plperl.so库时的钩子,一种是加载perl语言解释器时的钩子。

钩子的使用有安全问题吗?

相关参数

plperl.on_init (string)

当设置了 shared_preload_libraries = 'plperl' 预加载时,plperl.on_init 只会被调用一次。

当没有设置 shared_preload_libraries = 'plperl' 预加载时,plperl.on_init 会在每个会话第一次装载plperl.so时被调用。

代码

src/pl/plperl/plperl.c

plperl.on_init (string) 只能设置在配置文件中,或者在启动postgres时命令行指定。

对只开放普通数据库用户的环境来说没有安全问题。

plperl 函数语言钩子,当在会话中第一次加载perl语言解释器时,perl 函数解释器将自动调用

或设置的串。

具体调用哪个,和函数语言有关,plperl则调用on_plperl_init, plperlu则调用on_plperlu_init。

需要注意的是,这两个函数可以在参数中设置,也能在会话中设置,但是在会话中设置的话,如果perl解释器已经加载了,不会触发修改后的值。

另外需要注意on_plperl_init是在plperl安全化后执行的,所以即使在这里配置了不安全的属性,也不怕,因为会直接报错。(与调研plperl的用户权限无关,plperl是不允许执行不安全操作的,例如调研system接口)

这两个参数的解释 :

<a href="https://www.postgresql.org/docs/9.5/static/plperl-under-the-hood.html">https://www.postgresql.org/docs/9.5/static/plperl-under-the-hood.html</a>

plperl.on_plperl_init (string)

plperl.on_plperlu_init (string)

代码如下

只有超级用户能设置这两个值,普通用户在会话中设置plperl.on_plperl_init时,触发设置则报错。

postgresql.conf 参数

测试

使用 stat touch /home/digoal/t123 查看时间戳的变化

判断是否触发。

plperl是trust语言,在创建它的函数时,会监测安全性,例如过滤一些os操作,等。普通用户和超级用户都可以创建plperl语言的函数。

plperlu则是untruste语言,允许任何操作,只有超级用户能创建plperlu的函数。

如果已经设置了plperl.on_plperl_init是一个不安全的值,则新建plperl函数会报错。

调用时,如果触发了不安全的plperl.on_plperl_init,也会报错。

postgresql将函数语言分为两类,一类是trust的另一类是untrust的。

trust的语言,不允许执行有破坏性的操作,例如系统命令,文件访问等。普通用户可以创建trust语言的函数。

untrust的语言,允许执行任何操作,只有superuser能创建untrust语言的函数。

如果只开放普通数据库用户出去,是没有安全风险的。

postgresql 为 plperl或plperlu语言设置了两种钩子,分别允许在加载libperl.so时被触发(在_pg_init(void)里面实现);

或者在加载perl解释器时被触发,其中加载解释器时又分为两种,plperl和perlu的设置。

用户利用钩子,可以实现一些特殊场景的应用。

数据库普通用户无法修改钩子参数

即使设置了危险的plperl.on_plperl_init参数,因为这个参数的内容是在plperl函数风险评估后执行的,所以如果有风险也不允许执行,不存在安全风险。

综上,postgresql对语言的管理是非常安全的,只要不随意把超级用户放出去,不随意使用untrust语言创建不安全的函数。

继续阅读