工作准备

•一台SQLSERVER 2005/SQLSERVER 2008服务

•SQLSERVER jdbc驱动程序

•Java开发环境eclipse + jdk1.8

•java反编译工具JD-Core

反编译JDBC分析SQLSERVER客户端与服务器通信原理

SQLServerConnection.class

1、经过反编译分析SQLServerConnection.class文件我们可以看到登录时所执行的算法,代码如下图所示:

sql server 实现 rsa 加密 sqlserver密码加密_客户端

由此可见sqlserver在用户名密码传输过程中使用了SSL加密,从上图中我们可以看到在启用SSL加密前执行了Prelogin(String param,int param2)函数,该函数算法大致如下图所示:

sql server 实现 rsa 加密 sqlserver密码加密_java_02

sql server 实现 rsa 加密 sqlserver密码加密_数据库_03

2、经过一些列分析得知,在启用SSL加密前客户端向服务器发送了客户端驱动信息之后立即读取服务返回的版本内容以作判断当前所使用的驱动是否支持。

3、在反编译分析代码过程中可以看到用户名密码加密算法分别所示:

sql server 实现 rsa 加密 sqlserver密码加密_SSL_04

由此可以通过逆向推算得出用户名密码解密算法如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_客户端_05

sql server 实现 rsa 加密 sqlserver密码加密_SSL_06

TDSChannel.class

1、经过反编译分析SQLServerConnection.class 文件得知通过调用TDSChannel.class 中的函数enableSSL(String param,int param2),那么经过反编译TDSChannel.class文件分析得知该函数主要代码段如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_数据库_07

2、由此可见SQLSERVER客户端仅在传输用户名密码时启用了ssl加密,登录认证前后数据传输均采取明文传输。

SSL通道拦截设计

1、SQLSERVER原始SSL通信如下:

sql server 实现 rsa 加密 sqlserver密码加密_客户端_08

2、拦截后通信如下:

sql server 实现 rsa 加密 sqlserver密码加密_java_09

程序设计

1、认证服务伪代码如下:

sql server 实现 rsa 加密 sqlserver密码加密_java_10

2、读取客户端驱动版本等信息并模拟sqlserver返回的版本信息,伪代码如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_客户端_11

3、完成以上两步操作后立即开启SSL通道等待客户端开启SSL并握手,伪代码如下:

sql server 实现 rsa 加密 sqlserver密码加密_SSL_12

4、若SSL握手成功则接收客户端发送的用户名密码信息,并立即连接目标服务伪代码如下:

sql server 实现 rsa 加密 sqlserver密码加密_运维_13

5、若连接成功则模拟客户端发送驱动版本信息并读取目标服务返回的信息反馈给真正的用户,紧接着开始SSL握手,若握手成功则立即发送真实的用户名密码,伪代码如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_SSL_14

SSL通道用户名密码替换以及实时监控

1、使用SQLSERVER标准客户端工具填写堡垒主机地址和端口号用户名密码以及目标主机信息,如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_SSL_15

2、点击“连接”登录实现转发连接功能,登录成功如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_SSL_16

3、通过实时监控窗口查看SQLSERVER客户端执行的命令,如下图所示:

sql server 实现 rsa 加密 sqlserver密码加密_数据库_17

4、新建查询执行命令,如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_运维_18

5、通过实时监控查看执行的命令信息,如下所示:

sql server 实现 rsa 加密 sqlserver密码加密_运维_19

到此为止已完成所有工作。