Security Hardening Project
Security Hardening Project
Security hardening is the systematic process of reducing vulnerabilities and strengthening defenses across your entire application stack. This lesson guides you through a comprehensive security audit, implementing defense-in-depth strategies, and establishing ongoing security practices. We'll build a complete security framework that protects your application against modern threats while maintaining usability and performance.
Complete Security Audit Walkthrough
A thorough security audit systematically examines every layer of your application, from infrastructure to code to processes. This comprehensive approach ensures no vulnerability goes unnoticed.
class SecurityAudit {\n constructor() {\n this.findings = [];\n this.severity = { critical: 0, high: 0, medium: 0, low: 0 };\n }\n\n async runFullAudit() {\n console.log('Starting comprehensive security audit...');\n \n await this.auditAuthentication();\n await this.auditAuthorization();\n await this.auditInputValidation();\n await this.auditDataProtection();\n await this.auditSessionManagement();\n await this.auditSecurityHeaders();\n await this.auditDependencies();\n await this.auditInfrastructure();\n \n return this.generateReport();\n }\n\n async auditAuthentication() {\n const checks = [\n {\n name: 'Password Complexity',\n test: () => this.checkPasswordPolicy(),\n severity: 'high'\n },\n {\n name: 'Multi-Factor Authentication',\n test: () => this.checkMFAImplementation(),\n severity: 'critical'\n },\n {\n name: 'Brute Force Protection',\n test: () => this.checkRateLimiting(),\n severity: 'high'\n },\n {\n name: 'Secure Password Reset',\n test: () => this.checkPasswordResetFlow(),\n severity: 'high'\n },\n {\n name: 'Account Lockout Policy',\n test: () => this.checkLockoutPolicy(),\n severity: 'medium'\n }\n ];\n\n for (const check of checks) {\n try {\n const result = await check.test();\n if (!result.passed) {\n this.addFinding(\n 'Authentication',\n check.name,\n result.message,\n check.severity\n );\n }\n } catch (error) {\n this.addFinding(\n 'Authentication',\n check.name,\n `Test failed: ${error.message}`,\n 'high'\n );\n }\n }\n }\n\n async auditAuthorization() {\n const checks = [\n {\n name: 'RBAC Implementation',\n test: () => this.checkRBACCompleteness(),\n severity: 'critical'\n },\n {\n name: 'Privilege Escalation',\n test: () => this.testPrivilegeEscalation(),\n severity: 'critical'\n },\n {\n name: 'IDOR Vulnerabilities',\n test: () => this.testIDORVulnerabilities(),\n severity: 'high'\n },\n {\n name: 'API Authorization',\n test: () => this.checkAPIAuthorization(),\n severity: 'high'\n }\n ];\n\n for (const check of checks) {\n const result = await check.test();\n if (!result.passed) {\n this.addFinding(\n 'Authorization',\n check.name,\n result.message,\n check.severity\n );\n }\n }\n }\n\n async auditInputValidation() {\n const checks = [\n {\n name: 'XSS Protection',\n test: () => this.testXSSVulnerabilities(),\n severity: 'critical'\n },\n {\n name: 'SQL Injection',\n test: () => this.testSQLInjection(),\n severity: 'critical'\n },\n {\n name: 'Command Injection',\n test: () => this.testCommandInjection(),\n severity: 'critical'\n },\n {\n name: 'File Upload Security',\n test: () => this.checkFileUploadSecurity(),\n severity: 'high'\n },\n {\n name: 'Input Sanitization',\n test: () => this.checkInputSanitization(),\n severity: 'high'\n }\n ];\n\n for (const check of checks) {\n const result = await check.test();\n if (!result.passed) {\n this.addFinding(\n 'Input Validation',\n check.name,\n result.message,\n check.severity\n );\n }\n }\n }\n\n addFinding(category, name, message, severity) {\n this.findings.push({\n category,\n name,\n message,\n severity,\n timestamp: new Date().toISOString()\n });\n this.severity[severity]++;\n }\n\n generateReport() {\n const report = {\n summary: {\n totalFindings: this.findings.length,\n critical: this.severity.critical,\n high: this.severity.high,\n medium: this.severity.medium,\n low: this.severity.low,\n riskScore: this.calculateRiskScore()\n },\n findings: this.groupFindingsByCategory(),\n recommendations: this.generateRecommendations()\n };\n\n return report;\n }\n\n calculateRiskScore() {\n return (\n this.severity.critical * 10 +\n this.severity.high * 5 +\n this.severity.medium * 2 +\n this.severity.low * 1\n );\n }\n\n groupFindingsByCategory() {\n const grouped = {};\n this.findings.forEach(finding => {\n if (!grouped[finding.category]) {\n grouped[finding.category] = [];\n }\n grouped[finding.category].push(finding);\n });\n return grouped;\n }\n\n generateRecommendations() {\n const recommendations = [];\n \n if (this.severity.critical > 0) {\n recommendations.push({\n priority: 'IMMEDIATE',\n action: 'Address all critical vulnerabilities before deployment'\n });\n }\n \n if (this.severity.high > 5) {\n recommendations.push({\n priority: 'HIGH',\n action: 'Schedule dedicated sprint for security remediation'\n });\n }\n \n return recommendations;\n }\n}\n\n// Usage\nconst audit = new SecurityAudit();\nconst report = await audit.runFullAudit();\nconsole.log(JSON.stringify(report, null, 2));Implementing Security Automation Tools
Security automation ensures continuous protection without manual intervention. Integrating security tools into your CI/CD pipeline catches vulnerabilities early when they're cheapest to fix.
// .github/workflows/security.yml\nname: Security Scanning\n\non:\n push:\n branches: [ main, develop ]\n pull_request:\n branches: [ main ]\n schedule:\n - cron: '0 0 * * 0' # Weekly scan\n\njobs:\n sast:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n \n - name: Run Semgrep\n uses: returntocorp/semgrep-action@v1\n with:\n config: >\n p/security-audit\n p/owasp-top-ten\n p/javascript\n p/typescript\n \n - name: SonarCloud Scan\n uses: SonarSource/sonarcloud-github-action@master\n env:\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}\n\n dependency-check:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n \n - name: Run npm audit\n run: npm audit --audit-level=high\n \n - name: Run Snyk\n uses: snyk/actions/node@master\n env:\n SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}\n with:\n command: test\n args: --severity-threshold=high\n\n secrets-scan:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n with:\n fetch-depth: 0\n \n - name: TruffleHog Scan\n uses: trufflesecurity/trufflehog@main\n with:\n path: ./\n base: ${{ github.event.repository.default_branch }}\n head: HEAD\n\n container-scan:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n \n - name: Build Docker image\n run: docker build -t myapp:${{ github.sha }} .\n \n - name: Run Trivy vulnerability scanner\n uses: aquasecurity/trivy-action@master\n with:\n image-ref: myapp:${{ github.sha }}\n format: 'sarif'\n output: 'trivy-results.sarif'\n \n - name: Upload results to GitHub Security\n uses: github/codeql-action/upload-sarif@v2\n with:\n sarif_file: 'trivy-results.sarif'// security-scan.js\nconst ZAP = require('zaproxy');\nconst fs = require('fs');\n\nclass DynamicSecurityScanner {\n constructor(config) {\n this.zap = new ZAP({\n apiKey: config.zapApiKey,\n proxy: config.proxy || 'http://localhost:8080'\n });\n this.targetUrl = config.targetUrl;\n this.scanPolicy = config.scanPolicy || 'Default Policy';\n }\n\n async runScan() {\n console.log(`Starting DAST scan on ${this.targetUrl}`);\n \n try {\n // Spider the application\n console.log('Phase 1: Spidering...');\n const spiderScanId = await this.spider();\n await this.waitForScan(spiderScanId, 'spider');\n \n // Active scan\n console.log('Phase 2: Active scanning...');\n const activeScanId = await this.activeScan();\n await this.waitForScan(activeScanId, 'ascan');\n \n // Generate report\n console.log('Phase 3: Generating report...');\n const report = await this.generateReport();\n \n return report;\n } catch (error) {\n console.error('DAST scan failed:', error);\n throw error;\n }\n }\n\n async spider() {\n const response = await this.zap.spider.scan({\n url: this.targetUrl,\n maxChildren: 10,\n recurse: true\n });\n return response.scan;\n }\n\n async activeScan() {\n const response = await this.zap.ascan.scan({\n url: this.targetUrl,\n recurse: true,\n inScopeOnly: false,\n scanPolicyName: this.scanPolicy\n });\n return response.scan;\n }\n\n async waitForScan(scanId, scanType) {\n let progress = 0;\n while (progress < 100) {\n await new Promise(resolve => setTimeout(resolve, 5000));\n const status = await this.zap[scanType].status(scanId);\n progress = parseInt(status.status);\n console.log(`${scanType} progress: ${progress}%`);\n }\n }\n\n async generateReport() {\n const alerts = await this.zap.core.alerts({\n baseurl: this.targetUrl\n });\n \n const report = {\n targetUrl: this.targetUrl,\n timestamp: new Date().toISOString(),\n summary: this.summarizeAlerts(alerts.alerts),\n alerts: alerts.alerts,\n passed: !alerts.alerts.some(a => a.risk === 'High' || a.risk === 'Critical')\n };\n \n // Save report\n fs.writeFileSync(\n `dast-report-${Date.now()}.json`,\n JSON.stringify(report, null, 2)\n );\n \n return report;\n }\n\n summarizeAlerts(alerts) {\n const summary = {\n total: alerts.length,\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n informational: 0\n };\n \n alerts.forEach(alert => {\n const risk = alert.risk.toLowerCase();\n if (summary.hasOwnProperty(risk)) {\n summary[risk]++;\n }\n });\n \n return summary;\n }\n}\n\n// Usage in CI/CD\nconst scanner = new DynamicSecurityScanner({\n zapApiKey: process.env.ZAP_API_KEY,\n targetUrl: process.env.TARGET_URL || 'http://localhost:3000',\n scanPolicy: 'OWASP Top 10'\n});\n\nconst report = await scanner.runScan();\n\nif (!report.passed) {\n console.error('Security scan failed! High-risk vulnerabilities detected.');\n process.exit(1);\n}Penetration Testing Basics
Penetration testing simulates real-world attacks to identify vulnerabilities before malicious actors do. While comprehensive pentesting requires specialized expertise, developers should understand basic testing techniques.
class PenetrationTestingSuite {\n constructor(targetUrl) {\n this.targetUrl = targetUrl;\n this.findings = [];\n }\n\n async runBasicTests() {\n console.log('Starting basic penetration tests...');\n \n await this.testAuthenticationBypass();\n await this.testSQLInjection();\n await this.testXSS();\n await this.testCSRF();\n await this.testDirectoryTraversal();\n await this.testSessionFixation();\n await this.testSecurityHeaders();\n \n return this.generateFindings();\n }\n\n async testAuthenticationBypass() {\n const tests = [\n // Test 1: Empty password\n { username: 'admin', password: '' },\n // Test 2: SQL injection in username\n { username: \"admin' OR '1'='1\", password: 'anything' },\n // Test 3: Default credentials\n { username: 'admin', password: 'admin' },\n { username: 'admin', password: 'password' },\n // Test 4: Username enumeration\n { username: 'nonexistent_user_12345', password: 'test' }\n ];\n\n for (const test of tests) {\n try {\n const response = await fetch(`${this.targetUrl}/api/login`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(test)\n });\n\n if (response.ok) {\n this.addFinding(\n 'Authentication Bypass',\n 'CRITICAL',\n `Successfully bypassed authentication with: ${JSON.stringify(test)}`\n );\n }\n\n // Check for username enumeration\n const responseText = await response.text();\n if (responseText.includes('user not found') || responseText.includes('incorrect password')) {\n this.addFinding(\n 'Username Enumeration',\n 'MEDIUM',\n 'Login endpoint reveals whether username exists'\n );\n }\n } catch (error) {\n console.log(`Test failed: ${error.message}`);\n }\n }\n }\n\n async testSQLInjection() {\n const payloads = [\n \"1' OR '1'='1\",\n \"1'; DROP TABLE users--\",\n \"1' UNION SELECT NULL, username, password FROM users--\",\n \"1' AND 1=0 UNION ALL SELECT NULL, CONCAT(username, ':', password), NULL FROM users--\"\n ];\n\n for (const payload of payloads) {\n try {\n const response = await fetch(\n `${this.targetUrl}/api/users?id=${encodeURIComponent(payload)}`\n );\n\n const data = await response.text();\n \n // Check for SQL error messages\n if (data.match(/SQL syntax|mysql_fetch|pg_query|ORA-\d{5}|SQLite/i)) {\n this.addFinding(\n 'SQL Injection',\n 'CRITICAL',\n `SQL error exposed with payload: ${payload}`\n );\n }\n\n // Check for successful injection\n if (response.ok && data.length > 1000) {\n this.addFinding(\n 'Potential SQL Injection',\n 'HIGH',\n `Suspicious response size with payload: ${payload}`\n );\n }\n } catch (error) {\n console.log(`SQL injection test failed: ${error.message}`);\n }\n }\n }\n\n async testXSS() {\n const payloads = [\n '<script>alert(document.cookie)</script>',\n '<img src=x onerror=alert(document.domain)>',\n '<svg/onload=alert(1)>',\n 'javascript:alert(document.cookie)',\n '<iframe src=javascript:alert(1)></iframe>'\n ];\n\n for (const payload of payloads) {\n try {\n // Test reflected XSS\n const response = await fetch(\n `${this.targetUrl}/search?q=${encodeURIComponent(payload)}`\n );\n\n const html = await response.text();\n \n // Check if payload is reflected unescaped\n if (html.includes(payload)) {\n this.addFinding(\n 'Reflected XSS',\n 'HIGH',\n `Unescaped input reflection with payload: ${payload}`\n );\n }\n\n // Test stored XSS\n const postResponse = await fetch(`${this.targetUrl}/api/comments`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ comment: payload })\n });\n\n if (postResponse.ok) {\n // Retrieve and check if payload is stored\n const getResponse = await fetch(`${this.targetUrl}/api/comments`);\n const comments = await getResponse.text();\n \n if (comments.includes(payload)) {\n this.addFinding(\n 'Stored XSS',\n 'CRITICAL',\n `Payload stored without sanitization: ${payload}`\n );\n }\n }\n } catch (error) {\n console.log(`XSS test failed: ${error.message}`);\n }\n }\n }\n\n async testCSRF() {\n try {\n // Test if state-changing operation works without CSRF token\n const response = await fetch(`${this.targetUrl}/api/settings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email: 'attacker@evil.com' }),\n credentials: 'include'\n });\n\n if (response.ok) {\n this.addFinding(\n 'CSRF Vulnerability',\n 'HIGH',\n 'State-changing operation succeeds without CSRF token'\n );\n }\n } catch (error) {\n console.log(`CSRF test failed: ${error.message}`);\n }\n }\n\n async testDirectoryTraversal() {\n const payloads = [\n '../../../etc/passwd',\n '..\\..\\..\\windows\\system32\\config\\sam',\n '....//....//....//etc/passwd',\n '%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd'\n ];\n\n for (const payload of payloads) {\n try {\n const response = await fetch(\n `${this.targetUrl}/files?path=${encodeURIComponent(payload)}`\n );\n\n const content = await response.text();\n \n if (content.includes('root:x:') || content.includes('Administrator')) {\n this.addFinding(\n 'Directory Traversal',\n 'CRITICAL',\n `Sensitive file accessible with payload: ${payload}`\n );\n }\n } catch (error) {\n console.log(`Directory traversal test failed: ${error.message}`);\n }\n }\n }\n\n addFinding(vulnerability, severity, description) {\n this.findings.push({\n vulnerability,\n severity,\n description,\n timestamp: new Date().toISOString()\n });\n }\n\n generateFindings() {\n return {\n totalFindings: this.findings.length,\n criticalFindings: this.findings.filter(f => f.severity === 'CRITICAL').length,\n findings: this.findings,\n passed: this.findings.filter(f => f.severity === 'CRITICAL' || f.severity === 'HIGH').length === 0\n };\n }\n}\n\n// Usage\nconst pentest = new PenetrationTestingSuite('https://staging.example.com');\nconst results = await pentest.runBasicTests();\nconsole.log(JSON.stringify(results, null, 2));Incident Response Planning
Even with strong security measures, incidents can occur. A well-documented incident response plan minimizes damage and ensures rapid recovery.
1. Preparation Phase:
☐ Document all system assets and their criticality
☐ Establish incident response team with defined roles
☐ Set up secure communication channels
☐ Deploy monitoring and alerting systems
☐ Create backup and recovery procedures
☐ Establish relationships with external experts (forensics, legal)
2. Detection and Analysis:
☐ Define security events and incidents
☐ Establish severity classification (Critical/High/Medium/Low)
☐ Document indicators of compromise (IOCs)
☐ Create decision trees for incident classification
☐ Set up 24/7 monitoring and alerting
3. Containment Strategy:
☐ Short-term containment procedures (isolate affected systems)
☐ Long-term containment (temporary fixes while maintaining business operations)
☐ Evidence preservation protocols
☐ Communication protocols (internal and external)
4. Eradication and Recovery:
☐ Remove malware and close vulnerabilities
☐ Restore systems from clean backups
☐ Patch and harden systems
☐ Reset all credentials
☐ Monitor for re-infection
5. Post-Incident Activities:
☐ Document timeline and actions taken
☐ Conduct lessons-learned meeting
☐ Update security controls based on findings
☐ Update incident response procedures
☐ Share relevant information with community (anonymized)
Implementation:
Create a detailed incident response playbook for your organization. Include contact information, escalation procedures, communication templates, and specific technical steps for common incident types. Test the plan through tabletop exercises quarterly.
Security Documentation and Compliance
Comprehensive security documentation demonstrates due diligence and is essential for compliance with regulations and standards.
// security-documentation.md structure\n\n# Application Security Documentation\n\n## 1. Security Architecture\n- Network architecture diagram\n- Data flow diagrams\n- Trust boundaries and security zones\n- Authentication and authorization architecture\n\n## 2. Threat Model\n- Assets and their valuation\n- Threat actors and their capabilities\n- Attack vectors and threat scenarios\n- Risk assessment matrix\n\n## 3. Security Controls\n- Authentication mechanisms\n- Authorization and access control\n- Data encryption (at rest and in transit)\n- Input validation and output encoding\n- Session management\n- Security logging and monitoring\n- Incident detection and response\n\n## 4. Secure Development Practices\n- Security requirements in SDLC\n- Secure coding guidelines\n- Code review procedures\n- Security testing (SAST, DAST, penetration testing)\n- Dependency management\n- Security training requirements\n\n## 5. Compliance Requirements\n- GDPR compliance measures\n- PCI-DSS compliance (if applicable)\n- HIPAA compliance (if applicable)\n- SOC 2 controls\n- ISO 27001 alignment\n\n## 6. Data Protection\n- Data classification scheme\n- Data retention and disposal policies\n- Privacy impact assessments\n- Data breach response procedures\n\n## 7. Third-Party Security\n- Vendor security assessment procedures\n- Third-party risk management\n- Supply chain security\n\n## 8. Security Metrics\n- KPIs and security metrics\n- Vulnerability management metrics\n- Incident response metrics\n- Security training completion rates
Security hardening is an ongoing commitment, not a one-time project. By conducting comprehensive audits, implementing automated security tools, establishing incident response procedures, and maintaining thorough documentation, you create a robust security posture that evolves with emerging threats. The key is making security a continuous practice embedded in your development culture and processes.