Cookie防僞造防修改 電商課題:cookie防篡改

主要防止非法用戶修改cookie信息,以及cookie的超時時間 
傳統cookie存儲,Cookie(name, value),value很容易就被篡改。 
防修改cookie存儲,Cookie(name, value+「&&」+ signToken+「&&」+saveTime+「&&」+maxTime) 
signToken :簽名密鑰 由md5(value+saveTime+maxTime+」自定義密鑰「)生成 
saveTime:cookie建立時間 
maxTime:cookie超時時間html

設置Cookie瀏覽器

public static void put(HttpServletResponse response, String key, String value, int maxTime) { String pwdKey = "white_yu"; //自定義密鑰 String saveTime = System.currentTimeMillis() + ""; String signToken = md5(pwdKey, saveTime, maxTime + "", value); String cookieValue = signToken + "&&" + saveTime + "&&" + maxTime + "&&" + value; Cookie cookie = new Cookie(key,cookieValue); cookie.setMaxAge(maxTime); response.addCookie(cookie); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

獲取Cookie安全

public static String getCookie(String cookieValue) { String pwdKey = "white_yu"; //自定義密鑰 if (StringUtils.isNotBlank(cookieValue)) { String cookieStrings[] = cookieValue.split("&&"); if (null != cookieStrings && 4 == cookieStrings.length) { String signToken = cookieStrings[0]; String saveTime = cookieStrings[1]; String maxTime = cookieStrings[2]; String value = cookieStrings[3]; String sign = md5(pwdKey, saveTime, maxTime, value); // 保證 cookie 不被人爲修改 if (sign.equals(signToken)) { long stime = Long.parseLong(saveTime); long maxtime = Long.parseLong(maxTime) * 1000; // 查看是否過期 if ((stime + maxtime) - System.currentTimeMillis() > 0) { return value; } } } } return null; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
版權聲明:轉載請標註原文地址 https://blog.csdn.net/soul_code/article/details/52768421
 
 
 
cookie是存儲在用戶本地的,最高權限仍是在用戶手上,服務器能夠驗證cookie是否合法性,
 
 
 
 
關鍵詞: cookie poisoning
概述:
除了 session 外,通常不會在客戶端的 cookies 裏保存過於重要的憑據,但電商應用有時候不可避免地存儲了一些敏感數據到客戶端,固然不但願被篡改。

目的:
讓服務器端能識別cookie值被篡改了。
 
手法:
set-cookie時加上防篡改驗證碼。
如:
user_name=alex|bj95ef23cc6daecc475de
 
防篡改驗證碼的生成規則能夠很簡單:md5(cookieValue+key)或sha1(cookieValue+key),key能夠是服務器端掌握的一個固定字符串,也能夠很複雜(如後面的LTPA示例)。
 
服務器端獲得客戶端送上來的cookie後,從新計算一下驗證碼,如一致,則未篡改。
 
示例2:IBM LTPA 的 cookie 簽名
Lightweight Third-Party Authentication (LTPA)是IBM Websphere和Domino產品中使用的單點登陸技術。
當服務器配置好LTPA認證方式,用戶經過瀏覽器成功登陸後,服務器會自動發送一個 session cookie 給瀏覽器;此 Cookie 中包含一個 LTPA Token。
一個有效的 LTPA Cookie 可以在同一個認證域中被全部服務器自動認證。此 Cookie 中包含認證信息和時間戳。這些信息經過共享的 3DES Key 進行了 bis  加密。使用公共密鑰/私有密鑰進行簽名。
 
1)大體介紹:
LTPA Cookie 原始值 經過  3DES密鑰 使用 DESede/ECB/PKCS5P 進行加密。
此  3DES密鑰  也是採用 DESede/ECB/PKCS5P 進行加密,加密後再使用事先提供的  密鑰密碼 進行SHA-1 Hash,生成24個字節的密鑰,再進行Base64編碼。
 
如 Dmonio 裏, LTPA Cookie 值爲如下公式組成:
SHA-1=LTPA版本號+建立時間+過時時間+用戶名+Domino LTPA 密鑰
LTPA Cookie= Base64(LTPA版本號+建立時間+過時時間+用戶名+SHA-1)
 
如要解析 LTPA Token,先得使用  密鑰密碼,生成 3DES密鑰;再使用 3DES密鑰 解密 Token Cookie。也可使用公共/私有密鑰來簽名或驗證LTPA Cookie。

2)WebSphere LTPA 生成原理

