PostgreSQL学徒

窥探 PGSQL 协议:没有加密时的数据有多裸奔

前言

在排查数据库连接异常、安全链路验证时,抓包分析往往是最“直击本质”的方式。通过 tcpdump + Wireshark,我们不仅能看到每一条 SQL 如何在网络上传输,还能清晰对比开启 SSL 前后协议层面的巨大差异。本文就简单介绍下 PostgreSQL 中常见的协议,以及如何利用 tcpdump 和 wireshark 分析协议。

实战

[postgres@mypg ~]$ sudo tcpdump -i any -w pg_nossl.cap host localhost and port 5432tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes...

同时另外一个窗口,使用非 SSL 进行连接,随便抓个几条 SQL 即可。

Image

wireshark 分析的结果如上所示,我们可以看到 Q、T、D、C、Z 这样的字眼,这正是 PGSQL 的协议消息

•Q:Query (发送 SQL 文本)•T:RowDescription (列定义)•D:DataRow (数据行)•C:CommandComplete (语句完成)•Z:ReadyForQuery (准备接收下一个 SQL)

以 SELECT id, name FROM users 为例,客户端与 PostgreSQL 之间会发生如下消息交互:

Image

1.-> Query("SELECT id, name FROM users"),其中 -> 表示 客户端发送给 PostgreSQL 服务端,其中「Q」表示 Query2.<- 表示 PostgreSQL 服务器返回给客户端,RowDescription 是服务器告诉客户端诸如返回了几个字段,每个字段的名字和数据类型 oid 等,对应 Wireshark 中的 「T」,T = RowDescription3.<- DataRow("123", "Han Solo") 和 <- DataRow("456", "Luke Skywalker") 则表示具体的每一行数据,对应 Wireshark 中的 「D」,D = DataRow4.<- ReadyForQuery('I'),这是 PostgreSQL 返回的最后一个消息,表示:

•当前 SQL 已执行完•后端现在处于某种状态,比如 idle,或者 idle in transaction

Image

所以 'I' 表示服务器现在处于 空闲可接受下一条 SQL 的状态,对应 Wireshark 中的 「Z」,Z = ReadyForQuery。

有了这样的前置知识后,再回过头来分析我们上方 Tcpdump 抓取的结果:

->Q,表明发送了一个查询,对应 51,其次可以看到数据是明文的,“Query:” 字段中直接显示了执行的 SQL

Image

而在 Packet Bytes 区域中,更是能看到 SQL 文本的 ASCII 编码,这也充分说明了,**未启用 SSL 时 PostgreSQL 传输层是完全明文的

73 65 6c 65 63 74 20 2a 20 66 72 6f 6d ... select * from

<-T/D,表明返回了具体数据

Image

最后的 C 和 T,对应 CommandComplete (表示这个 SQL 请求执行结束了) 以及准备接收下一条语句 (ReadyForQuery),虽然理论上收到 CommandComplete 就表明 SQL 已经结束了,但是这个时候可能后端进程还没有准备好执行新的查询请求,比如在释放相应资源等,所以 PG 要求前端收到 ReadyForQuery 了之后才能发出新的查询请求,保证安全。

Image

SSL

前面可以看到,如果没有 SSL 加密,攻击者只要能监听 (sniff) 或篡改 (inject) 客户端与服务器之间的网络,就能看到明文数据甚至伪造请求。

Image

对比未开启 SSL 的明文模式,开启 SSL 后,协议层立即出现明显变化,Wireshark 不再解析为 PGSQL,由于 SSL 会先在传输层建立加密通道,因此 PGSQL 协议的所有 Q / T / D / C / Z 消息都被包裹在 TLS Application Data 中,Wireshark 无法再对其进行协议级解析:

Image

这一次可以看到,Protocal 里面增加了 TLS,其中 Client Hello、Server Hello、Server Key Exchange 等,这正是标准的 TLS 握手阶段。

握手完成后,所有数据均展示为:TLSv1.2 Application Data 和 Encrypted Application Data,其次再去观察数据包的话,你已经无法看到任何 SQL 文本,也无法看到 PGSQL 协议的 Q / T / D / Z 消息。所有数据都已被 TLS 层加密。

Image

小结

PostgreSQL 协议结构简洁清晰,在 Simple Query 模式下非常容易识别,当然像 Extend Protocal,COPY,Replication protocol,以及 14 以后支持的 Query pipelining,都有其各自的消息。

另外 Greenplum 在 PG 的基础上也新增了许多其他消息类型,譬如 新增了 M 消息类型,表明 QD 使用该消息发送查询计划给 QE。各位感兴趣的读者可以自行抓包分析。