audit-expert

安装量: 40
排名: #17840

安装

npx skills add https://github.com/personamanagmentlayer/pcl --skill audit-expert

Expert guidance for security auditing, compliance assessments, code reviews, vulnerability assessments, and regulatory compliance (SOC 2, GDPR, HIPAA, PCI-DSS).

Core Concepts

Audit Types

  • Security Audit: Vulnerability assessment, penetration testing

  • Code Audit: Code review, static analysis, security patterns

  • Compliance Audit: SOC 2, GDPR, HIPAA, PCI-DSS, ISO 27001

  • Infrastructure Audit: Configuration review, access control

  • Process Audit: SDLC, change management, incident response

Audit Frameworks

  • OWASP ASVS (Application Security Verification Standard)

  • NIST Cybersecurity Framework

  • CIS Controls

  • ISO 27001/27002

  • SOC 2 Trust Service Criteria

Audit Process

  • Planning and scoping

  • Information gathering

  • Vulnerability identification

  • Risk assessment

  • Reporting

  • Remediation tracking

  • Follow-up verification

Security Code Review

Authentication Review

// ❌ Issues to flag
class AuthService {
  // Issue 1: Weak password requirements
  validatePassword(password) {
    return password.length >= 6; // Too short!
  }

  // Issue 2: Password stored in plaintext
  async createUser(email, password) {
    await db.users.create({ email, password }); // No hashing!
  }

  // Issue 3: Timing attack vulnerability
  async login(email, password) {
    const user = await db.users.findOne({ email });
    if (!user) return null;

    // Direct comparison reveals timing
    if (user.password === password) {
      return user;
    }
    return null;
  }

  // Issue 4: No rate limiting
  // Issue 5: No MFA support
  // Issue 6: Predictable session tokens
  generateSessionToken() {
    return Math.random().toString(36); // Not cryptographically secure!
  }
}

// ✅ Secure implementation
const bcrypt = require('bcrypt');
const crypto = require('crypto');

class SecureAuthService {
  // Strong password validation
  validatePassword(password) {
    const minLength = 12;
    const hasUppercase = /[A-Z]/.test(password);
    const hasLowercase = /[a-z]/.test(password);
    const hasNumber = /[0-9]/.test(password);
    const hasSpecial = /[^A-Za-z0-9]/.test(password);

    return password.length >= minLength &&
           hasUppercase && hasLowercase &&
           hasNumber && hasSpecial;
  }

  // Secure password hashing
  async hashPassword(password) {
    const saltRounds = 12;
    return await bcrypt.hash(password, saltRounds);
  }

  async createUser(email, password) {
    if (!this.validatePassword(password)) {
      throw new Error('Password does not meet requirements');
    }

    const passwordHash = await this.hashPassword(password);
    await db.users.create({
      email: email.toLowerCase(),
      passwordHash
    });
  }

  // Constant-time comparison with rate limiting
  async login(email, password) {
    // Check rate limit
    const attempts = await this.getLoginAttempts(email);
    if (attempts > 5) {
      throw new Error('Too many login attempts. Try again later.');
    }

    const user = await db.users.findOne({
      email: email.toLowerCase()
    });

    // Always hash password even if user not found (timing attack prevention)
    const isValid = user ?
      await bcrypt.compare(password, user.passwordHash) :
      await bcrypt.compare(password, '$2b$12$dummyhash');

    if (!user || !isValid) {
      await this.recordFailedAttempt(email);
      throw new Error('Invalid credentials');
    }

    await this.clearLoginAttempts(email);
    return user;
  }

  // Cryptographically secure tokens
  generateSessionToken() {
    return crypto.randomBytes(32).toString('hex');
  }

  // MFA support
  async verifyMFA(user, token) {
    const speakeasy = require('speakeasy');
    return speakeasy.totp.verify({
      secret: user.mfaSecret,
      encoding: 'base32',
      token,
      window: 2
    });
  }
}

SQL Injection Review

// Audit checklist for SQL injection:
// 1. Are all queries parameterized?
// 2. Is user input sanitized?
// 3. Are ORM features used correctly?
// 4. Are stored procedures parameterized?

