CSSLP · Domain 4 · 14%

Triển khai an toàn

Secure Software Implementation

Viết code an toàn theo chuẩn CERT/OWASP: input validation, output encoding, injection prevention, memory safety, secure error handling, secrets management và dependency pinning.

Mục tiêu chương / Learning objectives

1. Lý thuyết cốt lõi / Core theory

1.1. Secure Coding Standards (CERT / OWASP / MISRA)

CERT Secure Coding Standards: bộ rules cho C/C++, Java, Python — phân loại theo severity (L1-L3) và remediation cost. Ví dụ CERT C Rule ERR34-C: "Detect errors when converting a string to a number" — phòng tránh undefined behavior khi dùng atoi() thay vì strtol(). OWASP Secure Coding Practices: checklist 13 categories (Input Validation, Output Encoding, Authentication, Session Management, Access Control, Cryptography, Error Handling, Data Protection, Communication Security, System Configuration, Database Security, File Management, Memory Management). MISRA C/C++: guidelines cho safety-critical systems (automotive, aviation) — prohibit undefined behavior, restrict dynamic memory allocation.

Secure coding là về defaults: Secure defaults nghĩa là code phải làm thêm thao tác để trở nên insecure. Ví dụ: parameterized query là default trong ORM — developer phải chủ động gọi raw query method mới có thể SQL inject. Ngược lại, string concatenation là insecure default — developer phải cố ý dùng parameterized để an toàn.

1.2. Input Validation & Output Encoding (Validation vs Encoding)

Input validation: validate ở server-side (client-side chỉ là UX, không phải security); dùng allowlist (whitelist) thay vì denylist (blacklist) — chấp nhận những gì biết là tốt, từ chối phần còn lại; canonicalization trước khi validate — normalize encoding (URL decode, Unicode normalization) để tránh bypass: ../ vs %2E%2E%2F vs ..%c0%af đều là path traversal; type checking + range checking + length checking.

Output encoding — encode đúng ngữ cảnh (context-aware encoding): HTML context → HTML entity encoding (<&lt;); JS context → JavaScript encoding; URL context → percent encoding; SQL context → parameterized queries (không encode, mà tách data khỏi query structure); LDAP → LDAP escape. Dùng thư viện chuẩn: OWASP Java Encoder, AntiXSS (.NET), DOMPurify (JS).

1.3. Injection Prevention Deep Dive (SQL / NoSQL / LDAP / XML / OS Command)

SQL injection: Parameterized queries / prepared statements là giải pháp duy nhất tin cậy. Stored procedures không đủ nếu vẫn dùng dynamic SQL bên trong. ORM không đủ nếu dùng raw query methods. NoSQL injection: MongoDB vulnerable khi nhận JSON input trực tiếp vào query operator ($where, $gt). Validate schema input với Joi/Zod. LDAP injection: escape special chars: ( ) * \ NUL. XML injection/XXE: disable external entity processing (DTD) trong XML parser — XXE (XML External Entity) có thể đọc /etc/passwd hoặc SSRF. OS command injection: không truyền user input vào shell command — dùng API trực tiếp thay vì shell (ví dụ: dùng subprocess(['ping', hostname]) với shell=False thay vì xây dựng command string).

1.4. Memory Management & Error Handling (Memory Safety & Secure Logging)

Memory safety (C/C++): buffer overflow — luôn kiểm tra bounds trước khi write; use-after-free — dùng smart pointers (std::unique_ptr, std::shared_ptr); integer overflow — kiểm tra trước khi cộng, dùng safe integer libraries; format string — không bao giờ dùng printf(user_input), luôn printf("%s", user_input). Ngôn ngữ memory-safe (Rust, Go, Java, Python) eliminates nhiều classes này nhưng vẫn có logic bugs.

Secure error handling: không trả về stack traces, exception details, internal paths, DB error messages cho client — attacker dùng để enumerate hệ thống; log đủ thông tin ở server-side (request ID, user ID, timestamp, action, result) nhưng không log passwords, session tokens, PII; log injection — sanitize user input trước khi log (attacker có thể inject fake log entries bằng newline characters).

1.5. Secrets Management & Dependency Security (Secrets & Dependencies)

