YS私有通信协议安全整改方案
1、背景:
YS私有通信是hk研发的一款用于探测或设置hk设备的设备网络搜索软件,其基于hk的私有多播或广播协议实现。由于其自身拥有和hk同样长久的历史,早期在设计时未考虑到安全性因素,导致该协议存在被攻击的风险。
2、威胁分析:
2.1、攻击手段:
(1)、嗅探:
由于YS私有通信协议是基于明文传输的,当用户使用支持YS私有通信协议的客户端和设备通信时,处于同一个局域网内的攻击者可以嗅探到两者之间的通信数据,导致信息泄漏。常见的敏感信息包括:口令、设备验证码和设备版本信息等。一旦攻击者获取到这些信息,即可进一步进行攻击利用,比如:登录设备植入后门等。
(2)、篡改:
意指攻击者劫持明文通信包,将参数篡改后再放行发送给设备,由于YS私有通信协议本身不存在校验信令数据完整性的机制,所以会当正常请求进行处理,导致攻击成功。
(3)、伪造:
意指攻击者捕获明文通信包后进行保存,后续再对报文进行重放。对于“写”操作来说,此类攻击危害比较大,比如:设置设备参数。如果攻击者不停对设备进行重放请求,可能导致设备拒绝服务。由于YS私有通信协议本身不存在对重放的抵御设计,所以会不停处理来自外界的请求,不管该请求是不是真实的用户发起的。
2.2、攻击示意图 :
3、解决方案:
3.1、方案描述:
以上3方面牵涉到数据的保密性、完整性问题,通常来说,可以通过使用SSL协议来解决,但是YS私有通信协议本身不是应用层而是基于网络层的协议,故直接使用SSL并不适合。但就通信安全层面来讲,加密和数字签名是解决以上问题的常用方案。
(1)、加密:
加密分为对称加密和非对称加密两种算法,由于非对称加密算法对性能损耗较大,通常只用于小数量的数据报文交换,比如:SSL中交换对称加密密钥的场景;对称加密有具有良好的性能,适用于进行大量数据的加密通信。现今比较典型的对称加密算法有AES和3DES等,为适应当代主流,本文推荐使用AES128或AES256。对称加密密钥可由用户输入的设备验证码转换而来,由于设备本身拥有验证码,同样可以换算出对称加密密钥,因此,可以对接收到的密文进行解密获取明文。
(2)、消息摘要:
简单地说,消息摘要就是对数据报文所作的密码变换,这种变换允许接收者来确认数据的来源和完整性,此外,如果在进行摘要时加入时间戳或一次性随机token,可以有效防止数据被伪造重放。本文建议使用HMAC-SHA1算法来实现对发送数据的摘要,该算法要求通信双方必须预先协商一个共同的密钥作为摘要和验摘的机制,这个密钥可以通过设备验证码转换而来,和加密类似,摘要时,由用户输入设备验证码并转换成摘要密钥,而设备本身就拥有设备验证码,故可以进行验摘,关于HMA-SHA1的详细介绍和java实现,请参考附录。
注意:加密是一个可选项,当信令体存在敏感信息时才需要进行加密,而摘要是建议在每一个信令都实施的。
3.2、流程图:
流程图展示了详细的过程和处理步骤:
3.3、样例:
4、方案对比:
| 先前方案 | 本次方案 |
优点 | 1、实现简单,双方能够通信即可。 | 1、加入了数据签名和加密机制,弥补了先前方案的所有欠缺。 |
缺点 | 1、未做数据签名校验,无法保证数据完整性。 2、未对敏感数据进行加密,可能导致信息泄漏。 | 1、实现稍微复杂,需要加入新的参数和数据签名校验机制。 2、需要考虑前后版本兼容性问题。 |
5、附录:
HMAC-SHA1的JAVA实现代码如下:
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HMACSHA1 {
private static final String MAC_NAME = "HmacSHA1";
private static final String ENCODING = "UTF-8";
public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception
{
byte[] data=encryptKey.getBytes(ENCODING);
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
//生成一个指定 Mac 算法 的 Mac 对象
Mac mac = Mac.getInstance(MAC_NAME);
//用给定密钥初始化 Mac 对象
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
//完成 Mac 操作
return mac.doFinal(text);
}
}