剖析 PostgreSQL 的 CVE-2013-1899 安全漏洞
上个周,Postgresql团队对它旗下的著名开源RDBMS发布了一个安全方面的更新,一切看起来都像往常一样……
但是这条更新却引起了人们的极大关注,主要是因为在补丁发布前一周,Postgres开发者在pgsql-hackers邮件列表( http://www.postgresql.org/message-id/[email protected])中发布了一个令人震惊的消息,说即将发布的新版本中包含了修复某个安全问题的一些补丁,但这些补丁却又引进了极其严重的安全漏洞以至于在更新包出来之前要临时关闭大众对公共Git库的访问权限。
我不知道你是怎么想的,但是就从这个极其机密的安全漏洞的严重程度来看,竟然到了让一个著名的开源项目采取临时闭源的方式来防止细节泄露的地步,就这一点不免让我们感到一点小小的兴奋。
之后到了星期四,补丁出来了,代号 CVE-2013-1899。打眼一看好像是DoS漏洞,因为其至少具备了remote,unauthenticated的特点。并且在某些非常特定(经过认证的用户的用户名与数据库名相同)的情况下还可导致本地提权。
因此我们接下来的目标就是看看能否将这个DoS漏洞提升至RCE(远程代码执行)攻击或者至少是尽可能地接近这个目标……
层层深入
我们来分析一下这个漏洞。首先,这个漏洞的独特之处就是当一个客户端以指定的数据库进行登录时,若在数据库名前加 '-'(连字符),这会导致postgre服务器将数据库名解析为命令行的选项(flag)并传递给处理当前连接的服务器实例(所有这些解析、执行操作都是在身份验证之前进行的)。换句话说,任何攻击者在未经过身份验证的情况下都可以对处理连接会话的postgre服务器传入任意的命令行选项。
在Posgres的使用者中,大家认为最危险的参数便是“ -r”选项,可以将服务器的所有输出写入到指定的文件中。通过使用这个选项,攻击者可以将运行posgres的用户的那些具有可写权限的文件(像配置文件或数据库文件)作为参数传入,之后数据库输出的垃圾信息将会破坏这些文件从而导致拒绝服务攻击。
除了"-r"选项其他的命令行参数还是很少用到的。但是还有一个也是比较有用的,那就是"-c"选项。它允许我们设定一个更长的选项列表来作为运行时参数,详情请看 “Chapter 18″ of the PostgreSQL manual(实际上,大多数其他的命令行参数都是运行时参数的简化版)。
首先看一下几个有趣的选项:
- shared_preload_libraries – 指定在服务器启动时预先载入的一个或多个共享库
- archive_command – 指定用于归档完整WAL(Write-Ahead Logging)文件字节码的Shell命令
- log_line_prefix – 将指定的字符串作为每行日志的前缀并以printf风格输出
- dynamic_library_path – 当动态模块未在LOAD或CREAT FUNCTION命令中指定时,用此选项指定
- local_preload_libraries – 指定在连接开始时预载入的一个或多个共享库
进一步分析:
- shared_preload_libraries – 攻击者可以用来指定预载入具有钩子函数的库文件,但是需要对文件系统有写权限
- archive_command – 指定当write-ahead log归档时会调用的shell命令。不幸的是这个命令还需要同时设置其他几个参数才能触发运行,在经过进一步的研究后,我们只能传入一个命令行选项。
- log_line_prefix – 起初我以为可以将此选项与"-r"选项组合使用,让我们在每行日志前加入一些有用的信息,从而将某些信息写入到任意的文件中。不幸的是,这个选项一次也只能传一个参数
- dynamic_library_path 或 local_preload_libraries – 类似于shared_preload_libraries,但限制更多。