fix: 修复多个安全缺陷和功能问题

- 移除加密相关代码(服务端和所有客户端)
- 修复 JWT 验证未检查签名算法的问题
- 修复重置密码使用不安全随机数的问题
- 实现 Logout 服务端失效机制
- 修复历史版本对比 diff 颜色标记错误
- 修复占位符解析循环引用风险
- 添加用户禁用状态检查
- 更新 bug 清单文档
This commit is contained in:
2026-03-10 21:07:22 +08:00
parent f41d53da41
commit 932db9fbdc
27 changed files with 292 additions and 721 deletions
+2 -50
View File
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
@@ -22,39 +21,6 @@ namespace KenaitoConf
public string CacheDir { get; set; } = ".";
}
public static class Crypto
{
private const string CryptPrefix = "{Cipher}";
public static string DecryptConfig(string secret, string data)
{
if (!data.StartsWith(CryptPrefix))
return data;
return DecryptWithAES(secret, data.Substring(CryptPrefix.Length));
}
public static string DecryptWithAES(string key, string data)
{
using var md5 = MD5.Create();
string md5Hash = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", "").ToLower();
string aesKeyStr = md5Hash.Substring(16);
byte[] aesKey = Encoding.UTF8.GetBytes(aesKeyStr);
byte[] cipherText = Convert.FromBase64String(data);
byte[] iv = new byte[16];
using var aes = Aes.Create();
aes.Key = aesKey;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
using var decryptor = aes.CreateDecryptor();
byte[] plainText = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);
int padding = plainText[plainText.Length - 1];
return Encoding.UTF8.GetString(plainText, 0, plainText.Length - padding);
}
}
public class Cache
{
private readonly string _cacheDir;
@@ -86,8 +52,6 @@ namespace KenaitoConf
private readonly Cache _cache;
private readonly HttpClient _http = new();
private readonly Dictionary<string, string> _configs = new();
private string _secret = "";
private string _globalSecret = "";
private long _lastTime = 0;
private bool _started = false;
private CancellationTokenSource _cts;
@@ -188,10 +152,6 @@ namespace KenaitoConf
throw new Exception($"server error: {(data.ContainsKey("msg") ? data["msg"] : "unknown")}");
}
if (data.TryGetValue("kenaito.config.encrypt-secret", out var s))
_secret = s?.ToString() ?? "";
if (data.TryGetValue("kenaito.config.global-encrypt-secret", out var gs))
_globalSecret = gs?.ToString() ?? "";
if (data.TryGetValue("latest.fetch.timestamp", out var ts))
_lastTime = Convert.ToInt64(ts);
@@ -231,7 +191,7 @@ namespace KenaitoConf
var changed = new Dictionary<string, string>();
foreach (var kv in changedData)
{
changed[kv.Key] = TryDecrypt(kv.Value?.ToString() ?? "");
changed[kv.Key] = kv.Value?.ToString() ?? "";
}
foreach (var kv in changed)
@@ -252,16 +212,8 @@ namespace KenaitoConf
continue;
if (kv.Value is JsonElement)
continue;
_configs[kv.Key] = TryDecrypt(kv.Value?.ToString() ?? "");
_configs[kv.Key] = kv.Value?.ToString() ?? "";
}
}
private string TryDecrypt(string value)
{
string decrypted = Crypto.DecryptConfig(_secret, value);
if (decrypted == value && !string.IsNullOrEmpty(_globalSecret))
decrypted = Crypto.DecryptConfig(_globalSecret, value);
return decrypted;
}
}
}