
admin
Author: admin
Cybersecurity Fundamentals for Developers
Cybersecurity Fundamentals for Developers
In today's digital landscape, security is not an afterthought—it's a fundamental requirement. As developers, we have the responsibility to build secure applications that protect user data and maintain trust.
"Security is not a product, but a process. It's not something you buy, but something you do."
— Bruce Schneier
The OWASP Top 10
The OWASP Top 10 represents the most critical security risks to web applications:
- Broken Access Control
- Cryptographic Failures
- Injection Attacks
- Insecure Design
- Security Misconfiguration
- Vulnerable and Outdated Components
- Identification and Authentication Failures
- Software and Data Integrity Failures
- Security Logging and Monitoring Failures
- Server-Side Request Forgery (SSRF)
Input Validation and Sanitization
Never trust user input. Always validate and sanitize data before processing:
// Input validation example
function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// SQL injection prevention with parameterized queries
const query = 'SELECT * FROM users WHERE email = ?';
db.query(query, [userEmail], (err, results) => {
if (err) throw err;
// Process results safely
});
// XSS prevention
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
Authentication and Authorization
Secure Password Handling
const bcrypt = require('bcrypt');
const saltRounds = 12;
// Hash password before storing
async function hashPassword(plainPassword) {
try {
const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
return hashedPassword;
} catch (error) {
throw new Error('Password hashing failed');
}
}
// Verify password during login
async function verifyPassword(plainPassword, hashedPassword) {
try {
const match = await bcrypt.compare(plainPassword, hashedPassword);
return match;
} catch (error) {
throw new Error('Password verification failed');
}
}
JWT Security Best Practices
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// Generate secure secret
const JWT_SECRET = crypto.randomBytes(64).toString('hex');
// Create JWT with proper expiration
function createToken(payload) {
return jwt.sign(
payload,
JWT_SECRET,
{
expiresIn: '15m',
issuer: 'your-app-name',
audience: 'your-users'
}
);
}
// Verify and refresh tokens
function verifyToken(token) {
try {
return jwt.verify(token, JWT_SECRET);
} catch (error) {
if (error.name === 'TokenExpiredError') {
throw new Error('Token expired');
}
throw new Error('Invalid token');
}
}
HTTPS and Transport Security
Always use HTTPS in production and implement security headers:
// Express.js security middleware
const helmet = require('helmet');
const express = require('express');
const app = express();
// Use Helmet for security headers
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
// CORS configuration
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://yourapp.com');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
API Security
- Implement rate limiting to prevent abuse
- Use API keys for service-to-service communication
- Validate all API inputs and outputs
- Implement proper error handling without information disclosure
- Use HTTPS for all API communications
- Implement request/response logging for audit trails
// Rate limiting example
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests from this IP",
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
Security Testing and Monitoring
Integrate security testing into your development workflow:
- Static Application Security Testing (SAST)
- Dynamic Application Security Testing (DAST)
- Dependency vulnerability scanning
- Regular security audits and penetration testing
- Implement comprehensive logging and monitoring
- Set up alerts for suspicious activities
Data Protection and Privacy
Protect sensitive data at rest and in transit:
// Data encryption example
const crypto = require('crypto');
class DataEncryption {
constructor() {
this.algorithm = 'aes-256-gcm';
this.secretKey = crypto.randomBytes(32);
}
encrypt(text) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipher(this.algorithm, this.secretKey);
cipher.setAAD(Buffer.from('additional-data'));
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
}
decrypt(encryptedData) {
const decipher = crypto.createDecipher(this.algorithm, this.secretKey);
decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));
decipher.setAAD(Buffer.from('additional-data'));
let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
Security is an ongoing process, not a one-time implementation. Stay updated with the latest security threats, regularly audit your code, and always follow the principle of least privilege. Remember: the cost of preventing security issues is always less than the cost of fixing them after they occur.