Product Management
Đăng nhập
ESC

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

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

Bài 41 — Security Testing Mobile — OWASP MASVS

Đã đọc 0/13 mục · còn khoảng 13 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

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

Hãy tưởng tượng bạn là QA cho một ứng dụng ví điện tử tại Việt Nam. Bạn đã test kỹ chức năng: đăng nhập chạy tốt, chuyển tiền đúng số dư, giao diện đẹp trên mọi màn hình. Đội bạn tự tin release. Ba tuần sau, một bạn nghiên cứu bảo mật đăng lên diễn đàn rằng anh ta rút được file ứng dụng, mở ra thấy trong đó lưu PIN của người dùng dưới dạng plaintext trong SharedPreferences, và API key thanh toán được hard-code thẳng trong mã. Chỉ cần một chiếc điện thoại đã root, ai cũng đọc được. Câu chuyện lên báo, người dùng gỡ app, đội bạn phải giải trình với ngân hàng đối tác.

Điều đau đớn là: tất cả các test case chức năng đều PASS. Vì bảo mật không phải chuyện "chức năng có chạy hay không", mà là chuyện "chức năng có bị lạm dụng được hay không". Đây chính là góc mù mà rất nhiều đội QA di động bỏ qua.

Trong bài này, chúng ta học cách nhìn ứng dụng di động dưới góc độ kẻ tấn công, và dùng một bộ khung chuẩn quốc tế — OWASP MASVS (Mobile Application Security Verification Standard) — để biến bảo mật từ chuyện mơ hồ thành một checklist có thể kiểm thử được. Bạn không cần trở thành hacker chuyên nghiệp; bạn cần biết đủ để phát hiện những lỗ hổng phổ biến nhất trước khi kẻ xấu làm điều đó.

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

OWASP MASVS là gì

OWASP (Open Worldwide Application Security Project) là tổ chức phi lợi nhuận nổi tiếng về bảo mật ứng dụng. MASVS là tiêu chuẩn của họ dành riêng cho ứng dụng di động — một bộ yêu cầu bảo mật được chia theo nhóm, đóng vai trò như "thước đo" để đánh giá một app có an toàn hay chưa. Đi kèm MASVS là MASTG (Mobile Application Security Testing Guide) — cẩm nang hướng dẫn cách kiểm thử từng yêu cầu, và MAS Checklist — bảng tick từng mục.

Điều quan trọng cần hiểu: MASVS không phải công cụ, mà là ngôn ngữ chung. Khi bạn nói "app này chưa đạt MASVS-STORAGE-1", cả team dev, security và QA đều hiểu chính xác vấn đề nằm ở đâu.

Tám nhóm kiểm soát của MASVS

Phiên bản MASVS hiện đại tổ chức yêu cầu thành các nhóm (control groups). Bạn hãy ghi nhớ ý nghĩa thực dụng của từng nhóm, vì đó chính là các "mặt trận" bạn phải test:

  • V1 — Architecture (Kiến trúc & thiết kế): App có suy nghĩ về bảo mật ngay từ thiết kế không? Có mô hình mối đe dọa (threat model), có tách biệt dữ liệu nhạy cảm không?
  • V2 — Storage (Lưu trữ dữ liệu): Dữ liệu nhạy cảm (mật khẩu, token, thông tin cá nhân) được lưu ở đâu và có được mã hóa không? Đây là nhóm QA di động dễ chạm tới nhất.
  • V3 — Crypto (Mã hóa): App dùng thuật toán mã hóa mạnh hay tự chế thuật toán yếu? Key được sinh và lưu ra sao?
  • V4 — Auth (Xác thực & phân quyền): Đăng nhập, session, sinh trắc học có được xử lý an toàn không? Session có hết hạn không?
  • V5 — Network (Giao tiếp mạng): App có dùng HTTPS/TLS không? Có kiểm tra chứng chỉ (certificate pinning) để chống nghe lén không?
  • V6 — Platform (Tương tác nền tảng): App dùng WebView, deep link, clipboard, quyền hệ thống có an toàn không? Có rò rỉ dữ liệu qua các cơ chế IPC không?
  • V7 — Code (Chất lượng mã & khả năng chống dịch ngược): App có che giấu logic nhạy cảm, chống debug, chống chỉnh sửa (tampering) không?
  • V8 — Resilience (Khả năng kháng cự): App có phát hiện được thiết bị đã root/jailbreak, phát hiện bị hook/emulator không?
Với vai trò QA di động, bạn không cần đào sâu như một pentester ở V7/V8, nhưng bạn bắt buộc phải kiểm được các dấu hiệu cơ bản của V2 (Storage), V5 (Network) và V4 (Auth) — vì đây là nơi 80% lỗ hổng thực tế xuất hiện.

Ba mức độ kiểm thử (Verification Levels)

MASVS chia mức độ đảm bảo theo rủi ro của ứng dụng:

  • L1: Yêu cầu bảo mật cơ bản, áp dụng cho hầu hết mọi app. Ví dụ app đọc báo, app tin tức.
  • L2: Yêu cầu nâng cao, dành cho app xử lý dữ liệu nhạy cảm — ngân hàng, y tế, ví điện tử. Ví điện tử của bạn phải nhắm L2.
  • R (Resilience): Bổ sung các yêu cầu chống dịch ngược và chống tấn công phía client, dành cho app có giá trị cao dễ bị nhắm tới (game có in-app purchase lớn, fintech).
Việc đầu tiên khi lên kế hoạch security test là xác định app của bạn thuộc mức nào. Test một app tin tức theo tiêu chuẩn L2 + R là lãng phí; test một app ngân hàng chỉ ở L1 là tự sát.

Tình huống thực tế

Tình huống 1 — Token đăng nhập lưu trần trong ví điện tử (V2 Storage)

Một fintech startup ở TP.HCM, gọi là "PayNhanh", ra mắt ví điện tử. Đội QA có 4 người, tất cả đều mạnh về test chức năng nhưng chưa từng làm security. Trong một buổi review, mentor đề nghị họ thử một bài kiểm tra Storage đơn giản: cài app lên máy Android đã root, đăng nhập, rồi dùng ADB duyệt vào thư mục /data/data/com.paynhanh.wallet/shared_prefs/.

Kết quả gây sốc: file auth.xml chứa dòng <string name="access_token">eyJhbGci...</string> — token phiên đăng nhập hoàn toàn không mã hóa, còn hạn 30 ngày. Bất kỳ ai lấy được thiết bị (hoặc một malware có quyền root) đều có thể copy token này, dán vào công cụ Postman và gọi API chuyển tiền dưới danh nghĩa nạn nhân, không cần biết mật khẩu.

Diễn giải: Đây là vi phạm điển hình của MASVS-STORAGE. Dev đã dùng SharedPreferences mặc định thay vì EncryptedSharedPreferences (Android) hoặc Keychain (iOS). Lỗi này không thể phát hiện qua test chức năng vì app vẫn chạy hoàn hảo.

Bài học: Với mọi app xử lý tiền/danh tính, QA phải có ít nhất một bài test bắt buộc: "dữ liệu nhạy cảm sau khi lưu có đọc được ở dạng plaintext không?". Bài test này rẻ, nhanh, và chặn được thảm họa.

Tình huống 2 — Không có certificate pinning, bị nghe lén trên Wi-Fi công cộng (V5 Network)

Một app đặt xe giả định tên "GoDi" hoạt động ở Đông Nam Á. QA test trên mạng công ty, mọi thứ HTTPS đầy đủ, nên yên tâm rằng mạng đã an toàn. Nhưng một chuyên gia bảo mật đã dựng một proxy trung gian (mitmproxy) trên máy tính, cài chứng chỉ CA giả lên điện thoại test, rồi mở app.

Vì GoDi chấp nhận mọi chứng chỉ được thiết bị tin cậy (không có certificate pinning), toàn bộ lưu lượng — số điện thoại tài xế, tọa độ GPS, lịch sử chuyến đi, mã OTP — hiện rõ mồn một trong công cụ proxy. Trong một quán cà phê với Wi-Fi giả mạo, kẻ tấn công hoàn toàn có thể làm điều tương tự với người dùng thật.

Diễn giải: HTTPS chỉ đảm bảo dữ liệu được mã hóa với "một máy chủ nào đó mà thiết bị tin". Nếu kẻ tấn công lừa được thiết bị tin vào chứng chỉ của họ (rất dễ trong tấn công man-in-the-middle), HTTPS không còn bảo vệ. Certificate pinning buộc app chỉ chấp nhận đúng chứng chỉ của server thật, chặn đứng kiểu tấn công này.

Bài học: Test network security không chỉ là "kiểm tra có dùng HTTPS không", mà phải là "app có chống được proxy trung gian không". QA cần biết dựng mitmproxy — đây là kỹ năng nền tảng.

Tình huống 3 — API key hard-code lộ qua dịch ngược (V7 Code)

