Security considerations for middleware
Security Considerations for Middleware
Express middleware is the core component for handling HTTP requests, but improper usage can lead to serious security vulnerabilities. From input validation to dependency management, each step requires strict security measures.
Input Validation and Filtering
All data passed through middleware must be treated as untrusted. Lack of validation can lead to injection attacks or logic flaws:
// Dangerous example: Directly using unvalidated query parameters
app.use('/search', (req, res) => {
const query = req.query.term;
db.execute(`SELECT * FROM products WHERE name LIKE '%${query}%'`);
});
// Secure practice: Parameterized queries
app.use('/search', (req, res) => {
const query = req.query.term;
db.execute('SELECT * FROM products WHERE name LIKE ?', [`%${query}%`]);
});
Key validation points should include:
- Request body parameters (JSON/URL-encoded)
- Query string parameters
- Route parameters
- Uploaded filenames
- HTTP header values
Use validation libraries like Joi or express-validator:
const { body, validationResult } = require('express-validator');
app.post('/user',
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process valid data
}
);
Header Security Configuration
Middleware must correctly set security-related HTTP headers:
const helmet = require('helmet');
app.use(helmet());
// Custom CORS policy
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://trusted.example.com');
res.header('X-Content-Type-Options', 'nosniff');
res.header('X-Frame-Options', 'DENY');
next();
});
Special attention to:
Content-Security-Policy
to prevent XSSStrict-Transport-Security
to enforce HTTPSX-XSS-Protection
to enable browser XSS filtering- Disable
X-Powered-By
header
Session Management
Improper session middleware configuration can lead to authentication bypass:
// Insecure session configuration
app.use(session({
secret: 'weak-secret',
cookie: {
httpOnly: false, // Allows JS access
secure: false // Transmitted over non-HTTPS
}
}));
// Secure configuration
app.use(session({
secret: crypto.randomBytes(32).toString('hex'),
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000
},
resave: false,
saveUninitialized: false
}));
Must avoid:
- Using predictable session IDs
- Excessively long session timeouts
- Passing session identifiers in URLs
File Upload Handling
File upload middleware requires special protection:
const multer = require('multer');
const upload = multer({
limits: {
fileSize: 1024 * 1024 * 5, // 5MB limit
files: 1
},
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.mimetype)) {
return cb(new Error('Invalid file type'));
}
cb(null, true);
},
storage: multer.diskStorage({
destination: '/secure/upload/path',
filename: (req, file, cb) => {
const ext = path.extname(file.originalname);
cb(null, crypto.randomUUID() + ext); // Randomize filename
}
})
});
app.post('/upload', upload.single('avatar'), (req, res) => {
// Process file
});
Key protective measures:
- Restrict file types and sizes
- Scan uploaded content (e.g., using clamscan)
- Store in non-web-accessible directories
- Rename files to prevent path traversal
Dependency Security
Middleware dependencies may introduce vulnerabilities:
# Regularly check for dependency vulnerabilities
npm audit
npx nodejsscan --directory ./middleware
Best practices:
- Lock dependency versions (package-lock.json)
- Use Snyk or Dependabot for continuous monitoring
- Remove unused middleware
- Review third-party middleware source code
Error Handling
Insecure error handling can leak sensitive information:
// Dangerous example: Exposes stack traces
app.use((err, req, res, next) => {
res.status(500).send(err.stack);
});
// Secure error handling
app.use((err, req, res, next) => {
console.error('Internal error:', err);
res.status(500).json({
error: 'An unexpected error occurred'
});
});
Ensure:
- Detailed errors are disabled in production
- Log errors to secure logging systems
- Custom 404/500 error pages
- Do not expose server technology stack information
Rate Limiting
Middleware configuration to prevent brute-force attacks:
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 requests per IP
message: 'Too many login attempts',
handler: (req, res) => {
res.status(429).json({
error: 'Account temporarily locked'
});
}
});
app.post('/login', loginLimiter, authController.login);
Endpoints requiring limitation:
- User authentication-related
- Password reset
- Critical API operations
- Resource-intensive requests
Middleware Order
Security-related middleware must be loaded first:
// Correct middleware order
app.use(helmet());
app.use(cors());
app.use(rateLimit());
app.use(express.json());
app.use(session());
app.use(passport.initialize());
app.use(routes);
Common mistakes:
- Adding security middleware after routes
- Incorrect session middleware order
- Error-handling middleware not placed last
Environment Variable Protection
Sensitive information in middleware configuration must be encrypted:
// Wrong approach: Hardcoded secret
app.use(jwt({
secret: 'my-secret-key'
}));
// Correct approach: Get from environment variables
require('dotenv').config();
app.use(jwt({
secret: process.env.JWT_SECRET,
algorithms: ['HS256']
}));
Security requirements:
- Never commit .env files to version control
- Use encrypted secret management tools
- Set different keys for different environments
- Regularly rotate keys
Request Body Parsing
Insecure body parsing may lead to DoS attacks:
// Dangerous configuration: No request body size limit
app.use(express.json());
// Secure configuration
app.use(express.json({
limit: '10kb',
verify: (req, res, buf) => {
try {
JSON.parse(buf.toString());
} catch (e) {
throw new Error('Invalid JSON');
}
}
}));
Special attention:
- Limit URL-encoded data size
- Disable loose parsing modes
- Validate content-type headers
- Handle parsing errors
Cross-Site Request Forgery Protection
Critical operations require CSRF protection:
const csrf = require('csurf');
const csrfProtection = csrf({
cookie: {
httpOnly: true,
sameSite: 'strict'
}
});
app.get('/form', csrfProtection, (req, res) => {
res.render('send', { csrfToken: req.csrfToken() });
});
app.post('/transfer', csrfProtection, (req, res) => {
// Process protected form
});
Protection points:
- Use POST requests for sensitive operations
- Same-origin policy checks
- Custom header validation
- Require secondary authentication for state-changing operations
Logging
Security logging middleware example:
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');
// Create access log stream
const accessLogStream = fs.createWriteStream(
path.join(__dirname, 'access.log'),
{ flags: 'a' }
);
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"', {
stream: accessLogStream,
skip: (req) => req.path === '/healthcheck'
}));
// Audit logging middleware
app.use((req, res, next) => {
if (req.path.includes('/admin')) {
logAdminAction(req.user, req.path, req.method);
}
next();
});
Logging security requirements:
- Do not log sensitive information (passwords, tokens)
- Set log file permissions to 600
- Regularly rotate and archive logs
- Monitor abnormal access patterns
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:中间件的测试策略
下一篇:中间件的日志记录与监控