您查看的文章来源于http://www.oklinux.cn
尽管可能无法访问表,但是用户仍然可以收集有关表的信息。
清单 4 展示了用户帐户 user1 获取了一组用户帐户及其各自的属性。普通用户自己无法访问密码。
清单 4. 获取用户帐户的属性
postgres=> select * from pg_user; usename | usesysid | usecreatedb | usesuper | usecatupd | passwd | valuntil | useconfig---------- ---------- ------------- ---------- ----------- ---------- ----------postgres | 10 | t | t | t | ******** | | user1 | 18770 | f | f | f | ******** | |(2 rows)
所有用户默认情况下都能够获得集群的定义和模式。
清单 5 展示了一个可以获得有关集群完整定义模式的信息的脚本,方法就是查询系统目录。系统目录可以被超级用户修改或解密,从而减轻了这一威胁。
清单 5. 提取集群范围内的定义
#!/bin/bashpsql mydatabase << _eof_set search_path=public,information_schema,pg_catalog,pg_toast;\t\o list.txtSELECT n.nspname||'.'||c.relname as "Table Name"FROM pg_catalog.pg_class c JOIN pg_catalog.pg_roles r ON r.oid = c.relowner LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespaceWHERE c.relkind IN ('r','')ORDER BY 1;\q_eof_for i in $( cat list.txt ); do psql -c "\d $i"done
创建和访问由用户定义的函数
函数也分为可信的或不可信的。可信的 过程语言在数据库上下文内执行指令,比如创建表、索引,添加或移除数据,等等。不可信的 过程语言(除了可信的特性外)也能够影响真实的世界,比如列出目录的内容,创建或删除文件,调用系统进程,甚至是创建与其他主机的套接字连接。
清单 6. 向数据库添加过程语言并恢复对 user1 的访问
postgres=# create language plpgsql;CREATE LANGUAGEpostgres=# create language plperlu;CREATE LANGUAGEpostgres=# create language plperl;CREATE LANGUAGEpostgres=> SET SESSION AUTHORIZATION postgres;SETpostgres=# GRANT USAGE ON SCHEMA PUBLIC TO user1;GRANT
清单 7. 可信 vs. 不可信过程语言
postgres=# select lanname as language, lanpltrusted as trusted from pg_language; language | trusted---------- --------- internal | f c | f sql | t plperlu | f plperl | t(5 rows)
与表不同的是,普通用户帐户在调用某些用户的函数时不需要特殊权限,即使是由超级用户创建的函数也是如此。
清单 8. 调用超级用户的函数
postgres=# SET SESSION AUTHORIZATION postgres;SETpostgres=# CREATE OR REPLACE FUNCTION public.f1 (postgres(# OUT x textpostgres(# ) ASpostgres-# $body$postgres$# select 'hello from f1'::text;postgres$# $body$postgres-# LANGUAGE SQL;CREATE FUNCTIONpostgres=# SET SESSION AUTHORIZATION user1;SETpostgres=>postgres=> SELECT * FROM f1; x----------------- hello from f1(1 row)
下面清单 9 中的函数由超级用户通过 plperlu 创建。它返回目录的内容;user1 可以调用这个函数。一个普通用户可以同时调用可信函数和不可信函数。要应对这种威胁,最好的方法是通过撤销权限来拒绝对函数的访问。
清单 9. 函数被未授权的用户利用
postgres=> SET SESSION AUTHORIZATION postgres;SETpostgres=# CREATE OR REPLACE FUNCTION public.f2 (postgres(# OUT x textpostgres(# ) ASpostgres-# $body$postgres$# # output the root directory contents into standard outputpostgres$# # notice the use of the single back tickspostgres$# $a = `ls -l / 2>/dev/null`;postgres$# $message = "\nHere is the directory listing\n".$a;postgres$# return $message;postgres$# $body$postgres-# LANGUAGE PLPERLU;CREATE FUNCTIONpostgres=# SET SESSION AUTHORIZATION user1;SETpostgres=> SELECT * FROM f2; x---------------------------------------------------------------------------- Here is the directory listing total 120 drwxr-xr-x 2 root root 4096 Aug 29 07:03 bin drwxr-xr-x 3 root root 4096 Oct 11 05:17 boot drwxr-xr-x 3 root root 4096 Nov 26 2006 build lrwxrwxrwx 1 root root 11 Aug 22 2006 cdrom -> media/cdrom drwxr-xr-x 15 root root 14960 Oct 12 07:35 dev drwxr-xr-x 118 root root 8192 Oct 12 07:36 etc(1 row)
清单 10. 针对 user1 和组 PUBLIC 提供保护
postgres=# SET SESSION AUTHORIZATION postgres;SETpostgres=# REVOKE ALL ON FUNCTION f2 FROM user1, GROUP PUBLIC;REVOKEpostgres=# SET SESSION AUTHORIZATION user1;SETpostgres=> SELECT * FROM f2;ERROR: permission denied for function f2postgres=>
清单 11 展示了信息收集。
清单 11. 获取函数的源代码
postgres=> SET SESSION AUTHORIZATION user1;SETpostgres=> select prosrc as "function f3" from pg_proc where proname='f3'; function f3---------------# output the root directory contents into standard output# notice the use of the single back ticks $a = `ls -l / 2>/dev/null`; $message = "\nHere is the directory listing\n".$a; return $message;(1 row)