概述
SSH协议设计的⽬的是保证在不安全⽹络上进⾏安全传输。通过SSH协议原理可知SSH数据包在认证阶段之前是明⽂传输,从认证阶段开始,则采⽤握⼿阶段协商出的会话密钥,结合协商出的对称加密算法,对后续传输的内容进⾏对称加密传送,因此认证阶段开始的数据包都是加密传送的。如果需要解密SSH流量,获取SSH传输的命令,则需要获取会话密钥等关键解密因⼦。由于会话密钥是客户端与服务器通过DH密钥交换算法各⾃在本地协商⽣成,会话密钥并没有在⽹络上进⾏传输,因此直接通过中间⼈攻击⽅式在流量传输过程中截获SSH流量进⾏解密是不现实的,必须得获取会话密钥等关键解密因⼦。基于【技术分享 | 有趣的OpenSSH会话解密】这篇文章的分享,作者提供了开源工具,本文复现利用该开源工具从运⾏的主机内存中恢复出会话密钥等解密因子,并利用解密因子对SSH加密流量进行解密的实验过程。
获取会话密钥
OpenSSH是实现SSH协议的客户端和服务端程序,SSH协议在连接建⽴过程中,OpenSSH会启动相应的进程,进程名⼀般为"ssh"(ssh客户端进程名)或者“sshd”(ssh服务端进程名)。协商⽣成的会话密钥(随机字符串)等解密因⼦会存放在ssh进程的内存中。通过抓取终端上ssh程序的整个内存地址空间,便能找到shenc结构体,这是ssh程序的基本加密结构,⾥⾯存放了相关解密因⼦。包括:对称加密算法名称、会话密钥及密钥⻓度、IV(初始化向量,对称加密过程会⽤到的因⼦)以及IV⻓度、块⼤⼩等。
会话密钥提取⼯具
-
OpenSSH-Session-Key-Recovery(运⾏环境:python3)(linux系统会话密钥获取脚本)
实验环境
ssh客户端:10.211.55.5
ssh服务器:10.211.55.3
实验过程
1. 客户端通过账号密码方式登录ssh服务器。
ssh parallels@10.211.55.3
2. 同时在客户端运⾏会话密钥提取脚本,获取解密因⼦。
python3.9 keys.py
3. 获取的其中一个解密因子如下。
{
"pid":187232,
"proc_name":"ssh",
"sshenc_addr":187651422272880,
"cipher_name":"aes256-gcm@openssh.com",
"key":"6dbfe8ed48cc57f2a6d779345b8cc7404e9708bec0ee6f9b31ba231f2739d099",
"iv":"c28f21d98bf3352005b7b5aa",
"sshenc":{
"name":187651422246656,
"cipher":187650529554520,
"enabled":0,
"key_len":32,
"iv_len":12,
"block_size":16,
"key":187651422274416,
"iv":187651422275376
},
"network_connections":[
{
"family":2,
"fd":3,
"laddr":[
"10.211.55.5",
33356
],
"raddr":[
"10.211.55.3",
22
],
"status":"ESTABLISHED",
"type":1
}
]
}
-
pid:ssh客户端的进程号为187232
-
sshenc_addr:sshenc结构体内存地址为187651422272880
-
cipher_name:对称加密算法为aes256-gcm@openssh.com
-
key:会话密钥
-
iv:初始化向量
-
sshenc:sshenc结构体
-
network_connections:tcp连接情况,10.211.55.5的33356端口与10.211.55.3的22端口建立了TCP连接。
SSH流量解密
恢复出会话密钥后,需要解密通信流量。由于SSH加密流量采用对称加密算法,通过会话密钥加密,加密后会计算MAC,进行hash校验,传输的内容会采用压缩算法进行压缩传输。因此需要知道采用的对称加密算法、MAC算法、压缩算法等,这些算法都是由客户端和服务端进行算法协商得到的。因此在解密流量时要能还原算法协商过程,利用算法协商原则还原出解密过程所需算法,并根据已有的密钥因子,解密通信流量,还原出从SSH认证阶段开始加密的内容。
流量解密工具
-
OpenSSH Network Parser(运行环境:python version >=2.7,<3,因为pynids 与 py3 不兼容)
实验环境
ssh客户端:10.211.55.5
ssh服务器:10.211.55.3
实验过程
1. 客户端通过账号密码登录ssh服务器,并输入以下ssh命令传输到服务器。
ssh parallels@10.211.55.3
ls
whoami
pwd
ping www.baidu.com
2. 在客户端利用wireshark抓取ssh流量包,另存为test1_ssh.pcap。
3. 利用之前抓取的会话密钥等解密因子,构造密钥输入文件test1_keys.json。
{
"task_name":"ssh",
"sshenc_addr":187651422272880,
"cipher_name":"aes256-gcm@openssh.com",
"key":"6dbfe8ed48cc57f2a6d779345b8cc7404e9708bec0ee6f9b31ba231f2739d099",
"iv":"c28f21d98bf3352005b7b5aa"
}
{
"task_name":"ssh",
"sshenc_addr":187651422273184,
"cipher_name":"aes256-gcm@openssh.com",
"key":"28c6b072d0188db1ac0d3059ba64b9d933e5123c23fc26e30374efdb97c36ef0",
"iv":"4aa92c3a1929daa59fc53ed0"
}
4. 运行流量解密工具,进行解密,获取SSH明文命令。
python2.7 -m openssh_network_parser.tools.network_parser -p example/test1_ssh.pcap --proto=ssh --popt keyfile=example/test1_keys.json -o /tmp/ssh/ -s
-
-p:载入pcap流量包路径
-
--proto:解析协议
-
--popt:载入密钥文件
-
-o :运行过程中一些统计信息输出路径
-
-s:打印到标准输出而不是日志文件
5. 解密结果如下,可以看到客户端所有传输的命令及服务器响应的结果都被解密还原出来,登录认证的密码也被还原出来。