Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

API security: OWASP API Top 10

API and Technical Fundamentals cho BA Bài 50/60

Mở đầu — vì sao bài này quan trọng

Hãy hình dung thế này: doanh nghiệp xây dựng cả một bức tường thành kiên cố bằng tường lửa, mã hóa HTTPS, hệ thống đăng nhập phức tạp — nhưng lại để một cánh cửa sau mở toang. Cánh cửa đó chính là API. Trong thế giới hiện đại, API không còn là chi tiết kỹ thuật ẩn sau hậu trường nữa, mà là nơi phơi bày trực tiếp logic nghiệp vụ và dữ liệu quý giá nhất của tổ chức: thông tin khách hàng, số dư tài khoản, lịch sử giao dịch, dữ liệu y tế. Chính vì lộ ra ngoài như vậy, API đã trở thành mục tiêu tấn công số một. Gartner từng dự báo rằng API sẽ là vector tấn công phổ biến nhất, và thực tế những năm gần đây đã chứng minh điều đó.

Bạn có thể tự hỏi: "Tôi là BA, không phải kỹ sư bảo mật, vậy việc này liên quan gì đến tôi?" Câu trả lời rất rõ ràng. Phần lớn các lỗ hổng bảo mật API nghiêm trọng nhất KHÔNG nằm ở mật mã học hay mạng lưới, mà nằm ở logic nghiệp vụ — đúng phần việc mà BA định nghĩa, mô tả và nghiệm thu. Khi bạn viết một user story như "người dùng xem được hồ sơ của mình", nếu bạn không nói rõ "và KHÔNG được xem hồ sơ người khác", thì lập trình viên rất có thể bỏ sót, và bạn vừa tạo ra một lỗ hổng. BA chính là tuyến phòng thủ đầu tiên, ngay từ giai đoạn viết requirement.

Bài học này giới thiệu OWASP API Security Top 10 — danh sách 10 rủi ro bảo mật API nghiêm trọng nhất do tổ chức phi lợi nhuận OWASP (Open Worldwide Application Security Project) công bố. Đây là phiên bản chuyên biệt cho API, tách riêng khỏi danh sách OWASP Top 10 truyền thống dành cho web. Mục tiêu của bài không phải biến bạn thành chuyên gia pentest, mà giúp bạn đọc một bản spec API và phát hiện ra những lỗ hổng tiềm ẩn trước khi chúng lọt vào production.

Khái niệm cốt lõi

OWASP API Security Top 10 (phiên bản 2023) liệt kê 10 hạng mục rủi ro, đánh số từ API1 đến API10. Ta sẽ đi qua từng mục với góc nhìn của BA.

API1 — Broken Object Level Authorization (BOLA)

Đây là lỗ hổng phổ biến và nguy hiểm nhất. BOLA xảy ra khi API kiểm tra "bạn đã đăng nhập chưa" nhưng quên kiểm tra "bạn có quyền với chính đối tượng dữ liệu này không". Ví dụ kinh điển: endpoint GET /api/users/1024/orders. Nếu hệ thống chỉ cần token hợp lệ là trả về đơn hàng của user 1024, thì kẻ tấn công chỉ cần đổi số thành 1025, 1026... để đọc đơn hàng của người khác. Đây gọi là tấn công IDOR (Insecure Direct Object Reference). BA cần luôn đặt câu hỏi: "Khi truy cập một resource theo ID, hệ thống có kiểm tra resource đó thuộc về người đang gọi không?"

API2 — Broken Authentication

Liên quan đến cơ chế xác thực bị lỗi: cho phép mật khẩu yếu, không giới hạn số lần đăng nhập sai (brute force), token không hết hạn, hoặc endpoint quên reset password lộ thông tin. BA cần đảm bảo requirement có nêu chính sách mật khẩu, khóa tài khoản, và thời gian sống của token.

API3 — Broken Object Property Level Authorization

Đây là sự hợp nhất của hai lỗi cũ: Excessive Data Exposure (API trả về quá nhiều trường, ví dụ trả luôn cả password_hash, internal_notes rồi để frontend tự lọc) và Mass Assignment (API cho phép client gửi lên trường nhạy cảm mà nó không nên sửa, ví dụ gửi {"role": "admin"} vào endpoint cập nhật hồ sơ). BA cần liệt kê rõ trường nào được đọc, trường nào được ghi.

API4 — Unrestricted Resource Consumption