Secrets management: KHÔNG bao giờ hardcode secrets trong source code — git history là permanent, ngay cả khi xóa file sau đó; dùng environment variables (cho simple cases), secret managers (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager) cho production; .gitignore file .env nhưng commit .env.example với placeholder values; scan pre-commit với TruffleHog, git-secrets, detect-secrets. Dependency pinning: pin exact versions trong lockfiles (package-lock.json, Pipfile.lock, go.sum) — floating versions (^1.2.3) có thể pull malicious update; review lockfile changes trong PRs.

2. Bài thực hành / Hands-on labs

🖥️ Nền tảng / Platform: Windows 11 · Ubuntu 22.04 LTS
🛠️ Công cụ / Tools: PowerShell 7 + TruffleHog · Bash + Bandit

Lab 1 — Secret Detection trong Git History (PowerShell)

OS: Windows 11 · Tool: PowerShell 7 + TruffleHog (hoặc regex scan).

# Scan codebase tìm hardcoded secrets bằng regex patterns
Write-Host "=== Secret Detection Scan ===" -ForegroundColor Yellow

# Pattern phổ biến cho secrets bị lộ
$patterns = @(
    '[A-Za-z0-9+/]{40,}={0,2}',        # Base64-encoded secrets (40+ chars)
    'AKIA[0-9A-Z]{16}',                 # AWS Access Key ID
    'ghp_[A-Za-z0-9]{36}',             # GitHub Personal Access Token
    'sk-[A-Za-z0-9]{48}',              # OpenAI API Key
    'xox[baprs]-[0-9A-Za-z-]+',        # Slack token
    'password\s*[:=]\s*[''"][^''"]{8,}[''"]'  # Literal password assignment
)

$patternStr = ($patterns | ForEach-Object { "($_)" }) -join '|'

Get-ChildItem -Recurse -Include *.cs,*.py,*.js,*.ts,*.env,*.yaml,*.yml,*.json `
    -Exclude *.lock,node_modules -ErrorAction SilentlyContinue |
    Select-String -Pattern $patternStr |
    Select-Object Path, LineNumber, Line |
    Select-Object -First 15 |
    Format-Table -Wrap -AutoSize

# Kiểm tra xem có .env files bị track trong git không (nguy hiểm!)
Write-Host "`n=== Checking .env files in git ===" -ForegroundColor Cyan
$gitTracked = git ls-files --error-unmatch .env 2>&1
if ($LASTEXITCODE -eq 0) {
    Write-Warning ".env is tracked by git! Run: git rm --cached .env"
} else {
    Write-Host ".env is NOT tracked by git — OK" -ForegroundColor Green
}

# TruffleHog scan (nếu đã cài)
Write-Host "`n=== TruffleHog scan (nếu đã cài) ===" -ForegroundColor Cyan
if (Get-Command trufflehog -ErrorAction SilentlyContinue) {
    trufflehog filesystem . --json 2>/dev/null | ConvertFrom-Json |
        Select-Object -First 5 | Format-List SourceMetadata, DetectorName
} else {
    Write-Host "Install: pip install trufflehog  hoặc  winget install TruffleHog" -ForegroundColor Gray
}

✅ Kết quả mong đợi / Expected output: Scan liệt kê files và lines có secret patterns. AWS keys (AKIA...) và GitHub tokens (ghp_...) được highlight. .env check xác nhận không bị track trong git. TruffleHog (nếu cài) scan cả git history — tìm secrets đã từng commit rồi xóa. Bài học: một khi secret được push lên remote repo, phải coi là compromised — rotate ngay lập tức.

Lab 2 — Static Analysis với Bandit (Python Security) (Bash)

OS: Ubuntu 22.04 · Tool: Bash + Bandit (Python SAST).

# Cài Bandit — Python SAST tool
pip install bandit 2>/dev/null

# Tạo file Python với các vấn đề bảo mật phổ biến để phân tích
mkdir -p /tmp/bandit-demo
cat > /tmp/bandit-demo/insecure_patterns.py << 'PYEOF'
import hashlib, yaml, xml.etree.ElementTree as ET, tempfile, random

# B303: MD5 use (weak hashing)
def hash_data(data):
    return hashlib.md5(data.encode()).hexdigest()

# B506: yaml.load without Loader (unsafe deserialization)
def parse_config(yaml_string):
    return yaml.load(yaml_string)   # should be yaml.safe_load