首先,這個 cookie 由如下部分組成,以%進行分隔:
  • 用戶信息,格式爲u:user\:<RealmName>/<UserDN>,如:u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology
  • 過時時間
  • 簽名信息,如:
    u:user\:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology%1301558320666%Cy2CAeru5kEElGj0hrvYsKW2ZVsvvcu6Un573aeX55OO4G3EMYWc0e/ZbqDp1z7MS+dLzniuUH4sYWCMpnKdm7ZGabwmV+WcraBl+y+yzwcl722gHVMOnDZAW7U3jEay9Tk2yG4yXkMWU+617xndpVxke2jtS5wIyVVM3q7UDPw=

3)WebSphere LTPA Cookie 的解析

如下代碼爲解析從 WebSphere 或 Domino 發送過來的 LTPAToken Cookie。以Java爲例:服務器

01
02         // LTPA 3DES 密鑰
03         String ltpa3DESKey = "7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=";
04         // LTPA 密鑰密碼
05         String ltpaPassword = "Passw0rd";
06         try {
07             // 第一步,得到加密key
08             byte[] secretKey = getSecretKey(ltpa3DESKey, ltpaPassword);
09             // 第二步,使用加密key解密ltpa Cookie
10             String ltpaPlaintext = new String(decryptLtpaToken(tokenCipher,
11                     secretKey));
12             displayTokenData(ltpaPlaintext);
13         } catch (Exception e) {
14             System.out.println("Caught inner: " + e);
15         }
16
17     //得到安全Key
18     private static byte[] getSecretKey(String ltpa3DESKey, String password)
19             throws Exception {
20         // 使用SHA得到key密碼的hash值
21         MessageDigest md = MessageDigest.getInstance("SHA");
22         md.update(password.getBytes());
23         byte[] hash3DES = new byte[24];
24         System.arraycopy(md.digest(), 0, hash3DES, 0, 20);
25         // 使用0替換後4個字節
26         Arrays.fill(hash3DES, 20, 24, (byte) 0);
27         // BASE64解碼 ltpa3DESKey
28         byte[] decode3DES = Base64.decodeBase64(ltpa3DESKey.getBytes());
29         // 使用key密碼hash值解密已Base64解碼的ltpa3DESKey
30         return decrypt(decode3DES, hash3DES);
31     }
32     //解密LtpaToken
33     public static byte[] decryptLtpaToken(String encryptedLtpaToken, byte[] key)
34             throws Exception {
35         // Base64解碼LTPAToken
36         final byte[] ltpaByteArray = Base64.decodeBase64(encryptedLtpaToken
37                 .getBytes());
38         // 使用key解密已Base64解碼的LTPAToken
39         return decrypt(ltpaByteArray, key);
40     }
41     // DESede/ECB/PKC5Padding解方法
42     public static byte[] decrypt(byte[] ciphertext, byte[] key)
43             throws Exception {
44         final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
45         final KeySpec keySpec = new DESedeKeySpec(key);
46         final Key secretKey = SecretKeyFactory.getInstance("TripleDES")
47                 .generateSecret(keySpec);
48         cipher.init(Cipher.DECRYPT_MODE, secretKey);
49         return cipher.doFinal(ciphertext);
50     }
51

解析出來的LTPAToken信息以%分隔。markdown

 
參考資源:
1)hannover, LTPA Cookie原理
相關文章
相關標籤/搜索