// ❌ Vulnerable patterns to flag
async function searchUsers(name) {
  // Issue: String concatenation
  const query = `SELECT * FROM users WHERE name = '${name}'`;
  return await db.query(query);
}

async function updateUser(id, data) {
  // Issue: Dynamic column names not validated
  const columns = Object.keys(data).join(', ');
  const query = `UPDATE users SET ${columns} WHERE id = ${id}`;
  return await db.query(query);
}

// ❌ ORM misuse
async function findUsers(filters) {
  // Issue: Raw WHERE clause from user input
  return await User.findAll({
    where: db.literal(filters.where)
  });
}

// ✅ Secure patterns
async function searchUsers(name) {
  // Parameterized query
  return await db.query(
    'SELECT * FROM users WHERE name = ?',
    [name]
  );
}

async function updateUser(id, data) {
  // Whitelist allowed columns
  const allowedColumns = ['name', 'email', 'bio'];
  const updates = {};

  for (const [key, value] of Object.entries(data)) {
    if (allowedColumns.includes(key)) {
      updates[key] = value;
    }
  }

  return await User.update(updates, {
    where: { id }
  });
}

async function findUsers(filters) {
  // Use ORM query builder
  return await User.findAll({
    where: {
      name: { [Op.like]: `%${filters.name}%` },
      active: true
    }
  });
}

Authorization Review

// Audit checklist:
// 1. Is authentication checked before authorization?
// 2. Are resource ownership checks present?
// 3. Is role-based access control implemented?
// 4. Are there direct object reference vulnerabilities?

// ❌ Insecure patterns
app.delete('/api/posts/:id', authenticate, async (req, res) => {
  // Issue: No authorization check!
  await Post.delete(req.params.id);
  res.status(204).send();
});

app.get('/api/documents/:id', async (req, res) => {
  // Issue: No authentication at all!
  const doc = await Document.findById(req.params.id);
  res.json(doc);
});

// ✅ Secure patterns
const authorize = (resource) => async (req, res, next) => {
  const item = await db[resource].findById(req.params.id);

  if (!item) {
    return res.status(404).json({ error: 'Not found' });
  }

  // Check ownership or admin role
  if (item.userId !== req.user.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  req.resource = item;
  next();
};

app.delete('/api/posts/:id',
  authenticate,
  authorize('posts'),
  async (req, res) => {
    await req.resource.delete();
    res.status(204).send();
  }
);

// Role-based access control
const requireRole = (...roles) => (req, res, next) => {
  if (!req.user || !roles.includes(req.user.role)) {
    return res.status(403).json({ error: 'Insufficient permissions' });
  }
  next();
};

app.post('/api/admin/users',
  authenticate,
  requireRole('admin'),
  async (req, res) => {
    // Admin-only endpoint
  }
);

XSS and Output Encoding Review

// Audit checklist:
// 1. Is user input escaped in HTML context?
// 2. Is Content-Security-Policy header set?
// 3. Are dangerous functions (eval, innerHTML) avoided?
// 4. Is templating engine auto-escaping enabled?

// ❌ Vulnerable patterns
app.get('/search', (req, res) => {
  // Issue: No escaping
  res.send(`<h1>Results for: ${req.query.q}</h1>`);
});

app.post('/comment', async (req, res) => {
  // Issue: Storing unsanitized HTML
  await Comment.create({
    text: req.body.comment,
    html: req.body.comment // Dangerous!
  });
});

// Client-side issues
function displayComment(comment) {
  // Issue: Using innerHTML
  document.getElementById('comment').innerHTML = comment;

  // Issue: Using eval
  eval(comment);
}

// ✅ Secure patterns
const escape = require('escape-html');

app.get('/search', (req, res) => {
  res.send(`<h1>Results for: ${escape(req.query.q)}</h1>`);
});

// Or use templating with auto-escape
app.get('/search', (req, res) => {
  res.render('search', { query: req.query.q }); // Auto-escaped
});

// Content Security Policy
app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy',
    "default-src 'self'; " +
    "script-src 'self'; " +
    "style-src 'self' 'unsafe-inline'; " +
    "img-src 'self' data: https:;"
  );
  next();
});

// Client-side: Use textContent
function displayComment(comment) {
  document.getElementById('comment').textContent = comment;
}