API không giới hạn tài nguyên: không rate limit, cho phép upload file khổng lồ, cho phép page_size=1000000. Hậu quả là từ chối dịch vụ (DoS) hoặc chi phí cloud tăng vọt. Đặc biệt nguy hiểm với các endpoint gọi dịch vụ trả phí (gửi SMS, gửi email, gọi AI).

API5 — Broken Function Level Authorization (BFLA)

Khác với BOLA (về dữ liệu), BFLA là về chức năng: người dùng thường gọi được endpoint của admin. Ví dụ user phát hiện ra DELETE /api/admin/users/{id} và gọi được vì backend quên kiểm tra vai trò.

API6 — Unrestricted Access to Sensitive Business Flows

Một luồng nghiệp vụ bị lạm dụng tự động. Ví dụ: bot mua sạch vé concert hoặc iPhone giảm giá trong vài giây rồi bán lại. Về mặt kỹ thuật mỗi request đều hợp lệ, nhưng luồng nghiệp vụ bị khai thác. BA hiểu nghiệp vụ nên là người chỉ ra luồng nào cần bảo vệ chống automation.

API7 — Server Side Request Forgery (SSRF)

API nhận một URL từ người dùng rồi tự đi gọi URL đó mà không kiểm tra. Kẻ tấn công đưa vào URL nội bộ (ví dụ địa chỉ metadata của cloud) để moi thông tin nhạy cảm.

API8 — Security Misconfiguration

Cấu hình sai: bật chế độ debug ở production, để CORS mở toang, thiếu header bảo mật, dùng mật khẩu mặc định, thông báo lỗi lộ stack trace.

API9 — Improper Inventory Management

Không quản lý danh mục API: còn tồn tại các phiên bản cũ v1 đầy lỗ hổng dù đã có v3, hoặc môi trường staging/test bị lộ ra Internet với dữ liệu thật. "Shadow API" và "zombie API" là kẻ thù.

API10 — Unsafe Consumption of APIs

Tin tưởng mù quáng dữ liệu từ API bên thứ ba. Khi tích hợp với đối tác, hệ thống coi dữ liệu họ trả về là an toàn 100% và không validate, dẫn đến lỗ hổng lan truyền.

Tình huống thực tế

Tình huống 1 — BOLA tại một ví điện tử Việt Nam (giả định: ví "MoMoPay")

Một ví điện tử giả định tên MoMoPay ra mắt tính năng "xem hóa đơn điện tử" qua app. Endpoint là GET /api/v2/invoices/{invoice_id}. Đội phát triển kiểm tra token đăng nhập rất kỹ, nhưng invoice_id lại là số tăng dần đơn giản: 8830012, 8830013, 8830014...

Một bạn kỹ sư bảo mật, vốn là khách hàng, tò mò mở công cụ developer của trình duyệt, thấy app gọi hóa đơn 8830450 của mình. Bạn ấy thử đổi thành 8830451 — và bất ngờ nhận về hóa đơn của một người hoàn toàn xa lạ, đầy đủ tên, số điện thoại, số tiền giao dịch. Bằng một vòng lặp đơn giản, về lý thuyết có thể tải về hàng trăm nghìn hóa đơn của toàn bộ người dùng.

Diễn giải: Lỗi nằm ở chỗ backend chỉ hỏi "token này có hợp lệ không" mà không hỏi "hóa đơn này có phải của chủ token không". Đây chính xác là API1 — BOLA.

Bài học cho BA: Trong acceptance criteria của user story "xem hóa đơn", phải có một dòng tường minh: "Hệ thống PHẢI từ chối (trả về 403 hoặc 404) nếu hóa đơn không thuộc về người dùng đang đăng nhập". Ngoài ra, nên đề xuất dùng ID không đoán được (UUID thay vì số tăng dần) như một lớp phòng thủ bổ sung — dù bản thân điều đó không thay thế việc kiểm tra quyền.

Tình huống 2 — Mass Assignment ở một sàn thương mại điện tử

Một sàn TMĐT khu vực Đông Nam Á (giả định tên "ShopFast") có endpoint PATCH /api/users/me để người dùng tự cập nhật hồ sơ: tên, số điện thoại, địa chỉ. Lập trình viên, vì tiện, viết code kiểu "lấy toàn bộ JSON gửi lên và map thẳng vào đối tượng User trong database".

Vấn đề là đối tượng User còn có trường loyalty_points (điểm thưởng) và account_tier (hạng thành viên). Một người dùng tinh ý gửi request:

PATCH /api/users/me
{ "name": "Nam", "loyalty_points": 9999999, "account_tier": "platinum" }

