NodeClub代码的一个安全风险!Nodejs版
NodeClub代码的一个安全风险!Nodejs版
我看了一下NodeClub的源码,关于登录认证这部分我觉得是很有风险的。NodeClub作为一个开源程序,估计会有人图省事不会去修改session_secret
先看看生成认证Session代码:
function gen_session(user, res) {
var auth_token = encrypt(user._id + '\t' + user.name + '\t' + user.pass + '\t' + user.email, config.session_secret);
res.cookie(config.auth_cookie_name, auth_token, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30}); //cookie 有效期30天
}
这个代码有几个问题:
- 只要用户没修改密码和session secret,每次加密后结果其实是一样的,也就是用户每次登录后Cookie的值都是一样的,它是不会过期的,如果泄漏,那么就会被伪造,用户除了修改密码毫无办法。
- 加密使用的对称加密,如果session_secret泄密,那么Cookie的值会被解密。如果只是解密倒还是小事,关键会把用户的密码
user.pass
也看到,这很要命!虽然pass是md5之后的,但是md5并没有加上salt,所以有可能是会暴露一些信息的,因为只要密码一样,那么md5后的结果必然一样的。 - 如果session_secret泄密,那么可以加密结果直接伪造身份
建议:
- 登录后的Cookie加密时增加时间戳,保证每次登录后Cookie是不一样的,并且校验时根据时间戳判断过期
user.pass
不要放在加密内容里面- 提醒用户session_secret不修改导致的严重后果(最好是能安装时随机生成一个)
3 回复
NodeClub代码的一个安全风险!Nodejs版
我看了一下NodeClub的源码,关于登录认证这部分我觉得是很有风险的。NodeClub作为一个开源程序,估计会有人图省事不会去修改session_secret
。
先看看生成认证Session代码:
function gen_session(user, res) {
var auth_token = encrypt(user._id + '\t' + user.name + '\t' + user.pass + '\t' + user.email, config.session_secret);
res.cookie(config.auth_cookie_name, auth_token, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30}); // cookie 有效期30天
}
这段代码存在几个潜在的安全问题:
-
Cookie值固定不变:
- 只要用户没有修改密码和
session_secret
,每次加密后的结果都是相同的,这意味着Cookie的值不会改变。如果Cookie泄露,攻击者可以使用相同的Cookie进行登录,而用户无法通过修改密码来撤销这个Cookie。
- 只要用户没有修改密码和
-
使用对称加密:
- 如果
session_secret
泄露,攻击者可以解密Cookie中的信息。更糟糕的是,用户密码(user.pass
)也会被暴露出来。尽管密码已经经过MD5哈希处理,但如果多个用户使用相同的密码,攻击者仍然可以通过比较哈希值来识别这些用户。
- 如果
-
容易被伪造身份:
- 如果
session_secret
泄露,攻击者可以直接构造合法的Cookie进行身份伪造。
- 如果
建议改进:
为了提高安全性,我们可以对上述代码进行以下改进:
-
增加时间戳以确保每次登录后Cookie不同:
- 在生成Cookie时,加入当前时间戳,这样每次登录后Cookie都会不同。同时,在验证Cookie时,根据时间戳判断其是否过期。
function gen_session(user, res) { var timestamp = Date.now(); var auth_token = encrypt(user._id + '\t' + user.name + '\t' + timestamp, config.session_secret); res.cookie(config.auth_cookie_name, auth_token, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30}); // cookie 有效期30天 }
-
移除用户密码:
- 不要在加密内容中包含用户密码,只保留必要的信息,如用户ID和用户名。
function gen_session(user, res) { var timestamp = Date.now(); var auth_token = encrypt(user._id + '\t' + user.name + '\t' + timestamp, config.session_secret); res.cookie(config.auth_cookie_name, auth_token, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30}); // cookie 有效期30天 }
-
提醒用户修改默认的
session_secret
:- 在安装过程中随机生成一个
session_secret
,并提醒用户不要使用默认值。如果用户继续使用默认值,可能会面临严重的安全风险。
- 在安装过程中随机生成一个
通过以上改进,可以显著提升NodeClub的安全性,减少潜在的风险。
…这个咱们程序员不会连这个常识都没吧…
根据你描述的问题,NodeClub的登录认证机制确实存在一定的安全隐患。主要问题是session的加密方式容易被破解或伪造,尤其是在session_secret
未被修改的情况下。
改进建议
- 使用不同的加密内容:避免在加密内容中包含敏感信息,如
user.pass
。 - 添加时间戳:确保每次登录后的Cookie值不同,并且可以根据时间戳来判断是否过期。
- 使用更强的加密算法:推荐使用更安全的加密算法和密钥管理方法。
示例改进代码
const crypto = require('crypto');
const moment = require('moment');
function gen_session(user, res, sessionSecret) {
const timestamp = moment().unix(); // 获取当前时间戳
const dataToEncrypt = `${user._id}\t${user.name}\t${timestamp}`;
const auth_token = encrypt(dataToEncrypt, sessionSecret);
res.cookie(config.auth_cookie_name, auth_token, {
path: '/',
maxAge: 1000 * 60 * 60 * 24 * 30, // Cookie有效期30天
httpOnly: true, // 增加安全性,禁止JavaScript访问cookie
secure: true // 如果使用HTTPS,则应设置为true
});
}
function encrypt(data, secret) {
const cipher = crypto.createCipher('aes-256-cbc', secret);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
function decrypt(encryptedData, secret) {
const decipher = crypto.createDecipher('aes-256-cbc', secret);
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// 使用示例
gen_session({ _id: '123', name: 'testuser' }, res, 'your-session-secret');
解释
- 使用时间戳:每次登录时,都会生成一个新的时间戳,这样即使
session_secret
没有改变,每次生成的Cookie值也会不同。 - 加密内容:只加密必要的信息,例如用户ID和用户名,而不是用户的密码。
- 增强安全性:在设置Cookie时增加
httpOnly
和secure
标志,提高安全性。
通过这些改进,可以显著提升NodeClub的安全性,减少因Cookie泄露而带来的潜在风险。