Một app thương mại điện tử ở Hà Nội tích hợp dịch vụ gửi SMS OTP của bên thứ ba. Để tiện, dev nhét thẳng API key và secret của nhà cung cấp SMS vào mã nguồn app. Một sinh viên tò mò tải file APK từ máy mình, dùng công cụ apktool và jadx để dịch ngược, và trong vòng 15 phút tìm thấy chuỗi SMS_API_KEY = "sk_live_...".

Với key đó, bạn sinh viên gửi thử vài trăm tin nhắn SMS — mỗi tin tốn tiền của công ty. Nếu là kẻ xấu, họ có thể đốt hết hạn mức SMS trong một đêm, khiến người dùng thật không nhận được OTP để đăng nhập.

Diễn giải: Mọi thứ nằm trong file cài đặt app đều có thể bị đọc. App di động chạy trên thiết bị của người dùng — môi trường mà bạn không kiểm soát. Bí mật thực sự (secret) phải nằm ở server, app chỉ gọi qua backend của chính mình.

Bài học: QA nên thêm một bước kiểm tra định kỳ: dịch ngược build và tìm các chuỗi nhạy cảm (API key, mật khẩu, URL nội bộ, token). Đây là kiểm thử V7 cơ bản mà không cần là chuyên gia.

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

Dưới đây là quy trình một QA di động có thể thực hiện để đưa security test vào công việc hằng ngày, ưu tiên các nhóm chạm tới được nhiều nhất.

Bước 1 — Phân loại rủi ro ứng dụng. Xác định app thuộc L1, L2 hay cần thêm R. Ghi vào tài liệu test plan. Câu hỏi định hướng: app có xử lý tiền, danh tính, hồ sơ y tế, hay dữ liệu cá nhân nhạy cảm không?

Bước 2 — Chuẩn bị môi trường. Bạn cần: một máy Android đã root (hoặc máy ảo) và/hoặc iOS jailbreak để duyệt hệ thống file; công cụ adb; mitmproxy hoặc Burp Suite để chặn mạng; jadx/apktool để dịch ngược APK. Với đội chưa có thiết bị root, có thể dùng emulator hoặc dịch vụ device farm hỗ trợ.

Bước 3 — Kiểm thử Storage (V2). Đăng nhập, thực hiện vài thao tác nhạy cảm, rồi duyệt các vị trí lưu trữ: shared_prefs/, database SQLite trong databases/, file trong files/ và thư mục cache. Tìm token, mật khẩu, PIN, số thẻ ở dạng plaintext. Kiểm tra thêm log hệ thống bằng adb logcat xem app có in dữ liệu nhạy cảm ra log không.

Bước 4 — Kiểm thử Network (V5). Dựng mitmproxy, cấu hình proxy trên thiết bị, cài chứng chỉ CA của proxy. Mở app: nếu bạn đọc được lưu lượng rõ ràng, app thiếu certificate pinning — ghi nhận lỗi. Kiểm tra thêm: có endpoint nào dùng HTTP thay vì HTTPS không.

Bước 5 — Kiểm thử Auth & Session (V4). Sau khi đăng xuất, thử dùng lại token cũ — nó có còn hiệu lực không (session phải bị vô hiệu)? Token có thời gian hết hạn hợp lý không? Đổi mật khẩu có làm mất hiệu lực các phiên khác không? Với sinh trắc học, thử bypass bằng cách nào đó xem app có fallback an toàn không.

Bước 6 — Kiểm thử Code (V7 cơ bản). Dịch ngược build bằng jadx, tìm chuỗi nhạy cảm: grep các từ khóa như password, secret, api_key, http://, tên miền nội bộ. Ghi nhận mọi bí mật lộ ra.

Bước 7 — Ghi nhận theo ngôn ngữ MASVS. Khi báo lỗi, gắn đúng nhóm control (ví dụ: "MASVS-NETWORK: thiếu certificate pinning, tái hiện bằng mitmproxy"). Điều này giúp dev hiểu ngay và ưu tiên xử lý.

Bước 8 — Tích hợp vào quy trình. Đưa các bước rẻ nhất (kiểm tra storage, dịch ngược tìm secret, kiểm session logout) thành checklist bắt buộc mỗi lần release. Các bước sâu hơn (pentest đầy đủ) thì thuê chuyên gia định kỳ.

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

Nhầm "app dùng HTTPS" với "app an toàn về mạng". HTTPS là điều kiện cần chứ không đủ. Không có certificate pinning, app vẫn bị nghe lén qua MITM. Luôn test bằng proxy trung gian.

Chỉ test trên thiết bị không root nên "không thấy gì". Nhiều lỗ hổng storage chỉ lộ khi bạn duyệt được vào /data/data/. Nếu không có thiết bị root, bạn đang bỏ qua nhóm dễ khai thác nhất. Hãy đầu tư một thiết bị test root riêng.