Hệ thống vui vẻ cập nhật cả ba trường. Người này tự nâng mình lên hạng Platinum và có gần 10 triệu điểm thưởng, đổi ra hàng chục triệu đồng voucher.

Diễn giải: Đây là API3 — Mass Assignment. Hệ thống không phân biệt trường nào client được phép ghi, trường nào không.

Bài học cho BA: Khi viết spec cho bất kỳ endpoint cập nhật nào, hãy lập một bảng rõ ràng: cột "trường", cột "client được đọc?", cột "client được ghi?". Những trường như điểm thưởng, số dư, vai trò, trạng thái thanh toán chỉ được thay đổi bởi logic phía server, không bao giờ nhận trực tiếp từ client. Dùng cơ chế "allowlist" (chỉ chấp nhận đúng các trường được liệt kê) thay vì nhận tất cả.

Tình huống 3 — Lạm dụng luồng nghiệp vụ và rate limiting tại một ngân hàng số

Một ngân hàng số giả định ("TimoBank") có API gửi mã OTP qua SMS khi người dùng quên mật khẩu: POST /api/auth/forgot-password nhận vào số điện thoại. Mỗi lần gọi, hệ thống gửi một tin SMS qua nhà cung cấp với chi phí khoảng 300–700 đồng/tin.

Endpoint này không có rate limit. Một đối thủ (hoặc một bot) viết script gọi endpoint này 200.000 lần trong một đêm với các số điện thoại ngẫu nhiên. Kết quả: hóa đơn SMS đội lên hơn 100 triệu đồng chỉ trong vài giờ, đồng thời hàng nghìn người dân nhận tin nhắn OTP rác giữa đêm, gây khủng hoảng truyền thông.

Diễn giải: Đây là sự kết hợp của API4 (Unrestricted Resource Consumption — không giới hạn tài nguyên/chi phí) và API6 (lạm dụng luồng nghiệp vụ nhạy cảm).

Bài học cho BA: Mọi endpoint gọi dịch vụ tốn tiền hoặc nhạy cảm (gửi SMS, email, gọi AI, tạo đơn) phải có yêu cầu phi chức năng rõ ràng về rate limiting: "tối đa 3 lần/số điện thoại/giờ, tối đa 5 lần/IP/phút", kèm CAPTCHA khi vượt ngưỡng. BA là người hiểu chi phí nghiệp vụ nên phải chủ động nêu các con số này.

Hướng dẫn từng bước

Khi bạn nhận một bản spec API để review về mặt bảo mật, hãy đi theo quy trình sau:

Bước 1 — Liệt kê toàn bộ endpoint và phân loại theo độ nhạy cảm. Lập bảng các endpoint, đánh dấu cái nào đọc/ghi dữ liệu cá nhân, dữ liệu tài chính, hay chức năng admin. Những cái nhạy cảm cần soi kỹ nhất.

Bước 2 — Với mỗi endpoint nhận ID, kiểm tra BOLA. Đặt câu hỏi: "Nếu tôi đổi ID này thành ID của người khác, hệ thống có chặn không?" Yêu cầu spec ghi rõ quy tắc kiểm tra quyền sở hữu (ownership check).

Bước 3 — Với mỗi endpoint trả dữ liệu, kiểm tra Excessive Data Exposure. Yêu cầu danh sách chính xác các trường được trả về. Tìm những trường không nên lộ: hash mật khẩu, token nội bộ, ghi chú nội bộ, dữ liệu của người khác trong cùng response.

Bước 4 — Với mỗi endpoint ghi/cập nhật, kiểm tra Mass Assignment. Lập bảng trường nào client được ghi. Loại bỏ khỏi đầu vào mọi trường nhạy cảm.

Bước 5 — Với mỗi endpoint admin hoặc chức năng đặc quyền, kiểm tra BFLA. Yêu cầu spec ghi rõ vai trò nào được gọi, và backend phải kiểm tra vai trò ở phía server (không tin vào việc "frontend đã ẩn nút đó").

Bước 6 — Bổ sung yêu cầu phi chức năng về rate limiting và resource limit cho các endpoint tốn tài nguyên hoặc tốn chi phí.

Bước 7 — Kiểm tra inventory. Hỏi: còn phiên bản API cũ nào đang chạy không? Môi trường staging có lộ ra ngoài không? Tài liệu Swagger có để public lộ cả endpoint nội bộ không?

Bước 8 — Ghi tất cả phát hiện thành các requirement/acceptance criteria cụ thể, để chúng được kiểm thử và nghiệm thu chứ không chỉ là khuyến nghị suông.