Compliance Auditing

GDPR Compliance Checklist

// GDPR Requirements Audit

// 1. Lawful Basis for Processing
// ✓ Explicit consent obtained
// ✓ Purpose clearly stated
// ✓ Option to withdraw consent

// 2. Data Minimization
// Review: Are we collecting only necessary data?
async function createUser(data) {
  // ❌ Collecting too much
  const user = {
    email: data.email,
    password: data.password,
    ssn: data.ssn,              // Unnecessary!
    medicalHistory: data.medical, // Unnecessary!
    location: data.location      // May be unnecessary
  };

  // ✅ Only essential data
  const user = {
    email: data.email,
    passwordHash: await hashPassword(data.password)
  };
}

// 3. Right to Access (Subject Access Request)
app.get('/api/gdpr/data', authenticate, async (req, res) => {
  const userData = {
    personalInfo: await User.findById(req.user.id),
    posts: await Post.findByUserId(req.user.id),
    comments: await Comment.findByUserId(req.user.id),
    loginHistory: await LoginHistory.findByUserId(req.user.id)
  };

  res.json(userData);
});

// 4. Right to Erasure (Right to be Forgotten)
app.delete('/api/gdpr/delete-account', authenticate, async (req, res) => {
  const userId = req.user.id;

  await db.transaction(async (tx) => {
    // Anonymize or delete personal data
    await User.anonymize(userId, tx);
    await Post.anonymizeByUser(userId, tx);
    await Comment.anonymizeByUser(userId, tx);

    // Keep audit logs (legal requirement)
    await AuditLog.create({
      action: 'account_deletion',
      userId,
      timestamp: new Date()
    }, tx);
  });

  res.status(204).send();
});

// 5. Right to Data Portability
app.get('/api/gdpr/export', authenticate, async (req, res) => {
  const data = await exportUserData(req.user.id);

  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Disposition', 'attachment; filename="my-data.json"');
  res.json(data);
});

// 6. Breach Notification (72 hours)
async function handleDataBreach(breach) {
  // Log breach
  await SecurityIncident.create({
    type: 'data_breach',
    severity: breach.severity,
    affectedUsers: breach.userIds.length,
    detectedAt: new Date()
  });

  // Notify authorities within 72 hours if high risk
  if (breach.severity === 'high') {
    await notifyDataProtectionAuthority(breach);
  }

  // Notify affected users
  for (const userId of breach.userIds) {
    await notifyUserOfBreach(userId, breach);
  }
}

// 7. Privacy by Design
// - Encryption at rest and in transit
// - Access controls
// - Audit logging
// - Data retention policies

// 8. Data Processing Agreement
// - Document third-party processors
// - Ensure processor compliance
// - Review contracts

SOC 2 Compliance Audit

// SOC 2 Trust Service Criteria

// 1. Security - Access Control class AccessControlAudit { async auditUserAccess() { // Review user permissions const users = await User.findAll(); const issues = [];

for (const user of users) {
  // Check for overprivileged users
  if (user.role === 'admin' && !user.adminJustification) {
    issues.push({
      type: 'excessive_privilege',
      user: user.email,
      message: 'Admin access without justification'
    });
  }

  // Check for inactive users with access
  const daysSinceLogin = daysBetween(user.lastLoginAt, new Date());
  if (daysSinceLogin > 90) {
    issues.push({
      type: 'stale_access',
      user: user.email,
      message: `No login for ${daysSinceLogin} days`
    });
  }
}

return issues;

}

async auditAPIKeys() { const apiKeys = await APIKey.findAll(); const issues = [];

for (const key of apiKeys) {
  // Check for keys without expiration
  if (!key.expiresAt) {
    issues.push({
      type: 'no_expiration',
      keyId: key.id,
      message: 'API key has no expiration'
    });
  }

  // Check for unused keys
  if (!key.lastUsedAt ||
      daysBetween(key.lastUsedAt, new Date()) > 90) {
    issues.push({
      type: 'unused_key',
      keyId: key.id,
      message: 'API key not used in 90 days'
    });
  }
}

return issues;

} }

// 2. Availability - Monitoring class

返回排行榜