先前曾發表過一遍介紹水準權限漏洞的文章:
水準權限漏洞的修複方案:javascript:void(0)
"水準權限漏洞一般出現在一個使用者對象關聯多個其他對象(訂單、位址等)、并且要實作對關聯對象的CRUD的時候。開發容易習慣性的在生成CRUD表單(或 AJAX請求)的時候根據認證過的使用者身份來找出其有權限的被操作對象id,提供入口,然後讓使用者送出請求,并根據這個id來操作相關對象。在處理 CRUD請求時,往往預設隻有有權限的使用者才能得到入口,進而才能操作相關對象,是以就不再校驗權限了。可悲劇的是大多數對象的ID都被設定為自增整型, 是以攻擊者隻要對相關id加1、減1、直至周遊,就可以操作其他使用者所關聯的對象了。"
該文章主要是對水準權限漏洞産生的原因進行了一些分析,感興趣的同學可以溫習下。
這次在一個安全項目開發中,上司要求預防水準權限漏洞的産生,項目底層正好使用了通用權限管理底層代碼。參考了上面文章的方法。
通過引用其底層代碼的安全工具類對水準權限漏洞進行了預防。下面把代碼分享下:
一、前端對userId,利用通用權限管理系統底層的方法DotNet.Utilities.SecretUtil.Encrypt方法加密。加密内部實作原理如下:
1 /// <summary>
2 /// DES資料加密
3 /// </summary>
4 /// <param name="targetValue">目标值</param>
5 /// <param name="key">密鑰</param>
6 /// <returns>加密值</returns>
7 public static string Encrypt(string targetValue, string key)
8 {
9 if (string.IsNullOrEmpty(targetValue))
10 {
11 return string.Empty;
12 }
13
14 var result = new StringBuilder();
15 var des = new DESCryptoServiceProvider();
16 byte[] inputByteArray = Encoding.Default.GetBytes(targetValue);
17 // 通過兩次哈希密碼設定對稱算法的初始化向量
18 des.Key = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile
19 (FormsAuthentication.HashPasswordForStoringInConfigFile(key, "md5").
20 Substring(0, 8), "sha1").Substring(0, 8));
21 // 通過兩次哈希密碼設定算法的機密密鑰
22 des.IV = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile
23 (FormsAuthentication.HashPasswordForStoringInConfigFile(key, "md5")
24 .Substring(0, 8), "md5").Substring(0, 8));
25 var ms = new MemoryStream();
26 var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
27 cs.Write(inputByteArray, 0, inputByteArray.Length);
28 cs.FlushFinalBlock();
29 foreach (byte b in ms.ToArray())
30 {
31 result.AppendFormat("{0:X2}", b);
32 }
33 return result.ToString();
34 }
二、背景利用通用權限管理系統底層的方法DotNet.Utilities.SecretUtil.Decrypt 對前台傳來的useId進行了解密,實作原理如下:
1 /// <summary>
2 /// DES資料解密
3 /// 20140219 吉日嘎拉 就是出錯了,也不能讓程式崩潰
4 /// </summary>
5 /// <param name="targetValue"></param>
6 /// <param name="key"></param>
7 /// <returns></returns>
8 public static string Decrypt(string targetValue, string key)
9 {
10 if (string.IsNullOrEmpty(targetValue))
11 {
12 return string.Empty;
13 }
14 // 定義DES加密對象
15 try
16 {
17 var des = new DESCryptoServiceProvider();
18 int len = targetValue.Length / 2;
19 var inputByteArray = new byte[len];
20 int x, i;
21 for (x = 0; x < len; x++)
22 {
23 i = Convert.ToInt32(targetValue.Substring(x * 2, 2), 16);
24 inputByteArray[x] = (byte)i;
25 }
26 // 通過兩次哈希密碼設定對稱算法的初始化向量
27 des.Key = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile
28 (FormsAuthentication.HashPasswordForStoringInConfigFile(key, "md5").
29 Substring(0, 8), "sha1").Substring(0, 8));
30 // 通過兩次哈希密碼設定算法的機密密鑰
31 des.IV = Encoding.ASCII.GetBytes(FormsAuthentication.HashPasswordForStoringInConfigFile
32 (FormsAuthentication.HashPasswordForStoringInConfigFile(key, "md5")
33 .Substring(0, 8), "md5").Substring(0, 8));
34 // 定義記憶體流
35 var ms = new MemoryStream();
36 // 定義加密流
37 var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
38 cs.Write(inputByteArray, 0, inputByteArray.Length);
39 cs.FlushFinalBlock();
40 return Encoding.Default.GetString(ms.ToArray());
41 }
42 catch
43 {
44 }
45 return string.Empty;
46 }
可以看到,在加密和解密方法中,我使用了使用者的密碼作為秘鑰,這樣對水準權限漏洞的預防會更好。
通用權限底層對安全防護做的很完美,大家合理利用,可預防常見安全問題的産生。
對于水準權限漏洞的預防,大家如果有更好的方法,歡迎交流~~,上面提供的底層方法,大家可以直接在項目中使用。