跳到主要内容

密码攻击与防御

什么是密码攻击

密码攻击是指攻击者通过各种手段获取用户密码,从而未经授权访问系统或数据的攻击方式。密码攻击是最常见的网络攻击类型之一,成功率高且实施成本低。

攻击原理

  1. 攻击者获取密码存储文件或密码哈希值
  2. 使用字典攻击、暴力破解、彩虹表等方法破解密码
  3. 或者通过钓鱼、键盘记录等方式直接获取明文密码
  4. 使用获取的密码登录系统,窃取数据或进行其他恶意操作

常见攻击手法

  • 字典攻击:使用预定义的字典尝试常见密码
  • 暴力破解:尝试所有可能的字符组合
  • 彩虹表攻击:使用预计算的哈希值表匹配密码哈希
  • 钓鱼攻击:通过欺骗用户获取密码
  • 键盘记录:通过恶意软件记录用户输入的密码
  • 密码重用攻击:利用用户在多个网站使用相同密码的习惯
  • 社会工程学:通过欺骗手段获取密码(已单独成篇)

防御措施

  1. 使用强密码策略:要求密码包含大小写字母、数字和特殊字符
  2. 密码哈希存储:使用bcrypt、Argon2等强哈希算法存储密码
  3. 加盐哈希:为每个密码添加唯一盐值,防止彩虹表攻击
  4. 双因素认证:启用双因素认证,增加额外安全层
  5. 密码策略:实施密码过期、历史密码检查等策略
  6. 用户教育:教育用户使用强密码,避免密码重用
  7. 防钓鱼训练:培训用户识别钓鱼攻击

Node.js防御示例

安全的密码存储与验证

const express = require('express');
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const app = express();

app.use(express.json());

// 定义用户模型
const UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true }
});

// 密码加密中间件
UserSchema.pre('save', async function(next) {
if (!this.isModified('password')) {
return next();
}

// 生成盐值并加密密码
const salt = await bcrypt.genSalt(12); // 12轮盐值生成
this.password = await bcrypt.hash(this.password, salt);
next();
});

// 密码验证方法
UserSchema.methods.validatePassword = async function(password) {
return bcrypt.compare(password, this.password);
};

const User = mongoose.model('User', UserSchema);

// 用户注册
app.post('/register', async (req, res) => {
try {
const { username, password } = req.body;

// 验证密码强度
if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/.test(password)) {
return res.status(400).send('密码必须至少8位,包含大小写字母、数字和特殊字符');
}

const user = new User({ username, password });
await user.save();
res.status(201).send('用户注册成功');
} catch (error) {
res.status(500).send(error.message);
}
});

// 用户登录
app.post('/login', async (req, res) => {
try {
const { username, password } = req.body;
const user = await User.findOne({ username });

if (!user) {
return res.status(401).send('用户名或密码错误');
}

const isMatch = await user.validatePassword(password);
if (!isMatch) {
return res.status(401).send('用户名或密码错误');
}

// 生成JWT令牌等登录逻辑
res.send('登录成功');
} catch (error) {
res.status(500).send(error.message);
}
});

mongoose.connect('mongodb://localhost:27017/password-security')
.then(() => console.log('MongoDB连接成功'))
.catch(err => console.error('MongoDB连接错误:', err));

app.listen(3000, () => {
console.log('Server running on port 3000');
});

双因素认证实现

const express = require('express');
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');
const app = express();

app.use(express.json());

// 模拟用户数据库
const users = {};

// 生成双因素认证密钥
app.post('/enable-2fa', (req, res) => {
const { userId } = req.body;

// 生成密钥
const secret = speakeasy.generateSecret({ length: 20 });

// 保存密钥到用户数据
users[userId] = { secret: secret.base32 };

// 生成QR码URL
const otpauthUrl = speakeasy.otpauthURL({
secret: secret.ascii,
label: 'MyApp',
issuer: 'MyApp'
});

QRCode.toDataURL(otpauthUrl, (err, dataUrl) => {
if (err) {
res.status(500).send('生成QR码失败');
return;
}

res.send({
secret: secret.base32,
qrCode: dataUrl
});
});
});

// 验证双因素认证代码
app.post('/verify-2fa', (req, res) => {
const { userId, token } = req.body;

if (!users[userId]) {
res.status(404).send('用户未找到');
return;
}

const verified = speakeasy.totp.verify({
secret: users[userId].secret,
encoding: 'base32',
token
});

res.send({ verified });
});

app.listen(3000, () => {
console.log('Server running on port 3000');
});

检测与响应

  • 使用密码破解检测工具:如John the Ripper、Hashcat等
  • 登录监控:监控异常登录尝试,实施账户锁定
  • 密码强度检查:强制用户使用强密码
  • 安全审计:定期进行密码安全审计
  • 应急响应:制定密码泄露应急响应计划,包括密码重置和账户锁定

最佳实践

  • 使用bcrypt、Argon2等强哈希算法存储密码
  • 为每个密码添加唯一盐值
  • 实施强密码策略,要求密码包含多种字符类型
  • 启用双因素认证
  • 定期要求用户更改密码
  • 禁止密码重用
  • 教育用户使用密码管理器
  • 定期进行安全测试,包括密码破解测试