# B320: xml.etree allows XXE in some contexts — use defusedxml
def parse_xml(xml_string):
    return ET.fromstring(xml_string)

# B311: Standard random — not cryptographically secure
def generate_token():
    return str(random.randint(100000, 999999))

# B108: Insecure temp file
def write_temp(data):
    f = tempfile.mktemp()   # race condition risk; use mkstemp
    with open(f, 'w') as fp:
        fp.write(data)
    return f

# Secure alternatives (for reference — not flagged by Bandit)
import secrets, hashlib
def generate_token_secure():
    return secrets.token_hex(32)

def hash_data_secure(data):
    return hashlib.sha256(data.encode()).hexdigest()
PYEOF

# Chạy Bandit với tất cả severity levels
echo "=== Bandit SAST Analysis ==="
bandit -r /tmp/bandit-demo/ -ll 2>/dev/null | head -40

# Xuất kết quả JSON để integrate với CI/CD
bandit -r /tmp/bandit-demo/ -f json 2>/dev/null | python3 -c "
import json, sys
data = json.load(sys.stdin)
results = data.get('results', [])
print(f'Total issues: {len(results)}')
for r in results[:6]:
    print(f'  [{r[\"issue_severity\"]}] {r[\"test_id\"]}: {r[\"issue_text\"][:60]}')
    print(f'    File: {r[\"filename\"]}:{r[\"line_number\"]}')
" 2>/dev/null

✅ Kết quả mong đợi / Expected output: Bandit phát hiện: B303 (MD5 weak hash, MEDIUM severity), B506 (yaml.load unsafe, HIGH severity), B311 (random not secure, LOW severity), B108 (insecure temp file). JSON output có thể pipe vào CI/CD pipeline để fail build khi có HIGH/CRITICAL findings. Secure versions (secrets.token_hex, sha256) không bị flag.

3. Tình huống doanh nghiệp / Real-world scenario

Bối cảnh:

Một developer push code chứa AWS access key lên GitHub public repo. 4 phút sau, bot của attacker tự động detect và bắt đầu spin up EC2 instances để mine crypto — bill AWS lên $50,000 trong 2 giờ.

Ngăn chặn và xử lý:

  1. Ngăn chặn: Pre-commit hook với detect-secrets: detect-secrets scan --baseline .secrets.baseline — block commit nếu phát hiện secret pattern.
  2. Phát hiện: GitHub Advanced Security (Secret Scanning) tự động alert khi AWS key được push — thường trong vòng giây.
  3. Response: Rotate key ngay lập tức trong AWS IAM Console → Deactivate old key → Tạo key mới → Update secret manager. Coi key cũ là compromised vĩnh viễn.
  4. Purge từ git history: git filter-repo --path secrets.py --invert-paths để xóa file khỏi toàn bộ history, sau đó force-push (cần coordination với team).
  5. Phòng ngừa lâu dài: IAM role thay vì access keys cho EC2/Lambda; Secrets Manager cho apps; SCPs (Service Control Policies) giới hạn regions được phép tạo resources.

Bài học: bots scan GitHub liên tục trong thời gian thực — không có "chỉ public 1 phút rồi xóa". Phòng ngừa qua pre-commit hooks là giải pháp duy nhất hiệu quả.

4. Tự kiểm tra / Knowledge check

  1. Phân biệt allowlist và denylist validation. Khi nào dùng allowlist không khả thi và giải pháp thay thế?
  2. Output encoding "context-aware" nghĩa là gì? Cho ví dụ encoding khác nhau cho HTML vs JavaScript context.
  3. XXE (XML External Entity) attack hoạt động như thế nào? Cách mitigate trong Java và Python?
  4. Tại sao random.randint() trong Python không an toàn cho token generation? Module nào nên dùng?
  5. Log injection attack là gì? Developer cần làm gì trước khi log user-supplied data?
C03: Thiết kế phần mềm an toàn C05: Kiểm thử bảo mật
Thực hành trên công cụPowerShell 7 · TruffleHog · Bandit
Nền tảngWindows 11 · Ubuntu 22.04 LTS
Thời điểm phát hànhQ2/2026
Ngày biên soạn24/05/2026
Người biên soạnTrần Văn Hòa (MCT)
Phiên bảnv1.0
Zalo