1/139
Looks like no tags are added yet.
Name | Mastery | Learn | Test | Matching | Spaced | Call with Kai | Chat |
|---|
No analytics yet
Send a link to your students to track their progress
[C/C++ - Câu 1] Trong C, đoạn char name[32]; scanf("%s", name); với name nhập từ người dùng tiềm ẩn lỗ hổng nào?
A. Lỗi chuỗi định dạng do dùng "%s" B. Tràn bộ đệm ngăn xếp do đọc quá dài C. scanf không ghi ký tự NUL kết thúc D. Đọc biến name khi chưa khởi tạo
B. Tràn bộ đệm ngăn xếp do đọc quá dài
[C/C++ - Câu 2] Hàm thư viện C nào sao chép chuỗi mà không nhận kích thước vùng đích, dễ gây tràn bộ đệm?
A. snprintf B. fgets C. strcpy D. strncpy
C. strcpy
[C/C++ - Câu 3] Lỗ hổng nghiêm trọng nhất của syslog(LOG_INFO, msg); khi msg do người dùng nhập là gì?
A. Log injection: chèn dòng log giả qua msg B. Tràn bộ đệm nội bộ khi msg quá dài C. Lộ thông tin nhạy cảm của msg ra log D. msg bị dùng làm chuỗi định dạng
D. msg bị dùng làm chuỗi định dạng
[C/C++ - Câu 4] Đoạn int result; if (code == 0) result = 1; return result; (result là biến cục bộ) có rủi ro gì?
A. Trả về giá trị không xác định khi code ≠ 0 B. Trả về 0 vì biến cục bộ mặc định bằng 0 C. Không biên dịch được vì result có thể chưa gán D. Chỉ sai ở bản debug, bản release tự gán 0
A. Trả về giá trị không xác định khi code ≠ 0
[C/C++ - Câu 5] Đoạn free(t); if (t->active) log_warn("…"); mắc lỗi gì?
A. NULL dereference vì free() đặt t = NULL B. Use-after-free khi đọc t->active C. Không lỗi: vùng vừa free còn giữ giá trị cũ D. Rò rỉ bộ nhớ vì t chưa được gán NULL
B. Use-after-free khi đọc t->active
[C/C++ - Câu 6] Đoạn char *v = getenv(name); char *c = malloc(strlen(v) + 1); strcpy(c, v); thiếu bước an toàn nào?
A. Thiếu free() chuỗi do getenv trả về B. Nên thay strcpy bằng strncpy cho an toàn C. strlen(v) + 1 vẫn thiếu chỗ cho NUL D. Không kiểm tra getenv/malloc trả về NULL
D. Không kiểm tra getenv/malloc trả về NULL
[C/C++ - Câu 7] Hàm cấp phát count byte (count kiểu size_t do caller truyền): unsigned short n = count; return malloc(n);. Vấn đề là gì?
A. Lỗi dấu: n bị âm khi count quá lớn B. malloc trả NULL khi count lớn, gây crash C. Phải ép n sang int trước khi gọi malloc D. Cắt cụt: cấp thiếu khi count > 65535
D. Cắt cụt: cấp thiếu khi count > 65535
[C/C++ - Câu 8] Với int a[n];, đoạn for (i = 0; i <= n; i++) a[i] = 0; mắc lỗi gì?
A. Bỏ sót phần tử cuối a[n-1] B. Ghi ngoài mảng tại a[n] C. Hợp lệ vì C cho phép trỏ tới a[n] D. Ghi ngoài mảng tại a[n] và a[n+1]
B. Ghi ngoài mảng tại a[n]
[C/C++ - Câu 9] Hàm sau nguy hiểm vì sao? char *greet(const char *name){ char buf[64]; snprintf(buf, sizeof buf, "Hello %s", name); return buf; }
A. buf tràn khi name dài hơn 57 ký tự B. snprintf không ghi NUL khi bị cắt bớt C. Trả con trỏ tới mảng cục bộ đã bị hủy D. Caller phải free() kết quả, dễ rò rỉ
C. Trả con trỏ tới mảng cục bộ đã bị hủy
[C/C++ - Câu 10] Đoạn sau với host lấy từ request: snprintf(cmd, sizeof cmd, "ping -c 1 %s", host); system(cmd); có rủi ro chính nào?
A. Tràn bộ đệm cmd khi host quá dài B. Format string do host nằm trong %s C. Chỉ argument injection: thêm cờ cho ping D. Command injection qua shell của system()
D. Command injection qua shell của system()
[C/C++ - Câu 11] Đoạn sau với user lấy từ tham số HTTP: char path[256]; snprintf(path, sizeof path, "/var/www/avatars/%s", user); FILE *f = fopen(path, "rb"); Dẫn tới lỗ hổng nào?
A. Tràn bộ đệm path khi user quá dài B. Path traversal qua chuỗi ../ C. Race TOCTOU giữa snprintf và fopen D. Format string do user nằm trong %s
B. Path traversal qua chuỗi ../
[C/C++ - Câu 12] Đoạn char *p = malloc(strlen(s)); strcpy(p, s); sai ở đâu?
A. malloc thiếu 1 byte, strcpy ghi tràn NUL B. Không sai: strlen(s) đã tính cả byte NUL C. strcpy không ghi NUL nên p thiếu kết thúc D. Phải dùng strncpy(p, s, strlen(s))
A. malloc thiếu 1 byte, strcpy ghi tràn NUL
[C/C++ - Câu 13] Đoạn if (write_record(buf) < 0) free(buf); process(buf); free(buf); có lỗi gì?
A. Rò rỉ buf khi write_record thành công B. Use-after-free bên trong write_record C. Double-free khi write_record thất bại D. Double-free khi write_record thành công
C. Double-free khi write_record thất bại
[C/C++ - Câu 14] Với int scores[10]; và idx đến từ bên ngoài, hàm int get(int idx){ return scores[idx]; } có rủi ro gì?
A. Đọc ngoài mảng khi idx âm hoặc ≥ 10 B. Ghi ngoài mảng khi idx lớn hơn 9 C. Đọc ngoài mảng nhưng chỉ khi idx ≥ 10 D. Segfault ngay khi idx ≥ 10, không lộ dữ liệu
A. Đọc ngoài mảng khi idx âm hoặc ≥ 10
[C/C++ - Câu 15] Đọc code (rows, cols đọc từ header của file ảnh do người dùng tải lên): void *alloc_matrix(size_t rows, size_t cols){ return malloc(rows * cols * sizeof(int)); } Lỗ hổng là gì?
A. Off-by-one: cần cấp thêm một phần tử B. Phải dùng sizeof(int*) thay sizeof(int) C. Không lỗi: tích quá lớn thì malloc trả NULL D. Tràn số ở phép nhân, malloc cấp thiếu
D. Tràn số ở phép nhân, malloc cấp thiếu
[C/C++ - Câu 16] Đọc code (len lấy từ header gói tin): char dst[128]; int recv_packet(const char *src, int len){ if (len > 128) return -1; memcpy(dst, src, len); return len; } Lỗ hổng là gì?
A. Lỗi dấu: len âm qua được kiểm tra B. Off-by-one: len = 128 ghi tràn dst C. Vùng nhớ chồng lấn, phải dùng memmove D. Thiếu kiểm tra len == 0 trước memcpy
A. Lỗi dấu: len âm qua được kiểm tra
[C/C++ - Câu 17] Đọc code: struct Shape { virtual int area() const { return 0; } }; struct Rectangle : Shape { int w = 3, h = 4; int area() const override { return w * h; } }; int render_area(Shape s){ return s.area(); } // gọi: render_area(myRectangle); Vấn đề là gì?
A. Slicing: chỉ phần Shape được sao chép B. Rectangle::area() thiếu từ khóa virtual C. Lỗi biên dịch khi truyền Rectangle vào D. Gọi Rectangle::area() với w, h chưa khởi tạo
A. Slicing: chỉ phần Shape được sao chép
[C/C++ - Câu 18] Đọc code: void copy_str(char *dst, const char *src){ size_t i = 0; while (src[i]) { dst[i] = src[i]; i++; } } Cách sửa nào khắc phục được các lỗi của hàm?
A. Ghi NUL sau vòng lặp, kiểm tra src khác NULL B. Dừng khi i < strlen(dst), sau đó ghi NUL C. Dùng strncpy(dst, src, strlen(src)) rồi ghi NUL D. Truyền kích thước dst, dừng ở size-1, ghi NUL
D. Truyền kích thước dst, dừng ở size-1, ghi NUL
[C/C++ - Câu 19] Đọc code (total, used kiểu size_t): size_t remaining = total - used; memcpy(dst, src, remaining); Điều gì xảy ra khi used > total?
A. remaining bị kẹp về 0, memcpy không chép gì B. remaining thành số cực lớn, ghi tràn dst C. remaining âm, memcpy trả về lỗi tham số D. UB do tràn số có dấu ở phép trừ
B. remaining thành số cực lớn, ghi tràn dst
[C/C++ - Câu 20] Đọc code (count kiểu unsigned int): for (int i = 0; i <= count - 1; i++) transmit(items[i]); Khi count == 0 thì sao?
A. count - 1 thành UINT_MAX, lặp đọc tràn B. Không lặp lần nào vì 0 <= -1 là sai C. Lặp đúng một lần, chỉ đọc items[0] D. Lỗi biên dịch: so sánh int với unsigned
A. count - 1 thành UINT_MAX, lặp đọc tràn
[C/C++ - Câu 21] Hàm cần cấp phát mảng count phần tử Node (count do caller truyền): Node *alloc_nodes(size_t count){ return malloc(count); } Cách sửa đúng là gì?
A. return malloc(count * sizeof(Node *)); B. return calloc(count, sizeof(Node)); C. return malloc(count + sizeof(Node)); D. return malloc(count * sizeof(count));
B. return calloc(count, sizeof(Node));
[C/C++ - Câu 22] Đọc code (base từ cấu hình, user từ request): char path[128]; strcpy(path, base); strcat(path, "/"); strcat(path, user); load(path); Cách sửa đúng là gì?
A. Đổi lệnh cuối thành strncat(path, user, sizeof path) B. Tăng kích thước path lên PATH_MAX (4096) C. Kiểm tra strlen(user) < 128 trước khi nối D. snprintf(path, sizeof path, …) + kiểm tra kết quả
D. snprintf(path, sizeof path, …) + kiểm tra kết quả
[C/C++ - Câu 23] Đọc code (v là std::vector
A. it = v.erase(it); chỉ ++it khi không xóa B. Thêm break; ngay sau v.erase(it) C. Lưu auto end = v.end() trước vòng lặp D. Dùng v.erase(it++) giống như với std::map
A. it = v.erase(it); chỉ ++it khi không xóa
[C/C++ - Câu 24] Đọc code (i lấy từ tham số request): int get_pixel(const std::vector
A. operator[] kiểm tra biên và ném out_of_range B. operator[] không kiểm tra biên, i ≥ size() là UB C. Thiếu kiểm tra rỗng; thêm !buf.empty() là sửa xong D. Chỉ UB khi i ≥ capacity(), không phải size()
B. operator[] không kiểm tra biên, i ≥ size() là UB
[C/C++ - Câu 25] Đọc code: struct Document { char *body; explicit Document(const char *s) : body(strdup(s)) {} ~Document() { free(body); } }; Document clone_doc(const Document &src){ Document d = src; return d; } Lỗ hổng là gì?
A. Rò rỉ body vì clone_doc không gọi free B. Double-free: hai đối tượng cùng giữ body C. Slicing khi trả Document theo giá trị D. Dangling: trả về biến cục bộ d
B. Double-free: hai đối tượng cùng giữ body
[C/C++ - Câu 26] Đọc code: std::string_view first_word(const std::string& s){ return s.substr(0, s.find(' ')); } Lỗi là gì?
A. View trỏ vào std::string tạm đã bị hủy B. Sai khi không có dấu cách do find trả npos C. Không lỗi: string_view tự sao chép ký tự D. View chỉ treo nếu caller hủy s trước khi dùng
A. View trỏ vào std::string tạm đã bị hủy
[C/C++ - Câu 27] Reviewer nghi đoạn sau tràn số khi tính kích thước cấp phát (la, lb do caller truyền): char *concat(const char *a, size_t la, const char *b, size_t lb){ if (lb >= SIZE_MAX - la) return NULL; char *p = malloc(la + lb + 1); if (!p) return NULL; memcpy(p, a, la); memcpy(p + la, b, lb); p[la + lb] = '\0'; return p; } Đánh giá nào đúng?
A. Guard sai khi lb = SIZE_MAX do phép trừ quay vòng B. Không lỗi: guard đã loại trường hợp la + lb + 1 tràn C. Thiếu chỗ cho NUL, phải malloc(la + lb + 2) D. Tràn khi la + lb vượt SIZE_MAX dù đã có guard
B. Không lỗi: guard đã loại trường hợp la + lb + 1 tràn
[C/C++ - Câu 28] Đọc code (chạy trên x86-64, s là dữ liệu client gửi lên, dài ≥ 33 byte): struct Msg { char payload[32]; uint32_t len; }; void pack(struct Msg *m, const char *s){ m->len = 32; for (int i = 0; i
A. Chỉ mất NUL cuối payload, len vẫn là 32 B. Ghi 1 byte vào padding giữa hai trường C. Byte thấp của len bị ghi, send gửi tới 255 byte D. Byte cao của len bị ghi, send gửi tới ~4 GB
C. Byte thấp của len bị ghi, send gửi tới 255 byte
[C/C++ - Câu 29] Đọc code: void store(std::vector
A. Không lỗi: std::move chỉ ép kiểu, dữ liệu còn B. Double-free: store và samples cùng giữ buffer C. front() trên vector đã bị move (thường rỗng) D. Rò rỉ: store nhận bản sao, buffer cũ không giải phóng
C. front() trên vector đã bị move (thường rỗng)
[C/C++ - Câu 30] Đọc code: int mouse_x(Event *e){ MouseEvent *m = static_cast
A. static_cast kiểm tra lúc chạy, trả về nullptr B. Type confusion: đọc x theo bố cục sai kiểu C. Lỗi biên dịch vì e không phải MouseEvent D. Ném std::bad_cast khi chạy tới dòng cast
B. Type confusion: đọc x theo bố cục sai kiểu
[C/C++ - Câu 31] Đọc code (a, b là Socket*): Conn(){ a = new Socket(); b = new Socket(); } ~Conn(){ delete a; delete b; } Nếu new Socket() thứ hai ném ngoại lệ thì sao?
A. ~Conn không chạy nên a bị rò rỉ B. ~Conn vẫn chạy, giải phóng đúng a và b C. b bị rò rỉ vì chưa kịp giải phóng D. ~Conn chạy, delete b chưa khởi tạo gây crash
A. ~Conn không chạy nên a bị rò rỉ
[C/C++ - Câu 32] Đọc code (v là std::vector
A. Không lỗi: back() trả về bản sao phần tử B. Tham chiếu r không bị ảnh hưởng, chỉ iterator bị vô hiệu C. push_back có thể cấp phát lại, làm r bị treo D. r còn đúng vì string giữ chuỗi trên heap
C. push_back có thể cấp phát lại, làm r bị treo
[C/C++ - Câu 33] Linter cảnh báo tại dòng buf = realloc(buf, newsize); ('assigning realloc result to its own argument'). Cách xử lý đúng là gì?
A. Thêm if (!buf) return; ngay sau realloc B. free(buf) trước, rồi realloc(NULL, newsize) C. Bỏ qua: realloc lỗi thì buf vẫn giữ khối cũ D. Gán vào biến tạm, kiểm tra NULL rồi mới gán buf
D. Gán vào biến tạm, kiểm tra NULL rồi mới gán buf
[C/C++ - Câu 34] Semgrep gắn cờ 'path-traversal' cho hàm sau (raw là phần đường dẫn lấy từ URL): if (strstr(raw, "..") != NULL) return NULL; url_decode(raw, name, sizeof name); snprintf(path, sizeof path, "/data/%s", name); return fopen(path, "rb"); Nhận định nào đúng?
A. False positive: chuỗi ".." đã bị chặn B. Vượt được bằng đường dẫn tuyệt đối /etc/passwd C. Vượt được bằng %2e%2e/ vì kiểm tra trước khi decode D. Vượt được bằng "….//" như lỗi của replace()
C. Vượt được bằng %2e%2e/ vì kiểm tra trước khi decode
[C/C++ - Câu 35] CodeQL báo 'Uncontrolled command line' cho đoạn sau, field lấy từ HTTP request: if (strlen(field) != 1 || field[0] < '1' || field[0] > '9') return -1; char key[8]; snprintf(key, sizeof key, "-k%s", field); char *argv[] = { "sort", key, "data.txt", NULL }; execvp("sort", argv); Nhận định nào đúng?
A. Injection qua PATH vì execvp tự tìm "sort" B. False positive: chỉ 1 chữ số, không qua shell C. Argument injection: field = "-o/tmp/x" D. Tràn bộ đệm key khi field quá dài
B. False positive: chỉ 1 chữ số, không qua shell
[C/C++ - Câu 36] MemorySanitizer báo 'use-of-uninitialized-value' tại write(sock, &h, sizeof h); với: struct Header { uint8_t type; uint32_t len; }; struct Header h; h.type = type; h.len = 0; Nguyên nhân và cách xử lý?
A. len sai thứ tự byte; gọi htonl(h.len) trước khi gửi B. False positive vì type, len đã gán; bỏ qua C. Padding chưa khởi tạo; zero struct hoặc serialize từng trường D. h trên stack chứa rác; cấp h bằng malloc
C. Padding chưa khởi tạo; zero struct hoặc serialize từng trường
[C/C++ - Câu 37] AddressSanitizer báo 'attempting double-free' tại free(p->second) trong free(p->first); free(p->second);. Nguyên nhân khả dĩ nhất?
A. first và second cùng trỏ một vùng nhớ B. second trỏ vào stack chứ không phải heap C. second là NULL mà free(NULL) bị cấm D. Sai thứ tự: phải free second trước first
A. first và second cùng trỏ một vùng nhớ
[C/C++ - Câu 38] ASan báo 'heap-use-after-free READ' trong unlink, code: free(node); unlink(node); // unlink đọc node->prev, node->next Cách xử lý đúng là gì?
A. Gán node = NULL ngay sau free(node) B. Kiểm tra node != NULL trước khi unlink C. Gọi unlink(node) trước rồi mới free(node) D. Sau free, chép *node ra biến tạm để unlink
C. Gọi unlink(node) trước rồi mới free(node)
[C/C++ - Câu 39] Fuzzer gây crash; ASan báo 'heap-buffer-overflow WRITE' tại memcpy(buf, val, vallen), trong đó vallen đọc từ gói tin còn buf có kích thước buflen. Cách sửa đúng là gì?
A. Kiểm tra val != NULL trước khi memcpy B. Đổi memcpy thành memmove cho an toàn C. Từ chối gói tin khi vallen > buflen D. Dùng strncpy(buf, val, vallen) thay thế
C. Từ chối gói tin khi vallen > buflen
[C/C++ - Câu 40] ASan báo 'heap-buffer-overflow WRITE' trong memcpy với code sau (data_len, extra do attacker điều khiển): size_t total = data_len + extra + 4; char *buf = malloc(total); memcpy(buf, data, data_len); memset(buf + data_len, 0, extra + 4); Nhận định nào đúng?
A. Tổng bị quay vòng nên malloc cấp thiếu B. data và buf chồng lấn, phải dùng memmove C. malloc trả NULL và memcpy ghi vào NULL D. Off-by-one: thiếu 1 byte NUL cuối buf
A. Tổng bị quay vòng nên malloc cấp thiếu
[C/C++ - Câu 41] Build với -O2, gọi make_buf(INT_MAX) vẫn chạy tới malloc dù có guard; bản build debug -O0 -fsanitize=undefined báo 'signed integer overflow'. Code: void *make_buf(int n){ if (n + 1 < n) return NULL; return malloc(n + 1); } Giải thích nào đúng nhất?
A. Tràn quay về INT_MIN, guard bị bỏ do bug -O2 B. n + 1 tính theo size_t nên guard không bao giờ đúng C. Guard viết ngược, phải là n < n + 1 D. Tràn có dấu là UB nên -O2 được phép xóa guard
D. Tràn có dấu là UB nên -O2 được phép xóa guard
[C/C++ - Câu 42] ASan báo 'heap-use-after-free' tại use(alias), code: char *alias = buf + 10; char *p = realloc(buf, newsize); // newsize > kích thước cũ use(alias); return p; Cách xử lý đúng là gì?
A. Gọi realloc cùng kích thước để giữ địa chỉ B. Gọi free(buf) trước rồi mới realloc C. Lưu offset 10, sau realloc đặt alias = p + 10 D. memmove dữ liệu từ p + 10 về lại alias
C. Lưu offset 10, sau realloc đặt alias = p + 10
[C/C++ - Câu 43] LeakSanitizer báo rò rỉ 2 Node sau khi a, b ra khỏi scope. Code: struct Node { std::shared_ptr
A. Thêm ~Node() gọi next.reset() và back.reset()
B. Gọi a.reset() và b.reset() trước khi ra khỏi scope
C. Đổi cả next và back sang std::unique_ptr
D. Đổi back thành std::weak_ptr
[DevSecOps - Câu 1] Trong pipeline CI/CD của VinSOC, vì sao bước cài dependency Node.js bắt buộc dùng npm ci thay vì npm install?
A. npm ci bỏ qua devDependencies khi cài, nên artifact build ra có ít thành phần và ít bề mặt tấn công hơn B. npm ci cài đúng theo package-lock.json và dừng nếu lock lệch package.json, nên mọi lần build ra cùng một cây dependency C. npm ci chạy audit và dừng cài khi gặp dependency có CVE mức High trở lên, còn npm install chỉ in cảnh báo D. npm install cũng đọc lockfile như npm ci; quy định chọn npm ci vì cài nhanh hơn và giảm thời gian chiếm runner dùng chung
B. npm ci cài đúng theo package-lock.json và dừng nếu lock lệch package.json, nên mọi lần build ra cùng một cây dependency
[DevSecOps - Câu 2] Mục tiêu cốt lõi của một SBOM (Software Bill of Materials) trong chuỗi cung ứng phần mềm là gì?
A. Chứng minh artifact không bị sửa sau khi build, nhờ chữ ký số gắn kèm image và được kiểm tra lúc triển khai B. Liệt kê lỗ hổng đã biết của từng thành phần kèm điểm CVSS, để đội phát triển xếp thứ tự ưu tiên vá C. Kiểm kê thành phần, phiên bản và license, để khi có CVE mới tra ngay được sản phẩm nào bị ảnh hưởng D. Ghi lại ai build, build từ commit nào và bằng pipeline nào, để truy vết nguồn gốc khi artifact bị nghi ngờ
C. Kiểm kê thành phần, phiên bản và license, để khi có CVE mới tra ngay được sản phẩm nào bị ảnh hưởng
[DevSecOps - Câu 3] Trong stack VinSOC, Gitleaks chạy ở cả pre-commit lẫn CI/CD. Lý do chính của việc đặt thêm Gitleaks ở pre-commit là gì?
A. Chặn secret trước khi nó vào lịch sử Git; nếu chỉ chặn ở CI thì secret đã lên remote, phải coi là đã lộ và rotate B. Pre-commit chạy trên máy dev nên không bị bỏ qua được, còn job CI có thể bị người có quyền Maintainer tắt đi C. Pre-commit quét được toàn bộ lịch sử commit cũ của repo, còn bước quét ở CI chỉ thấy phần thay đổi trong MR D. Khi đã có pre-commit, bước quét secret ở CI chỉ còn vai trò dự phòng và có thể chuyển sang chạy theo lịch hằng đêm
A. Chặn secret trước khi nó vào lịch sử Git; nếu chỉ chặn ở CI thì secret đã lên remote, phải coi là đã lộ và rotate
[DevSecOps - Câu 4] Semgrep/Gosec (SAST) và Trivy/Dependency-Track (SCA) khác nhau cốt lõi ở điểm nào?
A. SAST phân tích mã nguồn khi chưa chạy, còn SCA phân tích ứng dụng lúc đang chạy để bắt lỗi runtime phát sinh trong thư viện B. SAST tìm lỗ hổng trong các dependency đã khai báo, còn SCA tìm lỗi lập trình trong mã do đội tự viết C. Cả hai cùng tìm lỗ hổng trong dependency; SAST đọc mã nguồn thư viện, còn SCA chỉ đọc file manifest như package.json D. SAST tìm lỗi lập trình trong mã đội tự viết (vd SQLi, path traversal); SCA đối chiếu thư viện bên thứ ba với CVE đã biết
D. SAST tìm lỗi lập trình trong mã đội tự viết (vd SQLi, path traversal); SCA đối chiếu thư viện bên thứ ba với CVE đã biết
[DevSecOps - Câu 5] Pipeline VinSOC sinh SBOM hai lần: trivy fs --format cyclonedx (SBOM-source) và trivy image --format cyclonedx (SBOM-image). Vì sao hai SBOM này không thay thế được cho nhau?
A. SBOM-source có cả dependency transitive còn SBOM-image chỉ có dependency trực tiếp, nên phải ghép cả hai mới đủ cây B. SBOM-image thấy thêm gói OS của base image và các binary thêm vào lúc build, những thứ SBOM-source không thấy C. SBOM-source dùng để quét lỗ hổng còn SBOM-image dùng để kiểm tra license, mỗi loại phục vụ một công cụ downstream D. SBOM-image được ký khi push lên registry nên dùng làm bằng chứng tuân thủ, còn SBOM-source chỉ dùng tham khảo nội bộ
B. SBOM-image thấy thêm gói OS của base image và các binary thêm vào lúc build, những thứ SBOM-source không thấy
[DevSecOps - Câu 6] Theo thực hành chuẩn ngành (FIRST, CISA), phát biểu nào mô tả đúng vai trò của CVSS, EPSS, KEV và SSVC?
A. CVSS: xác suất bị khai thác trong 30 ngày; EPSS: điểm nghiêm trọng điều chỉnh theo môi trường; KEV: danh mục CVE đã bị khai thác thực tế; SSVC: cây quyết định chọn hành động B. CVSS: xác suất bị khai thác trong 30 ngày; EPSS: điểm nghiêm trọng điều chỉnh theo môi trường; KEV: danh sách CVE có EPSS từ 0.7 trở lên; SSVC: định dạng trao đổi VEX C. CVSS: mức nghiêm trọng kỹ thuật; EPSS: xác suất bị khai thác trong 30 ngày; KEV: danh mục CVE đã bị khai thác thực tế; SSVC: cây quyết định chọn hành động D. CVSS: mức nghiêm trọng kỹ thuật; EPSS: xác suất bị khai thác trong 30 ngày; KEV: danh sách CVE có EPSS từ 0.7 trở lên; SSVC: định dạng trao đổi VEX
C. CVSS: mức nghiêm trọng kỹ thuật; EPSS: xác suất bị khai thác trong 30 ngày; KEV: danh mục CVE đã bị khai thác thực tế; SSVC: cây quyết định chọn hành động
[DevSecOps - Câu 7] Một CVE xuất hiện trong SBOM của sản phẩm. Sau phân tích, đội phát hành VEX cho CVE này với status not_affected, justification vulnerable_code_not_in_execute_path. Downstream nên hiểu tuyên bố này thế nào?
A. Thành phần có lỗ hổng vẫn có trong sản phẩm, nhưng nhà sản xuất khẳng định có căn cứ là nó không khai thác được ở đây B. CVE được xác minh là báo nhầm: phiên bản thành phần trong sản phẩm thực ra không thuộc dải phiên bản bị ảnh hưởng C. Thành phần và CVE được gỡ khỏi SBOM của bản phát hành, để scanner của downstream không còn báo cảnh báo này nữa D. Nhà sản xuất đã xác nhận lỗ hổng và cam kết phát hành bản vá theo SLA; trong lúc chờ, downstream chưa phải chặn triển khai
A. Thành phần có lỗ hổng vẫn có trong sản phẩm, nhưng nhà sản xuất khẳng định có căn cứ là nó không khai thác được ở đây
[DevSecOps - Câu 8] Xem .gitlab-ci.yml build image cho hệ thống Loyalty: build_image: stage: build image: docker:24 rules: - if: CICOMMITBRANCH=="main"script:−dockerbuild−tregistry.vinsmartfuture.tech/loyalty/loyalty−app:CI_COMMIT_SHA . - docker push registry.vinsmartfuture.tech/loyalty/loyalty-app:$CI_COMMIT_SHA với Dockerfile bắt đầu bằng: FROM wso2/wso2is:5.11.0 Rủi ro chuỗi cung ứng nghiêm trọng nhất ở đây là gì?
A. docker build không dùng --no-cache, nên layer cũ chứa thư viện lỗi thời có thể bị tái sử dụng trong image mới B. Tag $CI_COMMIT_SHA không thể hiện số phiên bản, nên khi có sự cố khó truy ra image đang chạy được build từ mã nào C. Dockerfile dựa trên image của bên thứ ba thay vì tự build từ scratch, nên đội không thể kiểm soát nội dung image D. Base image wso2/wso2is kéo thẳng từ Docker Hub, không qua JFrog, nên không có curation, SBOM, scan và không ai sở hữu
D. Base image wso2/wso2is kéo thẳng từ Docker Hub, không qua JFrog, nên không có curation, SBOM, scan và không ai sở hữu
[DevSecOps - Câu 9] Một đội Mobile thêm đoạn sau vào Dockerfile để tải artifact nội bộ từ JFrog lúc build: ARG JFROG_TOKEN RUN curl -H "Authorization: Bearer JFROGTOKEN" −Ohttps://registry.vinsmartfuture.tech/artifactory/…/sdk.aarvaˋtruye^ˋn−−build−argJFROGTOKEN=CI_JFROG_TOKEN trong CI (biến CI_JFROG_TOKEN được nạp từ Vault). Gitleaks (pre-commit và CI) đều pass. Vì sao đây là lỗ hổng, và vì sao Gitleaks không bắt được?
A. ARG chỉ tồn tại lúc build nên image không chứa token; lỗ hổng là Gitleaks bỏ qua Dockerfile, cần thêm rule quét Dockerfile B. Token bị in ra log CI khi lệnh curl chạy; Gitleaks không bắt vì công cụ này chỉ quét repo, không quét log pipeline C. Giá trị ARG dùng trong RUN bị ghi vào lịch sử image, ai pull image cũng đọc được; Gitleaks không thấy vì token chỉ truyền vào lúc build D. Header Authorization đi qua mạng có thể bị nghe lén; Gitleaks không bắt vì công cụ này không phân tích lưu lượng mạng của job
C. Giá trị ARG dùng trong RUN bị ghi vào lịch sử image, ai pull image cũng đọc được; Gitleaks không thấy vì token chỉ truyền vào lúc build
[DevSecOps - Câu 10] Sự cố 31/03: một số đội dùng ^ trong package.json, không commit package-lock.json và build bằng npm install; trong cửa sổ khoảng 3 giờ, phiên bản axios@1.14.1 bị chèn mã độc đã được kéo về và build; SOC phát hiện qua C2 beacon (không phải AppSec). Biện pháp nào ngăn được sự cố này một cách căn cơ nhất?
A. Commit lockfile đã review và build bằng npm ci, để phiên bản mới chỉ vào khi đội chủ động cập nhật lockfile B. Đổi ^ thành ~ cho các dependency, để pipeline chỉ nhận bản vá (patch) thay vì cả bản minor mới phát hành C. Ghim riêng axios bằng phiên bản cố định; các dependency khác giữ ^ vì chỉ thư viện trực tiếp mới bị kéo bản mới D. Sinh package-lock.json ngay trong job CI rồi chạy npm audit --audit-level=high, dừng build khi phát hiện phiên bản độc hại
A. Commit lockfile đã review và build bằng npm ci, để phiên bản mới chỉ vào khi đội chủ động cập nhật lockfile
[DevSecOps - Câu 11] Sự cố Log4Shell trong container WSO2 Identity Server trên GKE (hệ thống Loyalty): khi CVE-2021-44228 được công bố, Dependency-Track và Xray cảnh báo cho mọi service Java khác trong vài giờ, nhưng không có cảnh báo nào cho container WSO2. Nguyên nhân gốc đúng nhất?
A. Trivy và Xray đã quét image WSO2 lúc build, nhưng khi đó CSDL lỗ hổng chưa có CVE-2021-44228 nên không có gì để báo B. Image ghim phiên bản cũ 5.11.0; nếu cấu hình tự cập nhật lên tag mới nhất thì image đã nhận được bản vá log4j C. Pod chạy WSO2 không đặt securityContext hạn chế quyền, nên khi bị khai thác container có quyền rộng hơn mức cần D. Image kéo thẳng từ Docker Hub, lưu ngoài JFrog, nên không có SBOM, không được scan và không ai theo dõi
D. Image kéo thẳng từ Docker Hub, lưu ngoài JFrog, nên không có SBOM, không được scan và không ai theo dõi
[DevSecOps - Câu 12] Một pipeline dùng Personal Access Token (PAT) tĩnh, quyền cao (write registry + deploy), lưu trong CI/CD variable (masked), không hết hạn. Theo chính sách token của VSOC_IT09, hướng khắc phục đúng và được ưu tiên là gì?
A. Giữ PAT, bật thêm protected variable để chỉ nhánh protected đọc được, và đặt hạn 6 tháng theo chu kỳ review quyền B. Chuyển sang OIDC (token ngắn hạn sinh theo từng job); nếu buộc dùng token tĩnh quyền cao thì hạn tối đa 30 ngày, thu hẹp scope C. Chuyển PAT vào Vault và để job đọc lúc chạy; token vẫn không hết hạn nhưng không còn nằm trong biến CI/CD nữa D. Tách PAT thành hai token, một để ghi registry và một để deploy; mỗi token không hết hạn nhưng chỉ dùng cho đúng một job
B*. Chuyển sang OIDC (token ngắn hạn sinh theo từng job); nếu buộc dùng token tĩnh quyền cao thì hạn tối đa 30 ngày, thu hẹp scope
[DevSecOps - Câu 13] Một hệ thống đã ký image bằng cosign, sinh SBOM và sinh SLSA provenance v1 trong CI. Ở cluster K8s production, admission hiện chỉ bật Pod Security Admission mức restricted. Theo đánh giá gap của VSF_QD_DEVSECOPS_001, điểm yếu cốt lõi còn lại là gì?
A. SBOM chưa được đính kèm vào image dưới dạng attestation có chữ ký, nên downstream chưa tin được nội dung SBOM B. Provenance được sinh ngay trong job build nên chỉ đạt mức SLSA thấp; cần chuyển sang builder tách biệt để nâng mức C. Cluster không xác minh chữ ký và provenance khi admit pod, nên image chưa ký hoặc bị giả mạo vẫn chạy được D. Pod Security Admission restricted đã chặn image sai chữ ký nhưng chưa chặn image thiếu provenance; cần thêm rule provenance
C. Cluster không xác minh chữ ký và provenance khi admit pod, nên image chưa ký hoặc bị giả mạo vẫn chạy được
[DevSecOps - Câu 14] Nguồn lực vá hạn chế, Dependency-Track trả về 4 CVE. Theo nguyên tắc ưu tiên dựa trên rủi ro (kết hợp CVSS, EPSS, CISA KEV và reachability), CVE nào cần vá trước nhất?
A. CVE-A: CVSS 9.8; EPSS 0.4%; không có trong KEV; hàm lỗi reachable B. CVE-B: CVSS 6.5; EPSS 30%; có trong KEV; hàm lỗi reachable C. CVE-C: CVSS 8.8; EPSS 90%; có trong KEV; hàm lỗi không reachable D. CVE-D: CVSS 9.1; EPSS 45%; không có trong KEV; hàm lỗi reachable
B. CVE-B: CVSS 6.5; EPSS 30%; có trong KEV; hàm lỗi reachable
[DevSecOps - Câu 15] Theo chương trình Security Champions của VinSOC, Security Champion là ai?
A. Nhân sự VinSOC được cử vào từng đội, xử lý việc bảo mật hằng ngày thay cho đội và định kỳ báo cáo lại cho VinSOC B. Lập trình viên trong đội, làm đầu mối chuyển các finding và câu hỏi bảo mật của đội sang VinSOC xử lý C. Trưởng nhóm phát triển, được VinSOC ủy quyền duyệt bảo mật cho từng release thay cho cổng thẩm định của VinSOC D. Lập trình viên trong đội, kiêm nhiệm bảo mật, tự xử lý việc bảo mật hằng ngày và chuyển VinSOC case vượt ngưỡng
D. Lập trình viên trong đội, kiêm nhiệm bảo mật, tự xử lý việc bảo mật hằng ngày và chuyển VinSOC case vượt ngưỡng
[DevSecOps - Câu 16] Champion điều phối đội phát triển chuẩn bị tạo ticket yêu cầu VinSOC pentest. Trước khi tạo ticket, đội phải làm gì?
A. Tự quét bằng Tutus và AI với skill của VinSOC; sửa toàn bộ lỗi thật, đóng false positive kèm lý do; đính kèm báo cáo vào ticket B. Tự quét bằng Tutus và AI với skill của VinSOC; sửa toàn bộ lỗi thật, để VinSOC xác nhận false positive; gửi báo cáo cho AppSec qua email C. Tự quét bằng Tutus và AI với skill của VinSOC; sửa lỗi Critical/High, đóng false positive kèm lý do; gửi báo cáo cho AppSec qua email D. Tự quét bằng Tutus và AI với skill của VinSOC; sửa lỗi Critical/High, để VinSOC xác nhận false positive; đính kèm báo cáo vào ticket
A. Tự quét bằng Tutus và AI với skill của VinSOC; sửa toàn bộ lỗi thật, đóng false positive kèm lý do; đính kèm báo cáo vào ticket
[DevSecOps - Câu 17] Semgrep quét một MR và trả về 12 finding. Champion xem lại thì thấy 4 finding là false positive, 8 finding là lỗi SQL injection và path traversal thật trong code của đội. Champion nên làm gì?
A. Chuyển cả 12 finding cho VinSOC xác nhận trước, vì việc đóng finding của tool quét cần VinSOC phê duyệt B. Tắt các rule Semgrep sinh ra 4 false positive trong cấu hình pipeline, cho đội sửa 8 lỗi thật rồi duyệt MR C. Đóng 4 false positive kèm lý do, cho đội sửa 8 lỗi thật, và chỉ duyệt MR khi MR đã pass SAST D. Đóng 4 false positive kèm lý do, duyệt MR ngay và tạo ticket để đội sửa 8 lỗi thật trong sprint sau
C. Đóng 4 false positive kèm lý do, cho đội sửa 8 lỗi thật, và chỉ duyệt MR khi MR đã pass SAST
[OWASP Web - Câu 1] Nhận định nào về phòng chống SQL Injection là đúng?
A. Stored procedure dùng EXEC với chuỗi ghép từ tham số vẫn an toàn, vì tham số đã được bind khi ứng dụng gọi qua CallableStatement B. ORM sinh truy vấn tham số hóa ở API chuẩn; các hàm raw/native query có ghép chuỗi thì không được ORM bảo vệ C. mysqli_real_escape_string() bảo vệ được tham số kiểu số đặt ngoài dấu nháy, như WHERE id = $id D. Cấp cho tài khoản DB của ứng dụng chỉ quyền SELECT sẽ ngăn được SQL Injection, vì câu lệnh chèn thêm bị DBMS từ chối
B. ORM sinh truy vấn tham số hóa ở API chuẩn; các hàm raw/native query có ghép chuỗi thì không được ORM bảo vệ
[OWASP Web - Câu 2] Trường hợp nào là ví dụ điển hình của nhóm Insecure Design (A04:2021)?
A. Đặc tả khôi phục mật khẩu dùng câu hỏi bí mật dễ tra cứu, không giới hạn số lần trả lời B. Máy chủ production để bật trang lỗi chi tiết, hiển thị stack trace và phiên bản framework cho người dùng C. Ứng dụng dùng một bản thư viện JSON có lỗ hổng đã được công bố CVE từ năm trước D. Hàm tìm kiếm ghép trực tiếp từ khóa người dùng nhập vào câu lệnh SQL
A. Đặc tả khôi phục mật khẩu dùng câu hỏi bí mật dễ tra cứu, không giới hạn số lần trả lời
[OWASP Web - Câu 3] API GET /orders/{id}: gateway đã xác thực JWT và chỉ cho role customer đi qua; service đọc đơn theo id rồi trả về. Pentest dùng tài khoản customer A xem được đơn của customer B. Cách sửa đúng?
A. Đổi id đơn hàng từ số tuần tự sang UUIDv4 để A không đoán được id đơn của B B. Kiểm tra lại role customer ngay trong service, phòng request đi vòng qua gateway C. Ghi log mọi lần xem đơn và cảnh báo khi một tài khoản xem quá 100 đơn mỗi giờ D. Trong service, chỉ trả đơn khi order.customer_id trùng với user lấy từ token
D. Trong service, chỉ trả đơn khi order.customer_id trùng với user lấy từ token
[OWASP Web - Câu 4] Pentest báo lỗi CSRF ở chức năng xóa tài khoản, được gọi bằng request: GET /account/delete?confirm=1 Đội phát triển phản hồi: cookie phiên đã đặt SameSite=Lax nên trình duyệt không gửi cookie trong request từ site khác, đề nghị đóng finding. Đánh giá đúng nhất?
A. Phản hồi hợp lý: SameSite=Lax chặn cookie trong request khởi tạo từ site khác, nên có thể đóng finding này B. Lax vẫn gửi cookie khi điều hướng cấp cao nhất bằng GET (vd bấm link), nên cần đổi sang POST kèm CSRF token C. Nên đổi cookie sang SameSite=None kèm Secure để trình duyệt kiểm tra header Origin trước khi gửi cookie đi D. Giữ phương thức GET, bổ sung kiểm tra header Referer có chứa chuỗi tên miền của site, rồi đóng finding
B. Lax vẫn gửi cookie khi điều hướng cấp cao nhất bằng GET (vd bấm link), nên cần đổi sang POST kèm CSRF token
[OWASP Web - Câu 5] Ứng dụng web dùng session phía server và chấp nhận session ID qua cookie hoặc tham số URL. Kẻ tấn công lấy một session ID hợp lệ (chưa đăng nhập), gửi cho nạn nhân link chứa session ID đó; nạn nhân bấm link rồi đăng nhập; kẻ tấn công dùng chính session ID này vào được tài khoản nạn nhân. Biện pháp nào chặn đúng kịch bản này?
A. Đặt cờ HttpOnly và Secure cho cookie phiên B. Đặt SameSite=Strict cho cookie phiên C. Cấp session ID mới ngay sau khi đăng nhập thành công D. Giảm thời gian hết hạn phiên xuống 15 phút không hoạt động
C. Cấp session ID mới ngay sau khi đăng nhập thành công
[OWASP Web - Câu 6] DAST trên production phát hiện /actuator/env và /actuator/heapdump của một service Spring Boot truy cập được mà không cần đăng nhập; application-prod.yml có management.endpoints.web.exposure.include=*. Xử lý gốc đúng nhất?
A. Sửa cấu hình prod chỉ expose health, và đưa kiểm tra cấu hình actuator vào baseline của pipeline B. Nâng Spring Boot lên bản mới nhất, vì các bản mới mặc định chỉ mở endpoint health qua web C. Thêm luật WAF chặn đường dẫn /actuator/*, giữ nguyên cấu hình ứng dụng để giám sát nội bộ D. Đổi management.server.port sang một cổng không công bố để scanner bên ngoài không tìm thấy
A. Sửa cấu hình prod chỉ expose health, và đưa kiểm tra cấu hình actuator vào baseline của pipeline
[OWASP Web - Câu 7] SCA báo một thư viện JS phía client (dependency transitive qua một UI kit) có CVE mức High đã có bản vá; UI kit chưa ra bản mới; lockfile đang ghim bản lỗi. Cách xử lý đúng?
A. Xóa package-lock.json rồi chạy npm install để kéo bản mới nhất của mọi dependency trong khoảng semver
B. Chuyển sang nạp thư viện đó từ CDN công khai bằng thẻ
C. Giữ bản đang ghim trong lockfile, chờ UI kit phát hành bản mới rồi nâng một lần cho đồng bộ
D. Dùng overrides/resolutions ép thư viện lên bản đã vá, chạy lại test của UI kit và cập nhật SBOM
D. Dùng overrides/resolutions ép thư viện lên bản đã vá, chạy lại test của UI kit và cập nhật SBOM
[OWASP Web - Câu 8] Biện pháp nào phòng chống SSRF đúng bản chất nhất cho tính năng tải nội dung từ URL người dùng nhập?
A. Chỉ chấp nhận URL dùng https có chứng chỉ hợp lệ, vì dịch vụ nội bộ thường không có chứng chỉ công khai B. Resolve DNS, kiểm tra IP không thuộc dải nội bộ/link-local, rồi để thư viện HTTP tự resolve lại khi kết nối C. Resolve DNS, kiểm tra IP không thuộc dải nội bộ/link-local, rồi kết nối thẳng tới chính IP đã kiểm tra D. Đặt egress proxy chặn các cổng quản trị như 22 và 3389, giữ mở các cổng web
C. Resolve DNS, kiểm tra IP không thuộc dải nội bộ/link-local, rồi kết nối thẳng tới chính IP đã kiểm tra
[OWASP Web - Câu 9] Ứng dụng ghi nguyên request body (gồm cả mật khẩu khi đăng nhập) vào file log trên chính máy chủ; một IP thử sai mật khẩu 5.000 lần/giờ mà không ai được báo. Thay đổi nào khắc phục đúng cả hai vấn đề?
A. Mã hóa file log bằng khóa lưu trên máy chủ; dùng APM theo dõi tỷ lệ HTTP 401 trên dashboard B. Che/loại mật khẩu, token trước khi ghi; đẩy log về SIEM tập trung, đặt cảnh báo theo ngưỡng đăng nhập sai C. Giữ log body đầy đủ cho điều tra nhưng chỉ cho admin đọc; đặt rate limit đăng nhập ở gateway D. Hạ mức log xuống WARN để bỏ request body; bật log rotation 7 ngày cho gọn ổ đĩa
B. Che/loại mật khẩu, token trước khi ghi; đẩy log về SIEM tập trung, đặt cảnh báo theo ngưỡng đăng nhập sai
[OWASP Web - Câu 10] Đoạn PHP sau đã ép kiểu id nhưng vẫn bị SQL Injection qua tham số sort. Cách sửa đúng cho $sort là gì? $id = (int)$_GET['id']; $sort = $_GET['sort']; $sql = "SELECT * FROM users WHERE id = $id ORDER BY $sort"; res=mysqliquery(conn, $sql);
A. Bọc $sort bằng mysqli_real_escape_string() trước khi ghép vào câu truy vấn B. Chuyển sang prepared statement và bind $sort vào placeholder như các giá trị khác C. Đối chiếu $sort với danh sách tên cột cho phép, giá trị lạ thì dùng cột mặc định D. Lọc $sort bằng htmlspecialchars() trước khi ghép vào câu truy vấn
C. Đối chiếu $sort với danh sách tên cột cho phép, giá trị lạ thì dùng cột mặc định
[OWASP Web - Câu 11] Đoạn Node/Express sau bị Reflected XSS dù đã loại thẻ
A. Mã hóa HTML (entity encoding) giá trị name khi chèn vào response
B. Mở rộng regex để loại thêm các thẻ img, svg, iframe và object khỏi name
C. Thêm header X-XSS-Protection: 1; mode=block cho response
D. Chuyển name từ query string sang body POST trước khi xử lý
A. Mã hóa HTML (entity encoding) giá trị name khi chèn vào response
[OWASP Web - Câu 12] Đoạn Java sau kiểm tra thư mục gốc bằng startsWith nhưng vẫn bị path traversal. Cách sửa đúng? String name = request.getParameter("file"); File f = new File("/var/app/files/" + name); if (!f.getPath().startsWith("/var/app/files/")) throw new IllegalArgumentException("invalid file"); return Files.readAllBytes(f.toPath());
A. Gọi name.replace("../", "") trước khi tạo đối tượng File B. Kiểm tra name không bắt đầu bằng "/" để chặn đường dẫn tuyệt đối C. URL-encode tham số name trước khi ghép vào đường dẫn file D. So sánh startsWith trên getCanonicalPath() thay cho getPath()
D. So sánh startsWith trên getCanonicalPath() thay cho getPath()
[OWASP Web - Câu 13] Đoạn Python sau đã chặn các ký tự ; | & nhưng vẫn bị chèn lệnh. Cách sửa phù hợp nhất? import os host = request.args.get('host') if any(c in host for c in [';','|','&']): abort(400) os.system("ping -c 1 " + host)
A. Chặn thêm các ký tự $, `, <, >, dấu cách và ký tự xuống dòng trong host
B. Gọi subprocess.run với list tham số, shell=False, và chỉ nhận host đúng định dạng IP/hostname
C. Bọc host trong dấu nháy kép khi ghép vào chuỗi lệnh và giới hạn độ dài tối đa 255 ký tự
D. Đổi sang subprocess.run("ping -c 1 " + host, shell=True, check=True) để bắt được mã lỗi trả về
B. Gọi subprocess.run với list tham số, shell=False, và chỉ nhận host đúng định dạng IP/hostname
[OWASP Web - Câu 14] Đặc tả: mỗi hóa đơn thuộc riêng người tạo; chỉ người tạo và người có vai trò kế toán cùng tổ chức được xem. API hiện tại: @app.get("/invoice/
A. Nhân viên đổi id trên URL để xem hóa đơn của đồng nghiệp cùng tổ chức B. Nhân viên tổ chức X đổi id để xem hóa đơn của tổ chức Y C. Kế toán xem hóa đơn của một nhân viên bất kỳ trong cùng tổ chức mình D. Người tạo hóa đơn xem lại hóa đơn của chính mình sau khi đổi mật khẩu
A. Nhân viên đổi id trên URL để xem hóa đơn của đồng nghiệp cùng tổ chức
[OWASP Web - Câu 15] Lập trình viên lưu mật khẩu như sau. Cách cải thiện đúng nhất? salt = os.urandom(16) digest = sha256(salt + password).hexdigest() db.save(user, salt, digest)
A. Đổi sang SHA-512 và tăng độ dài salt lên 32 byte để chống tấn công brute-force B. Thêm pepper bí mật lưu ngoài cơ sở dữ liệu, vẫn giữ SHA-256 có salt như hiện tại C. Thay bằng Argon2id/bcrypt/scrypt với salt riêng và tham số chi phí phù hợp D. Băm hai lần sha256(sha256(salt + password)) để tăng độ khó
C. Thay bằng Argon2id/bcrypt/scrypt với salt riêng và tham số chi phí phù hợp
[OWASP Web - Câu 16] Đoạn Python sau kiểm tra kiểu sau khi giải tuần tự. Vì sao bước kiểm tra không bảo vệ được và nên sửa thế nào? data = pickle.loads(request.body) if not isinstance(data, dict): abort(400)
A. isinstance bỏ sót lớp con của dict có thể ghi đè phương thức; đổi sang kiểm tra type(data) is dict B. Payload lớn làm cạn bộ nhớ; giới hạn kích thước request body trước khi loads C. Payload lỗi làm tiến trình crash; bọc pickle.loads trong try/except và ghi log D. Mã độc chạy ngay trong pickle.loads, trước isinstance; đổi sang JSON và validate schema
D. Mã độc chạy ngay trong pickle.loads, trước isinstance; đổi sang JSON và validate schema
[OWASP Web - Câu 17] Đoạn code sau đã kiểm tra URL bắt đầu bằng địa chỉ API của đối tác. Đường khai thác SSRF nào còn lại? url = request.args.get('url') if not url.startswith("https://api.partner.com/"): abort(400) r = requests.get(url, allow_redirects=True) return r.text
A. Chèn userinfo dạng https://api.partner.com@10.0.0.5/ để đổi host đích mà vẫn qua kiểm tra B. URL hợp lệ của đối tác trả 302 sang địa chỉ nội bộ và requests tự đi theo C. Đổi scheme sang http:// để vượt qua kiểm tra prefix D. Dùng dạng IP thập phân của máy chủ đối tác thay cho tên miền
B. URL hợp lệ của đối tác trả 302 sang địa chỉ nội bộ và requests tự đi theo
[OWASP Web - Câu 18] Đoạn code sau chỉ cho chuyển hướng tới đường dẫn bắt đầu bằng "/" nhưng vẫn bị Open Redirect. Cách sửa đúng? next = request.args.get('next') if not next.startswith("/"): abort(400) return redirect(next)
A. Chặn thêm các giá trị next bắt đầu bằng "http://" hoặc "https://" (không phân biệt hoa thường) B. URL-encode toàn bộ giá trị next trước khi truyền vào hàm redirect của framework C. Từ chối next có scheme/host hoặc bắt đầu bằng // hay /\, rồi so allowlist D. Chỉ chấp nhận next nếu chuỗi có chứa tên miền chính thức của site ở bất kỳ vị trí nào
C. Từ chối next có scheme/host hoặc bắt đầu bằng // hay /\, rồi so allowlist
[OWASP Web - Câu 19] Lập trình viên đặt setExpandEntityReferences(false) và cho rằng đã chặn XXE. Cấu hình nào mới chặn được XXE cho parser này? DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(userInput);
A. Bật feature disallow-doctype-decl và tắt external general/parameter entities B. Giữ setExpandEntityReferences(false) và validate tài liệu theo XSD trước khi xử lý C. Bật setValidating(true) để parser từ chối tài liệu không khớp DTD khai báo D. Lọc chuỗi "<!ENTITY" trong userInput trước khi gọi db.parse()
A. Bật feature disallow-doctype-decl và tắt external general/parameter entities
[OWASP Web - Câu 20] Lập trình viên đã loại field isAdmin trước khi cập nhật hồ sơ. Cách sửa đúng để chặn leo thang quyền qua request này? body = request.get_json() body.pop('isAdmin', None) user.update(body)
A. Pop thêm các field nhạy cảm role, is_staff, group_id cùng với isAdmin trước khi update B. Từ chối body có key bắt đầu bằng "is" trước khi gọi update C. Gọi user.update(body) rồi đặt lại isAdmin = False ngay sau đó trong cùng transaction D. Chỉ lấy các field trong allowlist (DTO/serializer) rồi mới cập nhật user
D. Chỉ lấy các field trong allowlist (DTO/serializer) rồi mới cập nhật user
[OWASP Web - Câu 21] Server Node.js dùng thư viện jsonwebtoken 8.5.1, có RSA public key (công khai) và xác thực JWT như sau. Kẻ tấn công có thể làm gì nghiêm trọng nhất? jwt.verify(token, publicKey, { algorithms: ['RS256','HS256'] })
A. Gửi token có alg "none" không kèm chữ ký và token vẫn được server chấp nhận B. Ký token HS256 dùng chính RSA public key làm khóa HMAC và token được chấp nhận C. Dùng lại token đã hết hạn vì hàm verify không tự kiểm tra claim exp D. Sửa header kid để server tải khóa xác thực từ một URL do kẻ tấn công chỉ định
B. Ký token HS256 dùng chính RSA public key làm khóa HMAC và token được chấp nhận
[OWASP Web - Câu 22] SCA báo log4j-core 2.14.1 (Log4Shell) xuất hiện như dependency transitive qua một thư viện khác; đội vận hành đã thêm luật WAF chặn chuỗi "${jndi:". Hành động đúng và ưu tiên nhất?
A. Ép log4j-core lên bản đã vá (≥ 2.17.1) qua dependency management dù là transitive; WAF chỉ tạm thời B. Giữ luật WAF làm biện pháp chính, theo dõi log để bổ sung luật cho các biến thể payload mới xuất hiện C. Nâng JDK lên bản mới đặt trustURLCodebase=false, giữ nguyên log4j-core 2.14.1 trong dự án D. Chờ thư viện cha phát hành bản mới kéo theo log4j đã vá, trong lúc đó giữ luật WAF
A. Ép log4j-core lên bản đã vá (≥ 2.17.1) qua dependency management dù là transitive; WAF chỉ tạm thời
[OWASP Web - Câu 23] Site công khai đang chạy production bị DAST báo thiếu CSP và HSTS. Một thành viên đề xuất bật ngay CSP enforce "default-src https:" và HSTS preload (max-age 2 năm) trên toàn site. Cách triển khai hợp lý nhất?
A. Bật ngay CSP enforce và HSTS preload như đề xuất, xử lý các tài nguyên bị chặn nhầm khi người dùng phản ánh B. Bỏ CSP vì WAF đã lọc payload XSS ở vòng ngoài; chỉ bật HSTS preload 2 năm C. Bật CSP enforce ngay; hoãn HSTS vì header này chỉ có tác dụng với kết nối HTTP/2 D. Chạy CSP Report-Only để tinh chỉnh rồi mới enforce; tăng max-age HSTS dần trước khi đăng ký preload
D. Chạy CSP Report-Only để tinh chỉnh rồi mới enforce; tăng max-age HSTS dần trước khi đăng ký preload
[OWASP Web - Câu 24] SAST cảnh báo "SQL built from string concatenation" tại đoạn Java sau (ids đã được kiểm tra khác rỗng và tối đa 100 phần tử). Champion nên kết luận gì? List
A. Lỗ hổng thật: req.dir được ghép vào ORDER BY B. Lỗ hổng thật: số dấu ? do người dùng quyết định C. False positive: chỉ hằng số trong allowlist và dấu ? được ghép D. Lỗ hổng thật: contains() không phân biệt hoa thường
C. False positive: chỉ hằng số trong allowlist và dấu ? được ghép
[OWASP Web - Câu 25] Log cho thấy tính năng "import ảnh từ URL" (app trên AWS EC2) đã gửi request tới http://169.254.169.254/latest/meta-data/iam/security-credentials/ và tới http://[::ffff:169.254.169.254]/. Đội đề xuất bật IMDSv2. Kết luận và hướng xử lý đúng nhất?
A. SSRF đang bị khai thác lấy credential IAM; bật IMDSv2, chặn link-local ở ứng dụng (cả dạng IPv6-mapped), thu hồi credential đã lộ B. SSRF đang bị khai thác; bật IMDSv2 và thêm chuỗi "169.254.169.254" vào danh sách chặn của URL người dùng nhập C. Chỉ là quét tự động vì metadata service chỉ trả thông tin cấu hình; bật IMDSv2 để giảm nhiễu log D. SSRF đang bị khai thác; bật IMDSv2, chặn link-local ở ứng dụng (cả dạng IPv6-mapped), giữ credential hiện tại vì sẽ tự hết hạn
A. SSRF đang bị khai thác lấy credential IAM; bật IMDSv2, chặn link-local ở ứng dụng (cả dạng IPv6-mapped), thu hồi credential đã lộ
[Mobile - Câu 1] Phát biểu nào đúng về SharedPreferences trên Android?
A. MODE_PRIVATE mã hóa file XML bằng khóa gắn với chữ ký của app B. allowBackup="false" chặn cả adb backup lẫn việc đọc thư mục dữ liệu app trên máy đã root C. SharedPreferences lưu XML dạng rõ; MODE_PRIVATE chỉ là quyền file theo UID của app D. Từ Android 10, mỗi file SharedPreferences được mã hóa bằng khóa riêng của app trong Keystore
C. SharedPreferences lưu XML dạng rõ; MODE_PRIVATE chỉ là quyền file theo UID của app
[Mobile - Câu 2] App mobile cần mã hóa dữ liệu nhạy cảm trước khi lưu cục bộ. Cách làm nào đúng?
A. AES-GCM, khóa sinh và giữ trong Android Keystore/iOS Keychain, nonce ngẫu nhiên mới mỗi lần B. AES-GCM, khóa 256-bit hằng trong code đã làm rối bằng R8, nonce cố định lưu kèm theo dữ liệu C. AES-ECB, khóa sinh và giữ trong Android Keystore/iOS Keychain, không cần quản lý IV D. AES-ECB, khóa 256-bit hằng trong code đã làm rối bằng R8 để kẻ dịch ngược khó đọc được khóa
A. AES-GCM, khóa sinh và giữ trong Android Keystore/iOS Keychain, nonce ngẫu nhiên mới mỗi lần
[Mobile - Câu 3] Đoạn Kotlin sau lưu token sau khi đăng nhập. Đánh giá nào đúng? val prefs = getSharedPreferences("auth", Context.MODE_PRIVATE) prefs.edit().putString("access_token", response.accessToken).apply() prefs.edit().putString("refresh_token", response.refreshToken).apply()
A. Lỗi chính là gọi apply() hai lần liên tiếp; ghi bất đồng bộ có thể làm mất refresh_token khi app bị kill, nên đổi sang commit() B. Token lưu dạng rõ trong file XML; người đọc được thư mục dữ liệu app (root, bản backup) sẽ lấy được. Cần mã hóa bằng khóa Keystore C. MODE_PRIVATE đã giới hạn file cho riêng UID của app, nên trên thiết bị chưa root cách lưu này đáp ứng yêu cầu lưu trữ an toàn D. Nên tách access_token và refresh_token sang hai file preferences khác tên, để lộ một file không kéo theo token còn lại
B. Token lưu dạng rõ trong file XML; người đọc được thư mục dữ liệu app (root, bản backup) sẽ lấy được. Cần mã hóa bằng khóa Keystore
[Mobile - Câu 4] Pentester dùng adb backup trên máy chưa root (app targetSdk 30, không khai báo allowBackup) và đọc được token trong SharedPreferences dù app dùng MODE_PRIVATE. Biện pháp nào chặn đúng vector tấn công trong tình huống này?
A. Chuyển token sang database SQLite, vì adb backup mặc định chỉ sao lưu thư mục shared_prefs của app B. Lưu token trong getExternalFilesDir(), vì thư mục này không nằm trong bản adb backup của app C. Khai báo android:debuggable="false", vì adb chỉ truy cập được dữ liệu của app ở chế độ debug D. Đặt android:allowBackup="false" hoặc loại file preferences chứa token khỏi backup rules
D. Đặt android:allowBackup="false" hoặc loại file preferences chứa token khỏi backup rules
[Mobile - Câu 5] Khác biệt bảo mật quan trọng nhất giữa custom URL scheme (myapp://) và Android App Links (https://) là gì?
A. App Links mã hóa tham số trên URL bằng HTTPS khi hệ điều hành chuyển link cho app, còn custom scheme chuyển tham số dưới dạng văn bản rõ B. Custom scheme không xác minh chủ sở hữu, app khác đăng ký trùng để nhận link; App Links được xác minh qua assetlinks.json trên domain C. Custom scheme an toàn hơn vì link myapp:// không mở được từ trình duyệt, nên trang web lừa đảo không kích hoạt được app D. Hai loại tương đương về bảo mật vì Android chỉ chuyển link cho app mà người dùng đã chọn làm mặc định trong hộp thoại
B. Custom scheme không xác minh chủ sở hữu, app khác đăng ký trùng để nhận link; App Links được xác minh qua assetlinks.json trên domain
[Mobile - Câu 6] Activity sau (exported, nhận deep link myapp://page) mở trang trong WebView của app; WebView bật JavaScript và có addJavascriptInterface. Đánh giá nào đúng? val uri = intent.data val redirectUrl = uri?.getQueryParameter("redirect") webView.loadUrl(redirectUrl ?: "https://app.example.com/home")
A. Tham số redirect được nạp thẳng vào WebView có bridge; kẻ tấn công đưa trang của mình hoặc javascript: vào. Cần allowlist scheme https và host B. Cần URL-encode giá trị redirect trước khi gọi loadUrl, để các ký tự đặc biệt trong link không bị WebView hiểu thành mã lệnh C. Cần đặt android:exported="false" cho Activity để app khác không gửi được Intent; link mở từ trình duyệt vẫn được chuyển vào app D. Cần kiểm tra redirect bắt đầu bằng "https://" trước khi nạp, vì trang dùng HTTPS với chứng chỉ hợp lệ thì không thể là trang giả mạo của kẻ tấn công
A. Tham số redirect được nạp thẳng vào WebView có bridge; kẻ tấn công đưa trang của mình hoặc javascript: vào. Cần allowlist scheme https và host
[Mobile - Câu 7] Backend gửi email chứa link myapp://auth?token=
A. Force unwrap token! làm app crash khi link thiếu tham số; kẻ tấn công gửi link lỗi liên tục để người dùng không mở được app B. Hàm không kiểm tra options[.sourceApplication]; chấp nhận link khi nó đến từ Safari hoặc Mail sẽ chặn được app giả mạo C. Token đăng nhập đi qua custom scheme: app khác đăng ký cùng scheme có thể nhận link và lấy token. Nên dùng Universal Links với mã một lần D. Phép so sánh url.scheme phân biệt hoa thường; kẻ tấn công gửi MYAPP://auth để đi vòng qua điều kiện kiểm tra của app
C. Token đăng nhập đi qua custom scheme: app khác đăng ký cùng scheme có thể nhận link và lấy token. Nên dùng Universal Links với mã một lần
[Mobile - Câu 8] Khi nâng targetSdkVersion lên 31, build báo lỗi "android:exported needs to be explicitly specified" cho DeepLinkActivity. Activity này có intent-filter VIEW/BROWSABLE để nhận link https://shop.example.com/… từ trình duyệt. Xử lý nào đúng?
A. Đặt exported="false" để chặn app độc gọi vào; link mở từ trình duyệt vẫn đến được Activity vì đó là Intent do hệ thống gửi B. Đặt exported="true" và thêm android:permission là một quyền signature riêng, để chỉ app cùng chữ ký và trình duyệt hệ thống gọi được C. Hạ targetSdkVersion về 30 để giữ giá trị exported ngầm định như trước, rồi xử lý dần khi có thời gian ở bản sau D. Đặt exported="true" vì trình duyệt và app khác phải gọi được Activity, và coi mọi dữ liệu trong Intent là đầu vào không tin cậy
D. Đặt exported="true" vì trình duyệt và app khác phải gọi được Activity, và coi mọi dữ liệu trong Intent là đầu vào không tin cậy
[Mobile - Câu 9] Phát biểu nào về certificate pinning trong app mobile là đúng?
A. Pin public key (SPKI) cho phép gia hạn chứng chỉ với cùng key mà không cần cập nhật app; nên có ít nhất một backup pin B. Pin theo chứng chỉ leaf an toàn hơn pin public key, vì mỗi lần gia hạn chứng chỉ đều buộc phát hành app với pin mới C. Pinning ngăn được MITM cả trên máy đã root, vì việc so pin diễn ra trong thư viện TLS trước khi dữ liệu tới tầng ứng dụng D. Không nên thêm backup pin, vì mỗi pin dự phòng là thêm một khóa mà kẻ tấn công có thể nhắm tới để giả mạo máy chủ
A. Pin public key (SPKI) cho phép gia hạn chứng chỉ với cùng key mà không cần cập nhật app; nên có ít nhất một backup pin
[Mobile - Câu 10] Đoạn OkHttp sau pin theo hash khóa của CA trung gian đang cấp chứng chỉ cho api.example.com. Đánh giá nào đúng? val client = OkHttpClient.Builder() .certificatePinner( CertificatePinner.Builder() .add("api.example.com", "sha256/
A. Cấu hình hợp lệ: đã pin thì kiểm tra hostname là thừa, và tắt nó giúp app tránh lỗi khi máy chủ phục vụ nhiều tên miền phụ B. Chứng chỉ cho domain khác do cùng CA cấp vẫn khớp pin; hostname verifier luôn trả true nên kẻ tấn công dùng chứng chỉ đó để MITM C. Pin đang dùng SHA-256; OkHttp so pin chứng chỉ trung gian bằng SHA-1 nên pin này bị bỏ qua và app chấp nhận mọi chứng chỉ D. Rủi ro là pin nằm trong code nên bị Frida gỡ; chuyển cùng cấu hình sang network_security_config.xml sẽ xử lý được lỗi này của app
B. Chứng chỉ cho domain khác do cùng CA cấp vẫn khớp pin; hostname verifier luôn trả true nên kẻ tấn công dùng chứng chỉ đó để MITM
[Mobile - Câu 11] Pentester dùng Frida gỡ certificate pinning thành công trên máy đã root và đọc được toàn bộ API của app. Đội muốn tăng cường. Hướng nào đúng nhất?
A. Chuyển sang mTLS với client certificate đóng gói trong app, để chỉ app thật mới gọi được API B. Thêm root detection và chặn chạy trên máy root, vì Frida cần quyền root để hook vào app C. Bỏ pinning vì đã bị gỡ, chuyển nỗ lực sang giám sát bất thường phía server để phát hiện lưu lượng do công cụ tạo ra D. Giữ pinning và thêm phát hiện hooking để tăng chi phí tấn công; các kiểm soát quyết định như xác thực, phân quyền, giới hạn đặt ở server
D. Giữ pinning và thêm phát hiện hooking để tăng chi phí tấn công; các kiểm soát quyết định như xác thực, phân quyền, giới hạn đặt ở server
[Mobile - Câu 12] File network_security_config.xml của app có đoạn sau để tester dùng Burp với bản debug. Bản release được build bằng cấu hình release mặc định (debuggable=false). Nhận định nào đúng về bản release?
A. Bản release tin cả CA do người dùng cài, nên ai cài được CA giả vào máy nạn nhân đều MITM được lưu lượng của app B. Bản release chỉ tin CA người dùng khi máy bật Developer options, nên cần xóa đoạn này trước khi phát hành để chặn trường hợp đó C. Bản release không bị ảnh hưởng: debug-overrides chỉ áp dụng khi android:debuggable="true"; cần giữ cho bản release không bật debuggable D. debug-overrides chỉ được áp dụng khi app chạy trên emulator, nên bản release cài trên máy thật của người dùng cuối không hề bị ảnh hưởng
C. Bản release không bị ảnh hưởng: debug-overrides chỉ áp dụng khi android:debuggable="true"; cần giữ cho bản release không bật debuggable
[Mobile - Câu 13] Cách quản lý token nào trong app mobile là đúng?
A. Access token ngắn hạn, refresh token lưu bằng Keystore/Keychain; đăng xuất thì xóa token trên máy và thu hồi phía server B. Access token dài hạn (30 ngày) lưu bằng Keystore/Keychain để giảm số lần refresh; đăng xuất thì xóa token trên máy C. Access token ngắn hạn, refresh token lưu trong SharedPreferences (MODE_PRIVATE); đăng xuất thì xóa token trên máy D. Access token dài hạn (30 ngày) lưu trong SharedPreferences (MODE_PRIVATE); đăng xuất thì xóa token trên máy và thu hồi phía server
A. Access token ngắn hạn, refresh token lưu bằng Keystore/Keychain; đăng xuất thì xóa token trên máy và thu hồi phía server
[Mobile - Câu 14] Màn hình mở ví dùng vân tay như sau (promptInfo đặt BIOMETRIC_STRONG, không truyền CryptoObject). Điểm yếu chính là gì? val prompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded( result: BiometricPrompt.AuthenticationResult) { isAuthenticated = true val token = prefs.getString("stored_token", null) openWallet(token) } }) prompt.authenticate(promptInfo)
A. Luồng xác thực không vượt được vì callback do hệ thống gọi sau khi phần cứng xác thực; điểm cần thêm là timeout tự khóa lại ví B. Token đang lưu dạng rõ; chuyển stored_token sang EncryptedSharedPreferences là khắc phục được điểm yếu chính của luồng sinh trắc này C. BIOMETRIC_STRONG vẫn chấp nhận nhận diện khuôn mặt 2D; cần giới hạn chỉ dùng vân tay để chống giả mạo bằng ảnh chụp D. Sinh trắc chỉ dẫn tới một nhánh code nên hook callback bằng Frida là vượt được; cần CryptoObject gắn khóa Keystore cần xác thực
D. Sinh trắc chỉ dẫn tới một nhánh code nên hook callback bằng Frida là vượt được; cần CryptoObject gắn khóa Keystore cần xác thực
[Mobile - Câu 15] App dùng đoạn sau để quyết định có hiện và cho gọi các chức năng quản trị hay không. Nhận định nào đúng? val token = prefs.getString("access_token", "") val parts = token!!.split(".") val payload = String(Base64.decode(parts[1], Base64.URL_SAFE)) val isAdmin = JSONObject(payload).getBoolean("isAdmin")
A. Cần verify chữ ký JWT ngay trên app bằng khóa HMAC nhúng trong app trước khi đọc isAdmin, để payload bị sửa sẽ bị từ chối B. Quyền được quyết định ở client từ dữ liệu người dùng sửa được; server phải kiểm tra quyền quản trị cho từng request C. Lỗi là dùng Base64.URL_SAFE; JWT dùng Base64 chuẩn có padding nên payload có thể bị giải mã sai và đọc nhầm quyền D. Cần lưu token trong EncryptedSharedPreferences; khi đó người dùng không sửa được payload nên đọc isAdmin từ token là đáng tin
B. Quyền được quyết định ở client từ dữ liệu người dùng sửa được; server phải kiểm tra quyền quản trị cho từng request