Lỗi thường gặp & mẹo

Lỗi: Nhầm lẫn giữa Authentication và Authorization. Authentication là "bạn là ai" (đăng nhập). Authorization là "bạn được phép làm gì". Hầu hết lỗ hổng API Top 10 (API1, API3, API5) là lỗi authorization, không phải authentication. Token hợp lệ không có nghĩa là được phép truy cập mọi thứ.

Lỗi: Tin rằng "frontend đã ẩn nút thì user không gọi được". Sai hoàn toàn. Kẻ tấn công không dùng giao diện của bạn; họ gọi thẳng API bằng curl hoặc Postman. Mọi kiểm tra quyền PHẢI nằm ở backend.

Lỗi: Để frontend lọc dữ liệu. Nếu API trả về cả 30 trường rồi để app chỉ hiển thị 10 trường, thì 20 trường ẩn kia vẫn nằm trong response và ai cũng đọc được. Backend phải chỉ trả đúng những gì cần.

Lỗi: Dùng ID tuần tự dễ đoán. Tự nó không phải lỗ hổng, nhưng nó biến một lỗ hổng BOLA thành thảm họa quy mô lớn vì kẻ tấn công dễ dàng quét toàn bộ.

Mẹo: Hãy biến mỗi mục OWASP thành một câu hỏi trong checklist review của bạn. Khi đọc spec, lướt qua 10 câu hỏi đó cho từng endpoint nhạy cảm.

Mẹo: Phối hợp với QA để đưa các kịch bản tấn công cơ bản (đổi ID, gửi trường thừa, gọi endpoint admin bằng tài khoản thường) vào bộ test, gọi là "negative testing".

Mẹo: Lưu ý OWASP cập nhật danh sách theo thời gian (2019 → 2023). Luôn tham chiếu phiên bản mới nhất tại owasp.org.

Bài tập thực hành

Bài 1 — Soi BOLA: Cho endpoint GET /api/v1/medical-records/{record_id} của một app y tế. Hãy viết 2 acceptance criteria đảm bảo chống BOLA cho endpoint này.

Bài 2 — Lập bảng Mass Assignment: Đối tượng User có các trường: name, email, phone, password_hash, role, is_verified, wallet_balance. Cho endpoint PATCH /api/users/me. Hãy lập bảng đánh dấu trường nào client được phép ghi, trường nào không, và giải thích ngắn gọn.

Bài 3 — Phân loại lỗ hổng: Với mỗi mô tả sau, hãy gán đúng mã OWASP (API1–API10): (a) API trả về cả số CMND của khách hàng dù app chỉ hiển thị tên. (b) User thường gọi được POST /api/admin/refunds để tự hoàn tiền. (c) Endpoint gửi email mời bạn bè không giới hạn số lần, bị spam. (d) Phiên bản v1 đầy lỗi vẫn chạy song song dù đã có v3.

Bài 4 — Viết yêu cầu phi chức năng: Cho endpoint đăng nhập POST /api/auth/login. Hãy viết các yêu cầu phi chức năng về bảo mật (chống brute force, rate limit, khóa tài khoản) với con số cụ thể.

Gợi ý đáp án Bài 3: (a) API3 — Excessive Data Exposure; (b) API5 — BFLA; (c) API4/API6; (d) API9 — Improper Inventory Management.

Tóm tắt

OWASP API Security Top 10 là tấm bản đồ giúp BA nhận diện những rủi ro bảo mật nghiêm trọng nhất của API, mà phần lớn lại bắt nguồn từ lỗi logic nghiệp vụ và phân quyền — đúng địa hạt của BA. Hai điểm cốt lõi cần khắc cốt ghi tâm: thứ nhất, xác thực (authentication) khác với phân quyền (authorization) — đăng nhập hợp lệ không có nghĩa được phép làm mọi thứ; thứ hai, mọi kiểm tra bảo mật phải nằm ở backend, không bao giờ tin vào frontend.

Với tư cách BA, vũ khí mạnh nhất của bạn không phải là công cụ pentest, mà là một bản requirement viết tường minh: nói rõ ai được truy cập resource nào, trường nào được đọc/ghi, endpoint nào cần rate limit và bao nhiêu. Khi bạn biến 10 hạng mục OWASP thành 10 câu hỏi trong checklist review spec, bạn đã chuyển bảo mật từ "việc của đội security" thành một phần tự nhiên của quy trình phân tích nghiệp vụ — và ngăn chặn lỗ hổng ngay từ trang giấy, trước khi nó kịp trở thành dòng tin nóng trên báo.