Coi security test là việc của "team security", không phải QA. Trong thực tế, phần lớn đội không có team security riêng. QA là tuyến phòng thủ đầu tiên và thường là duy nhất. Những bài test cơ bản trong bài này bạn hoàn toàn làm được.

Test một lần rồi thôi. Mỗi bản build mới có thể vô tình thêm log nhạy cảm, thêm endpoint HTTP, hoặc gỡ pinning. Security test phải lặp lại theo chu kỳ release, tối thiểu là bộ checklist rẻ.

Bỏ quên dữ liệu ở trạng thái "app chạy nền" và clipboard. Ảnh chụp màn hình khi app vào background (task switcher) có thể lộ số thẻ; dữ liệu copy vào clipboard có thể bị app khác đọc. Đây là các điểm V6 Platform hay bị quên.

Mẹo — dùng MAS Checklist làm khung báo cáo. Tải bảng checklist chính thức của OWASP, đánh dấu Pass/Fail/Not Applicable cho từng mục theo mức L của app. Bạn sẽ có ngay một báo cáo bảo mật chuyên nghiệp, dễ trình bày với sếp và đối tác.

Mẹo — bắt đầu nhỏ. Đừng cố làm hết 8 nhóm ngay lần đầu. Chọn V2 Storage và V5 Network trước — đây là hai nhóm cho kết quả nhanh, tác động lớn và dễ thuyết phục cả team đầu tư thêm.

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

  • Xác định mức MASVS. Chọn ba app bạn dùng hằng ngày (một app tin tức, một app chat, một app ngân hàng). Với mỗi app, lập luận nó nên đạt mức L1, L2 hay cần thêm R, và giải thích vì sao dựa trên loại dữ liệu nó xử lý.
  • Săn dữ liệu plaintext (V2). Trên một emulator hoặc thiết bị Android đã root, cài một app test (có thể là app do team bạn phát triển hoặc app luyện tập như "InsecureBankv2"). Đăng nhập, rồi duyệt shared_prefs/ và databases/. Chụp lại bằng chứng nếu tìm thấy token/mật khẩu chưa mã hóa và viết mô tả lỗi theo ngôn ngữ MASVS-STORAGE.
  • Dựng MITM (V5). Cài mitmproxy, cấu hình thiết bị test đi qua proxy, cài chứng chỉ CA. Mở một app bất kỳ và quan sát xem bạn có đọc được lưu lượng không. Kết luận: app này có certificate pinning hay không, và mô tả rủi ro nếu không có.
  • Dịch ngược tìm secret (V7). Lấy một file APK, dùng jadx mở ra, và tìm các chuỗi nhạy cảm bằng từ khóa api_key, secret, http://. Ghi lại những gì tìm được và đề xuất cách khắc phục (đưa secret về server).
  • Viết một mini security checklist. Dựa trên bài học, soạn một checklist 10 mục mà đội QA của bạn sẽ chạy bắt buộc trước mỗi lần release, mỗi mục gắn với một nhóm MASVS.

Tóm tắt

Security testing di động không phải là kiểm tra "app có chạy không", mà là "app có bị lạm dụng được không". OWASP MASVS cho chúng ta một ngôn ngữ chung và một bộ khung tám nhóm kiểm soát — từ Architecture, Storage, Crypto, Auth, Network, Platform, đến Code và Resilience — cùng ba mức đảm bảo L1/L2/R tùy theo độ nhạy cảm của app.

Với vai trò QA di động, bạn không cần là pentester chuyên nghiệp, nhưng bạn bắt buộc phải làm được ba nhóm chạm tới nhiều nhất: kiểm tra dữ liệu nhạy cảm lưu plaintext (V2), kiểm tra khả năng chống nghe lén qua MITM (V5), và kiểm tra session/xác thực (V4), cộng thêm bước dịch ngược tìm secret (V7). Ba tình huống thực tế — token lưu trần ở ví điện tử, thiếu certificate pinning ở app đặt xe, và API key hard-code lộ qua dịch ngược — cho thấy các lỗi này rất phổ biến, hoàn toàn vô hình với test chức năng, nhưng có thể phát hiện bằng những bài test rẻ tiền.

Hãy bắt đầu nhỏ với V2 và V5, ghi nhận lỗi theo đúng ngôn ngữ MASVS, và biến các bài test rẻ nhất thành checklist bắt buộc mỗi lần release. Đó là cách một đội QA bình thường trở thành tuyến phòng thủ bảo mật thực sự cho sản phẩm.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi