阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 常见安全威胁

常见安全威胁

作者:陈川 阅读数:47283人阅读 分类: Node.js

Node.js 作为后端运行时环境,面临多种安全威胁。从代码注入到依赖漏洞,开发者需全面了解攻击场景并采取针对性防护措施。以下分类讨论典型风险及解决方案。

代码注入攻击

代码注入是Node.js应用最危险的安全威胁之一。常见形式包括:

  1. SQL注入:未过滤的用户输入直接拼接SQL语句
// 危险示例
const query = `SELECT * FROM users WHERE username = '${req.body.username}'`;
db.query(query, (err, result) => { ... });

// 安全方案
const query = 'SELECT * FROM users WHERE username = ?';
db.query(query, [req.body.username], (err, result) => { ... });
  1. 命令注入:通过child_process执行未净化的输入
// 危险示例
const { exec } = require('child_process');
exec(`ls ${userInput}`, (error, stdout) => {...});

// 安全方案
const { execFile } = require('child_process');
execFile('ls', [userInput], (error, stdout) => {...});
  1. 模板注入:动态模板引擎处理用户输入
// EJS示例
const template = `<h1>Welcome <%= unsafeUserInput %></h1>`;
// 应使用内容转义
const template = `<h1>Welcome <%- escape(unsafeUserInput) %></h1>`;

身份认证缺陷

认证系统漏洞常导致严重安全问题:

  1. 弱密码策略:未强制密码复杂度要求
// 应使用密码强度校验库
const zxcvbn = require('zxcvbn');
if (zxcvbn(password).score < 3) {
  throw new Error('密码强度不足');
}
  1. 会话固定攻击:登录前后session ID不变
// 应在认证成功后重置会话
app.post('/login', (req, res) => {
  req.session.regenerate(() => {
    req.session.user = authenticatedUser;
  });
});
  1. JWT实现问题:未验证签名或使用弱算法
// 错误配置
jwt.sign(payload, 'weak-secret', { algorithm: 'HS256' });

// 正确做法
jwt.sign(payload, process.env.STRONG_SECRET, { 
  algorithm: 'RS256',
  expiresIn: '2h'
});

依赖链风险

第三方包可能引入安全隐患:

  1. 恶意包植入:通过依赖项执行恶意代码
# 应定期审计依赖
npm audit
npx nodejsscan
  1. 过时依赖漏洞:未及时更新存在已知漏洞的包
// package.json应指定精确版本
"dependencies": {
  "express": "4.18.2",
  "lodash": "4.17.21"
}
  1. 供应链攻击:开发者账户被盗导致合法包被篡改
// 使用包完整性校验
npm install --package-lock-only
npm ci

配置错误

不当配置常成为攻击入口:

  1. 敏感信息泄露:配置文件包含明文密码
// 错误做法
module.exports = {
  dbPassword: '123456'
};

// 应使用环境变量
require('dotenv').config();
module.exports = {
  dbPassword: process.env.DB_PASSWORD
};
  1. CORS过度宽松:允许任意来源访问
// 危险配置
app.use(cors());

// 安全配置
const whitelist = ['https://example.com'];
app.use(cors({
  origin: (origin, callback) => {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}));
  1. HTTP头缺失:未设置安全相关头部
// 应添加安全头部
const helmet = require('helmet');
app.use(helmet());

拒绝服务攻击

系统资源可能被恶意耗尽:

  1. 正则表达式灾难:低效正则导致CPU过载
// 危险正则
/(a+)+$/.test('aaaaaaaaX');

// 应使用安全库
const safe-regex = require('safe-regex');
if (!safeRegex(regexPattern)) {
  throw new Error('潜在危险的正则表达式');
}
  1. 未限制请求体大小:大型文件上传导致内存溢出
// 应配置body解析限制
app.use(express.json({ limit: '100kb' }));
app.use(express.urlencoded({ limit: '100kb' }));
  1. 事件循环阻塞:同步操作占用主线程
// 错误示例
const data = fs.readFileSync('large.file');

// 正确做法
fs.readFile('large.file', (err, data) => {...});

文件系统安全

不当文件操作导致漏洞:

  1. 路径遍历攻击:未过滤用户提供的文件路径
// 危险示例
app.get('/download', (req, res) => {
  const file = req.query.file;
  res.download(`/var/www/uploads/${file}`);
});

// 安全方案
const path = require('path');
app.get('/download', (req, res) => {
  const file = path.basename(req.query.file);
  const fullPath = path.join('/var/www/uploads', file);
  if (!fullPath.startsWith('/var/www/uploads')) {
    return res.status(403).end();
  }
  res.download(fullPath);
});
  1. 临时文件竞争:文件创建与权限设置不同步
// 不安全操作
fs.writeFile('/tmp/data.tmp', data, (err) => {
  fs.chmod('/tmp/data.tmp', 0o600, (err) => {...});
});

// 原子操作方案
const { open } = require('fs').promises;
async function safeWrite(path, data) {
  const fd = await open(path, 'wx', 0o600);
  await fd.write(data);
  await fd.close();
}

日志与监控缺陷

安全事件未被有效记录:

  1. 敏感信息记录:日志中包含密码或令牌
// 错误日志
console.log(`User login with password: ${password}`);

// 应过滤敏感字段
const maskFields = (obj) => {
  const masked = { ...obj };
  ['password', 'token'].forEach(field => {
    if (masked[field]) masked[field] = '***';
  });
  return masked;
};
  1. 日志注入攻击:恶意输入污染日志格式
// 危险示例
logger.info(`User input: ${userInput}`);

// 安全处理
const sanitize = (str) => str.replace(/\n/g, '\\n');
logger.info(`User input: ${sanitize(userInput)}`);
  1. 缺乏监控:未设置异常行为告警
// 应配置异常监控
const NewRelic = require('newrelic');
process.on('uncaughtException', (err) => {
  NewRelic.noticeError(err);
  process.exit(1);
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:压测工具使用

下一篇:输入验证

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