Security:哈希长度扩展攻击
典型的hash算法,hash = md5((secret + data)),在服务器会校验hash的值。在不知道secret的情况下,如果知道secret的长度,可以算出一个吻合的hash值。举例如下:
- 服务器的secret = "secret", 加密算法为md5((secret + data))
- 服务器算好后,把data和hash值一起给客户端
- 服务器接收到请求后,通过再次计算比对,如果匹配证明是合法的请求
比如data = "data",正常情况下,可以算出一对值:
secret = "akSK06mn91c2MxARSrOBTqdmhVCMkkoZ"
data = "riguz"
token = secret + data = "akSK06mn91c2MxARSrOBTqdmhVCMkkoZriguz";
md5 = md5(token) = "38a67feac3cf91cf3e68467ae803a21b"
现在,利用hash_extender可以计算出一对值:
./hash_extender --data riguz --secret 32 --append helloworld --signature 38a67feac3cf91cf3e68467ae803a21b --out-data-format html --table md4 dd0c44d807b1c3ca0365b1e656fd1d39 riguz%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%28%01%00%00%00%00%00%00helloworld md5 1800bc243a00db801833b6e48c1b74ef riguz%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%28%01%00%00%00%00%00%00helloworld
其中%80%00这种是URL编码后的字符串,即0x80,。假设服务端收到这个字符串,会进行匹配,我们用java代码模拟一下:
String test = "akSK06mn91c2MxARSrOBTqdmhVCMkkoZriguz%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%28%01%00%00%00%00%00%00helloworld";
try {
String t = URLDecoder.decode(test, "ISO-8859-1");
String hex = Hex.hexViewer(t.getBytes("ISO-8859-1"));
System.out.println(hex);
String md5 = Hashs.encrypt("MD5", t.getBytes("ISO-8859-1"));
System.out.println("MD5:" + md5);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
输出为:
Address / 0 1 2 3 4 5 6 7 8 9 a b c d e f Dump 00000000| 61 6b 53 4b 30 36 6d 6e 39 31 63 32 4d 78 41 52 akSK06mn91c2MxAR 00000010| 53 72 4f 42 54 71 64 6d 68 56 43 4d 6b 6b 6f 5a SrOBTqdmhVCMkkoZ 00000020| 72 69 67 75 7a 80 00 00 00 00 00 00 00 00 00 00 riguz 00000030| 00 00 00 00 00 00 00 00 28 01 00 00 00 00 00 00 00000040| 68 65 6c 6c 6f 77 6f 72 6c 64 _ _ _ _ _ _ helloworld MD5:1800bc243a00db801833b6e48c1b74ef
可以看出算出的md5值与hash_extender生成的md5值是匹配的,如果服务器做比对的话,就会认为这个值是合理的。 Refer: