Penetration Testing
Learn ethical hacking techniques
Ta treść nie jest jeszcze dostępna w Twoim języku.
Your e-commerce platform just failed a security audit. The report reveals SQL injection vulnerabilities, exposed API keys, weak authentication, CSRF vulnerabilities, and sensitive data in logs. With PCI compliance deadline approaching and customer data at risk, you need to implement comprehensive security fixes immediately.
By completing this lesson, you’ll master:
Secure the application by:
Start with a full security audit:
@src"Perform a comprehensive security audit:- Check for SQL injection vulnerabilities- Find exposed secrets and API keys- Identify authentication weaknesses- Detect CSRF vulnerabilities- Find XSS attack vectors- Check for insecure dependenciesCategorize by severity and provide fixes"
"Analyze package.json and lock files for:- Known vulnerabilities in dependencies- Outdated packages with security issues- License compliance issues- Supply chain risksCreate upgrade plan with breaking change analysis"
Switch to Agent mode:
@src"Analyze code for security anti-patterns:- Hardcoded secrets- Unsafe regex (ReDoS)- Path traversal vulnerabilities- Command injection risks- Unsafe deserialization- Missing input validationGenerate security report with examples"
Example vulnerability report:
export interface SecurityVulnerability { severity: 'critical' | 'high' | 'medium' | 'low'; type: string; file: string; line: number; description: string; impact: string; recommendation: string; example?: string;}
// Example findings:const vulnerabilities: SecurityVulnerability[] = [ { severity: 'critical', type: 'SQL Injection', file: 'src/api/users.ts', line: 45, description: 'User input directly concatenated in SQL query', impact: 'Attacker can read/modify/delete entire database', recommendation: 'Use parameterized queries', example: ` // Vulnerable: const query = \`SELECT * FROM users WHERE id = \${userId}\`;
// Fixed: const query = 'SELECT * FROM users WHERE id = ?'; db.query(query, [userId]); ` }, { severity: 'high', type: 'Exposed Secret', file: 'src/config.ts', line: 12, description: 'API key hardcoded in source', impact: 'Attacker can access third-party services', recommendation: 'Use environment variables', example: ` // Vulnerable: const API_KEY = 'sk_live_abcd1234';
// Fixed: const API_KEY = process.env.API_KEY; ` }];
"Implement secure authentication system:- JWT with proper expiration- Refresh token rotation- Multi-factor authentication- Rate limiting on login- Account lockout mechanism- Secure password reset flowFollow OWASP guidelines"
Example secure auth implementation:
import bcrypt from 'bcrypt';import jwt from 'jsonwebtoken';import speakeasy from 'speakeasy';import { RateLimiter } from './rate-limiter';
export class SecureAuthService { private readonly saltRounds = 12; private readonly loginLimiter = new RateLimiter({ windowMs: 15 * 60 * 1000, // 15 minutes max: 5, // 5 attempts skipSuccessfulRequests: true });
async register(email: string, password: string) { // Validate password strength this.validatePasswordStrength(password);
// Check for compromised passwords await this.checkPwnedPassword(password);
// Hash password with bcrypt const hashedPassword = await bcrypt.hash(password, this.saltRounds);
// Generate 2FA secret const secret = speakeasy.generateSecret();
// Store user with hashed password const user = await db.user.create({ data: { email, password: hashedPassword, totpSecret: this.encrypt(secret.base32), isEmailVerified: false, createdAt: new Date() } });
// Send verification email await this.sendVerificationEmail(user);
return { userId: user.id, qrCode: secret.otpauth_url }; }
async login(email: string, password: string, totpToken?: string, ip?: string) { // Check rate limit await this.loginLimiter.check(email, ip);
try { // Get user with timing-safe comparison const user = await this.getUserByEmail(email);
if (!user || !(await bcrypt.compare(password, user.password))) { // Same error for both cases (prevents user enumeration) await this.loginLimiter.penalty(email, ip); throw new AuthError('Invalid credentials'); }
// Check account status if (user.lockedUntil && user.lockedUntil > new Date()) { throw new AuthError('Account temporarily locked'); }
// Verify 2FA if enabled if (user.totpSecret) { if (!totpToken) { throw new AuthError('2FA token required'); }
const secret = this.decrypt(user.totpSecret); const verified = speakeasy.totp.verify({ secret, encoding: 'base32', token: totpToken, window: 2 });
if (!verified) { await this.loginLimiter.penalty(email, ip); throw new AuthError('Invalid 2FA token'); } }
// Generate tokens const { accessToken, refreshToken } = await this.generateTokens(user);
// Log successful login await this.logSecurityEvent({ type: 'login_success', userId: user.id, ip, userAgent: req.headers['user-agent'] });
return { accessToken, refreshToken, expiresIn: 900 // 15 minutes }; } catch (error) { // Log failed attempt await this.logSecurityEvent({ type: 'login_failed', email, ip, reason: error.message });
throw error; } }
private async generateTokens(user: User) { const tokenId = crypto.randomUUID();
// Short-lived access token const accessToken = jwt.sign( { sub: user.id, email: user.email, jti: tokenId, type: 'access' }, process.env.JWT_SECRET, { expiresIn: '15m', issuer: 'myapp.com', audience: 'myapp.com' } );
// Long-lived refresh token with rotation const refreshToken = jwt.sign( { sub: user.id, jti: crypto.randomUUID(), type: 'refresh', family: crypto.randomUUID() // Token family for rotation }, process.env.JWT_REFRESH_SECRET, { expiresIn: '30d' } );
// Store refresh token (hashed) await db.refreshToken.create({ data: { hashedToken: await this.hashToken(refreshToken), userId: user.id, family: tokenFamily, expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) } });
return { accessToken, refreshToken }; }}
"Create role-based access control (RBAC):- Define roles and permissions- Implement middleware for route protection- Add resource-level permissions- Create permission checking utilities- Implement attribute-based access control- Add audit logging for access"
"Implement secure session management:- Secure session storage- Session fixation prevention- Concurrent session limits- Session timeout handling- Device tracking- Logout from all devices"
@src/api"Add input validation to all endpoints:- Request body validation- Query parameter validation- File upload validation- Header validation- Prevent injection attacksUse schema validation library"
Example validation implementation:
import { z } from 'zod';import DOMPurify from 'isomorphic-dompurify';import validator from 'validator';
// Custom validatorsconst safeString = z.string().transform((val) => { // Remove null bytes val = val.replace(/\0/g, '');
// Sanitize HTML val = DOMPurify.sanitize(val, { ALLOWED_TAGS: [] });
return val.trim();});
const email = z.string().email().refine( (val) => validator.isEmail(val, { allow_utf8_local_part: false, require_tld: true }), 'Invalid email format');
const password = z.string() .min(12, 'Password must be at least 12 characters') .refine( (val) => /[A-Z]/.test(val) && /[a-z]/.test(val) && /[0-9]/.test(val) && /[^A-Za-z0-9]/.test(val), 'Password must contain uppercase, lowercase, number, and special character' );
// User registration schemaexport const userRegistrationSchema = z.object({ email, password, name: safeString.min(2).max(100), acceptTerms: z.boolean().refine((val) => val === true, 'Must accept terms')});
// SQL injection preventionexport const searchQuerySchema = z.object({ q: safeString .max(100) .refine( (val) => !/(union|select|insert|update|delete|drop|script|exec)/i.test(val), 'Invalid search query' ), page: z.coerce.number().int().positive().default(1), limit: z.coerce.number().int().min(1).max(100).default(20)});
// File upload validationexport const fileUploadSchema = z.object({ file: z.custom<File>() .refine((file) => file.size <= 5 * 1024 * 1024, 'File too large') .refine( (file) => ['image/jpeg', 'image/png', 'image/webp'].includes(file.type), 'Invalid file type' ) .refine( async (file) => { // Verify file content matches MIME type const buffer = await file.arrayBuffer(); const header = new Uint8Array(buffer).slice(0, 4);
// Check magic numbers const jpg = header[0] === 0xFF && header[1] === 0xD8; const png = header[0] === 0x89 && header[1] === 0x50; const webp = header[0] === 0x52 && header[1] === 0x49;
return jpg || png || webp; }, 'File content does not match type' )});
// Middleware for validationexport function validateRequest(schema: z.ZodSchema) { return async (req: Request, res: Response, next: NextFunction) => { try { const validated = await schema.parseAsync({ ...req.body, ...req.query, ...req.params });
// Replace request data with validated/sanitized data req.body = validated; next(); } catch (error) { if (error instanceof z.ZodError) { res.status(400).json({ error: 'Validation failed', details: error.errors.map(e => ({ field: e.path.join('.'), message: e.message })) }); } else { next(error); } } };}
"Implement output encoding:- HTML entity encoding- JSON encoding- URL encoding- SQL identifier escaping- Command line escaping- Prevent XSS attacks"
"Implement CSP headers:- Define source allowlists- Prevent inline scripts- Block unsafe eval- Report violations- Implement nonce-based CSP- Add upgrade-insecure-requests"
"Implement data encryption:- Encrypt sensitive data at rest- Implement field-level encryption- Secure key management- Encrypt data in transit- Implement crypto best practices- Add encryption key rotation"
Example encryption service:
import crypto from 'crypto';import { KeyManagementService } from './kms';
export class EncryptionService { private readonly algorithm = 'aes-256-gcm'; private readonly kms = new KeyManagementService();
async encryptField(plaintext: string, context?: string): Promise<EncryptedData> { // Get or generate data encryption key const dataKey = await this.kms.generateDataKey();
// Generate IV const iv = crypto.randomBytes(16);
// Create cipher const cipher = crypto.createCipheriv( this.algorithm, dataKey.plaintext, iv );
// Add authenticated data if provided if (context) { cipher.setAAD(Buffer.from(context, 'utf8')); }
// Encrypt const encrypted = Buffer.concat([ cipher.update(plaintext, 'utf8'), cipher.final() ]);
// Get auth tag const authTag = cipher.getAuthTag();
return { ciphertext: encrypted.toString('base64'), iv: iv.toString('base64'), authTag: authTag.toString('base64'), keyId: dataKey.keyId, algorithm: this.algorithm, context }; }
async decryptField(encryptedData: EncryptedData): Promise<string> { // Get decryption key const dataKey = await this.kms.decryptDataKey( encryptedData.keyId, encryptedData.encryptedKey );
// Create decipher const decipher = crypto.createDecipheriv( encryptedData.algorithm, dataKey, Buffer.from(encryptedData.iv, 'base64') );
// Set auth tag decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'base64'));
// Add authenticated data if present if (encryptedData.context) { decipher.setAAD(Buffer.from(encryptedData.context, 'utf8')); }
// Decrypt const decrypted = Buffer.concat([ decipher.update(Buffer.from(encryptedData.ciphertext, 'base64')), decipher.final() ]);
return decrypted.toString('utf8'); }
// Searchable encryption for database queries async encryptSearchable(plaintext: string): Promise<SearchableEncrypted> { const encrypted = await this.encryptField(plaintext);
// Generate blind index for searching const blindIndex = crypto .createHmac('sha256', await this.kms.getBlindIndexKey()) .update(plaintext.toLowerCase()) .digest('hex');
return { ...encrypted, blindIndex }; }}
// Prisma middleware for automatic encryptionexport function encryptionMiddleware() { return async (params, next) => { // Encrypt on create/update if (params.action === 'create' || params.action === 'update') { if (params.args.data?.ssn) { params.args.data.ssn = await encryptionService.encryptField( params.args.data.ssn ); } }
const result = await next(params);
// Decrypt on read if (params.action === 'findUnique' || params.action === 'findFirst') { if (result?.ssn) { result.ssn = await encryptionService.decryptField(result.ssn); } }
return result; };}
"Implement secure data storage:- Separate PII from other data- Implement data retention policies- Secure backup procedures- Data anonymization- Audit trail for data access- Implement right to be forgotten"
"Secure all communications:- Enforce HTTPS everywhere- Implement certificate pinning- Secure WebSocket connections- API authentication- Request signing- Prevent man-in-the-middle attacks"
"Create security test suite:- SQL injection tests- XSS attack tests- CSRF tests- Authentication bypass tests- Authorization tests- API security testsInclude in CI/CD pipeline"
Example security tests:
describe('SQL Injection Prevention', () => { const maliciousInputs = [ "'; DROP TABLE users; --", "1' OR '1'='1", "admin'--", "1' UNION SELECT * FROM users--", "1; UPDATE users SET role='admin'--" ];
test.each(maliciousInputs)( 'should prevent SQL injection with input: %s', async (input) => { const response = await request(app) .get('/api/users/search') .query({ q: input }) .expect(400);
expect(response.body.error).toBe('Validation failed');
// Verify database wasn't affected const userCount = await db.user.count(); expect(userCount).toBeGreaterThan(0); } );});
describe('XSS Prevention', () => { const xssPayloads = [ '<script>alert("XSS")</script>', '<img src=x onerror=alert("XSS")>', '<svg onload=alert("XSS")>', 'javascript:alert("XSS")', '<iframe src="javascript:alert(\'XSS\')"></iframe>' ];
test.each(xssPayloads)( 'should sanitize XSS payload: %s', async (payload) => { const response = await request(app) .post('/api/comments') .send({ content: payload }) .expect(201);
// Verify stored content is sanitized const comment = await db.comment.findUnique({ where: { id: response.body.id } });
expect(comment.content).not.toContain('<script>'); expect(comment.content).not.toContain('javascript:'); expect(comment.content).not.toContain('onerror='); } );});
"Implement security monitoring:- Failed login attempts- Suspicious activity patterns- File integrity monitoring- Vulnerability scanning- Intrusion detection- Real-time alerts"
"Create incident response system:- Automated threat detection- Incident classification- Response procedures- Evidence collection- User notification system- Recovery procedures"
Layer security controls:
// Multiple layers of protectionasync function secureEndpoint(req, res) { // Layer 1: Rate limiting await rateLimiter.check(req);
// Layer 2: Authentication const user = await authenticate(req);
// Layer 3: Authorization await authorize(user, 'resource:read');
// Layer 4: Input validation const validated = await validateInput(req.body);
// Layer 5: Business logic with security checks const result = await processRequest(validated, user);
// Layer 6: Output encoding res.json(encodeOutput(result));}
Build security in from the start:
// Secure defaultsconst secureConfig = { session: { httpOnly: true, secure: true, sameSite: 'strict', maxAge: 15 * 60 * 1000 // 15 minutes }, headers: { 'X-Frame-Options': 'DENY', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Strict-Transport-Security': 'max-age=31536000' }};
Minimize access and permissions:
// Database user with minimal permissionsCREATE USER 'app_user'@'localhost' IDENTIFIED BY 'strong_password';GRANT SELECT, INSERT, UPDATE ON myapp.* TO 'app_user'@'localhost';-- No DELETE, DROP, CREATE permissions
// API permissionsconst permissions = { user: ['profile:read', 'profile:update'], admin: ['users:read', 'users:update', 'users:delete'], service: ['data:read'] // Service accounts get minimal access};
Problem: User input executed as code
Solution:
// Always use parameterized queriesconst user = await db.query( 'SELECT * FROM users WHERE email = ?', [email]);
// Validate and sanitize all inputconst validated = schema.parse(userInput);
// Use ORM with built-in protectionconst user = await prisma.user.findUnique({ where: { email }});
Problem: Weak authentication implementation
Solution:
// Implement proper password policiesconst strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{12,}$/;
// Use secure session managementreq.session.regenerate(); // Prevent fixation
// Implement MFAconst verified = speakeasy.totp.verify({ secret: user.totpSecret, token: userToken});
Problem: Unencrypted sensitive data
Solution:
// Encrypt at restconst encrypted = await encrypt(sensitiveData);
// Use HTTPS everywhereapp.use(enforceHTTPS());
// Don't log sensitive datalogger.info('User login', { userId: user.id, // Don't log: password, ssn, etc.});
Advanced security implementations:
Zero Trust Architecture
Advanced Threat Protection
Compliance Automation
Your security implementation succeeds when:
Teams implementing these practices report:
Before deploying:
You’ve mastered security implementation. Ready for more?
Penetration Testing
Learn ethical hacking techniques
Security Architecture
Design secure systems from scratch
Compliance Automation
Automate compliance processes
Continue to Documentation Generation →