1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • FFmpeg, phần mềm xử lý media trên các trình duyệt và hạ tầng streaming toàn cầu, trở thành một bề mặt tấn công quan trọng về bảo mật vì phải phân tích các đầu vào phức tạp và không đáng tin cậy
  • Tác nhân bảo mật tự động của depthfirst đã tìm ra 21 lỗ hổng zero-day trong khoảng 1,5 triệu dòng mã C được tối ưu hóa, với chi phí khoảng $1k, tương đương 10% mức $10k mà Anthropic đã dùng cho Mythos
  • Các phát hiện trải rộng trên nhiều thành phần như TS demuxer, VP9 decoder và các đường xử lý RTP/RTSP/RTMP; một số lỗ hổng đã tồn tại âm thầm suốt 15–20 năm
  • Lỗ hổng trong AV1 RTP depacketizer dẫn tới PoC ghi đè con trỏ hàm chỉ với một gói RTP 183 byte, và có thể chạm tới chỉ bằng cách chạy ffmpeg -i rtsp://attacker/stream
  • Việc kiểm chứng bảo mật thực chất đòi hỏi không chỉ cảnh báo lý thuyết mà còn cả đầu vào có thể tái hiện và xác nhận thực thi; phân tích kiểu tác nhân có thể được áp dụng trực tiếp để tìm lỗ hổng ẩn trong các codebase C quy mô lớn

Tổng quan

  • FFmpeg là phần mềm được triển khai rộng rãi để xử lý media trong trình duyệt và hạ tầng của các nền tảng streaming lớn
  • Vì là thư viện liên tục phân tích media phức tạp và không đáng tin cậy nên nó có tầm quan trọng lớn về bảo mật, đồng thời là mục tiêu chính của các cuộc tấn công zero-click
  • Kho mã FFmpeg gồm khoảng 1,5 triệu dòng mã C được tối ưu hóa cao, và phân tích hàng trăm định dạng media phức tạp
  • FFmpeg đã trải qua hơn 20 năm fuzzing và kiểm toán thủ công; gần đây nhóm Google Big Sleep đã công bố 13 lỗ hổng trong FFmpeg
  • Anthropic đã quét FFmpeg bằng mô hình Mythos và phát hiện một số vấn đề bảo mật
  • Sau những nỗ lực đi trước này, việc tìm ra lỗ hổng mới trong FFmpeg trở nên khó hơn, và đây trở thành mục tiêu để kiểm chứng năng lực của các hệ thống kiểu tác nhân trong việc quét sâu các codebase lớn

Tác nhân bảo mật của Depthfirst

  • Tác nhân lập trình và tác nhân bảo mật có thể dùng cùng một mô hình nền tảng, nhưng mục tiêu rất khác nhau
  • Tác nhân lập trình thường tập trung nhận yêu cầu từ con người và viết mã ứng dụng
  • Tác nhân bảo mật đảm nhận vai trò hẹp và định hướng mục tiêu hơn: tìm các vấn đề bảo mật thực sự có thể bị khai thác trong hệ thống sẵn có mà không cần chỉ dẫn cụ thể
  • Tác nhân bảo mật trước hết phải nắm được kiến trúc codebase, các parser và protocol handler lộ diện, cùng các điểm đầu vào do kẻ tấn công kiểm soát
  • Sau đó, thay vì xem kho mã như một tập hợp tệp phẳng, nó lần theo luồng dữ liệu từ mã thuộc bề mặt tấn công sang các thành phần liên quan
  • Một tác nhân bảo mật thực dụng cần các guardrail để không tự bịa ra điều kiện còn thiếu, phóng đại lỗi lý thuyết hoặc tạo ra hàng loạt kết quả dương tính giả
  • Nó phải xác nhận liệu kẻ tấn công có thực sự kiểm soát đúng đầu vào hay không, đường dẫn dễ tổn thương có thể chạm tới không, và lỗi nghi ngờ có tái hiện được không
  • Khi cần, nó phải xác định hoặc tạo harness để tương tác với thành phần mục tiêu và kiểm tra giả thuyết một cách cụ thể
  • Tác nhân bảo mật chuyên biệt của depthfirst phân tích mã ở mức sâu và rẽ nhánh nhiều giả thuyết để thử song song
  • Kết quả đầu ra không phải báo cáo lý thuyết hay cảnh báo mơ hồ, mà là các vấn đề bảo mật cụ thể đã được xác nhận thực thi bằng đầu vào có thể tái hiện

Kết quả phát hiện

  • Tác nhân đã phát hiện tổng cộng 21 zero-day, trải từ TS demuxer đến VP9 decoder
  • Tổng chi phí vào khoảng $1k, tương đương 10% chi phí Anthropic dùng cho Mythos
  • So sánh chi phí: {b:1,10}
  • Các lỗ hổng đã được gán CVE

    • CVE-2026-39210 là lỗi tràn bộ đệm heap trong TS demuxer do thiếu kiểm tra ranh giới độ dài trước khi đọc hai byte, được đưa vào từ năm 2010
    • CVE-2026-39211 là lỗi tràn số nguyên phát sinh trong quá trình refactor swscale, khi công thức hệ số kích thước không có giới hạn trên cho phép tham số do người dùng kiểm soát gây ra mức scaling lớn tùy ý, được đưa vào từ năm 2010
    • CVE-2026-39212 là lỗi tràn ngăn xếp trong ffmpeg_opt.c, nơi tệp preset có thể kích hoạt việc phân tích tùy chọn đệ quy mà không có giới hạn độ sâu; đây là hồi quy từ tháng 7/2025
    • CVE-2026-39213 là lỗi tràn bộ đệm heap trên đường xử lý đầu vào rawvideo của yuv4mpegenc do thiếu kiểm tra kích thước gói theo kích thước khung hình, được đưa vào từ năm 2023
    • CVE-2026-39214 là lỗi tràn bộ đệm ngăn xếp trong triển khai SDT gốc, nơi các service entry được ghi mà không theo dõi không gian còn lại; lỗ hổng được đưa vào từ năm 2003 và tồn tại âm thầm suốt 23 năm
    • CVE-2026-39215 là lỗi tràn bộ đệm heap do lỗi logic trong update_mb_info() khiến lần gọi sau ghi thêm 12 byte sau vùng đệm đã cấp phát, được đưa vào từ năm 2012
    • CVE-2026-39216 là lỗi tràn bộ đệm heap trong img2enc.c do thay kích thước chroma an toàn bằng kích thước không giới hạn dựa trên kích thước khung hình, được đưa vào từ năm 2012
    • CVE-2026-39217 là lỗi tràn bộ đệm heap trong VP9 decoder do hàm cập nhật kích thước được refactor khiến tile thread buffer bỏ lỡ lần cấp phát lại cần thiết; đây là hồi quy từ tháng 3/2025
    • CVE-2026-39218 là lỗi tràn bộ đệm heap trong DASH demuxer do không từ chối giá trị duration âm, khiến chỉ số mảng fragment trở thành số âm; lỗ hổng được đưa vào từ năm 2017
  • Các lỗ hổng được tham chiếu bằng ID theo dõi nội bộ

    • DFVULN-127 là lỗi tràn bộ đệm heap trong RTP AV1 depacketizer: av1_handle_packet() bỏ qua Temporal Delimiter OBU và tăng vị trí đầu ra theo obu_size, nhưng không cấp phát lượng không gian tương ứng, khiến OBU tiếp theo ghi ra ngoài ranh giới bộ đệm
    • DFVULN-126 là lỗi tràn bộ đệm heap trong mã đồ thị swscale: run_legacy_unscaled() xử lý sai chuyển đổi interlaced YUV420P→NV12, khiến Y-plane đích bị ghi quá 576 byte
    • DFVULN-125 là lỗi tràn bộ đệm ngăn xếp trong RTP JPEG depacketizer: khi jpeg_create_header() tạo phần quantization-table trong bộ đệm ngăn xếp 1024 byte, AV_WB16 sau gói có qtable_len >= 1024 sẽ ghi quá cuối 2 byte
    • DFVULN-124 là lỗi tràn bộ đệm heap trên đường AVIF overlay: istg_parse_tile_grid() không từ chối tham chiếu dimg có 0 tile entry, dẫn đến đọc ngoài phạm vi từ một heap allocation 1 byte sau khi xảy ra unsigned wraparound
    • DFVULN-123 là lỗi tràn số nguyên trong RTP LATM depacketizer: latm_parse_packet() cho phép vượt qua kiểm tra ranh giới bằng phép cộng signed 32-bit bị tràn, khiến memcpy đọc từ vị trí cách cuối bộ đệm heap khoảng 1GB
    • DFVULN-122 là lỗi tràn bộ đệm heap trong RTP MPEG-4 depacketizer: aac_parse_packet() chấp nhận AU-headers-length bằng 0, tạo ra một cấp phát 1 byte rồi đọc trường 4 byte mà không xác nhận sự tồn tại của AU header
    • DFVULN-121 là lỗi underflow bộ đệm heap trong CAF demuxer: read_seek() dùng giá trị trả về -1 từ av_index_search_timestamp() làm chỉ số mảng mà không kiểm tra, dẫn tới truy cập index_entries[-1]
    • DFVULN-120 là lỗi underflow số nguyên trong AVI demuxer: ff_read_riff_info() nhận size - 4 mà không xác nhận size >= 4, khiến LIST chunk kích thước 0 bị underflow thành khoảng 4GB và dẫn tới cấp phát khoảng 2GB
    • DFVULN-119 là lỗi tràn bộ đệm heap trong opt_map() của option parser: một phép tăng không cần thiết khiến link-label bị phân tích sai thành file index và lưu stream index -1, để rồi vòng lặp sau đó đọc trước mảng AVStream**
    • DFVULN-118 là lỗi tràn bộ đệm heap trên đường RTSP server: rtsp_read_announce() xử lý Content-Length âm như hợp lệ, nên ANNOUNCE từ xa với Content-Length: -1 có thể gây ghi ngoài phạm vi vào sdp[-1]
    • DFVULN-117 là lỗi tràn bộ đệm heap trong RTMP client: rtmp_calc_swfhash() chỉ kiểm tra in_size < 3 thay vì in_size < 8, nên đọc 8 byte từ bộ đệm tối thiểu 3 byte
    • DFVULN-116 là lỗi tràn bộ đệm heap trong RTSP SDP parsing: sdp_parse_line() tính strlen(control_url) - 1 trên chuỗi rỗng, khiến size_t wrap thành SIZE_MAX và gây đọc trước bộ đệm 1 byte

Từ marker khung hình bị bỏ qua đến kiểm soát PC

  • Trong 21 phát hiện, lỗi tràn bộ đệm heap của AV1 RTP depacketizer có thể bị chạm tới qua mạng mà không cần cờ đặc biệt nào
  • Nạn nhân chỉ cần chạy ffmpeg -i rtsp://attacker/stream, và một gói 183 byte là đủ để bẻ hướng luồng thực thi
  • Khi FFmpeg kéo một luồng RTSP, máy chủ sẽ gửi video đã mã hóa dưới dạng chuỗi gói RTP
  • AV1 tổ chức bitstream thành các OBU (Open Bitstream Units), và định dạng RTP payload sẽ chia các OBU này qua nhiều gói
  • Depacketizer của FFmpeg có nhiệm vụ ghép các OBU đã bị chia lại thành một elementary stream sạch
  • Temporal Delimiter (TD) là một marker nhỏ phân tách một temporal unit, tức một khung hình, khỏi khung kế tiếp
  • Đặc tả quy định depacketizer phải “ignore and remove” TD trong payload
  • Chính phần xử lý “ignore and remove” này đã trở thành điểm lỗi, và tác nhân đã bắt được điểm đó

Nguyên nhân gốc rễ

  • Depacketizer xây dần gói đầu ra, với con trỏ pktpos theo dõi vị trí byte tiếp theo sẽ được ghi trong pkt->data
  • pktpos bắt đầu từ cuối hiện tại của gói
// libavformat/rtpdec_av1.c:199
pktpos = pkt->size;
  • Khi mã lặp qua các phần tử OBU trong gói, mọi byte thực sự được xuất ra đều đi kèm lời gọi av_grow_packet, và lời gọi này sẽ mở rộng heap allocation của pkt->data
  • Bất biến mà toàn bộ routine này dựa vào là pktpos không được vượt quá kích thước đã cấp phát của pkt->data
  • Phần xử lý Temporal Delimiter phá vỡ bất biến này
// libavformat/rtpdec_av1.c:250
if ((obu_type == AV1_OBU_TEMPORAL_DELIMITER) ||
    (obu_type == AV1_OBU_TILE_LIST)) {
    pktpos += obu_size;
    rem_pkt_size -= obu_size;
    obu_cnt++;
    continue;
}
  • Khi bỏ qua TD, pktpos được đẩy lên theo obu_size do kẻ tấn công khai báo, nhưng không hề có bộ nhớ nào được cấp phát để chống đỡ bước nhảy đó
  • Con trỏ đầu vào buf_ptr cũng không được dịch qua phần byte của TD
  • Nếu TD có obu_size = 148 thì pktpos sẽ thành 148, trong khi pkt->data vẫn có thể chưa được cấp phát hoặc nhỏ hơn rất nhiều so với 148 byte
  • Ở vòng lặp tiếp theo, mã sẽ lại phân tích chính byte của TD, đọc lại byte header TD như độ dài của OBU mới, và dùng payload như nội dung của OBU đã bị thao túng
  • Với OBU hợp lệ tiếp theo, gói chỉ được nới ra đúng theo kích thước của OBU đó
// libavformat/rtpdec_av1.c:296
if ((result = av_grow_packet(pkt, output_size)) < 0)
    return result;

// libavformat/rtpdec_av1.c:304 / 336
pkt->data[pktpos++] = *buf_ptr++ | AV1F_OBU_HAS_SIZE_FIELD;
memcpy(pkt->data + pktpos, buf_ptr, obu_payload_size);
  • Nếu OBU bị thao túng dài 17 byte, av_grow_packet sẽ cấp phát bộ đệm 81 byte, gồm 17 byte cộng với 64 byte input padding của FFmpeg
  • Việc ghi sẽ bắt đầu tại pkt->data[148], tức là diễn ra ở vị trí cách cuối vùng cấp phát 67 byte
  • Khi đó lỗi trở thành một tràn bộ đệm heap mà kẻ tấn công kiểm soát được cả offset lẫn nội dung

Cách khai thác

  • Để một lỗi tràn có điều khiển trở nên hữu ích, ngay sau bộ đệm phải có mục tiêu đáng để ghi đè, và allocator của FFmpeg đã cung cấp đúng mục tiêu đó
  • Khi av_grow_packet cấp phát bộ đệm dữ liệu gói, nó đi qua av_buffer_alloc; hàm này lần lượt cấp phát bộ đệm dữ liệu, struct bookkeeping AVBufferAVBufferRef trên heap
  • FFmpeg cấp phát bằng posix_memalign với căn chỉnh 64 byte, nên bộ đệm dữ liệu 81 byte sẽ chiếm một chunk 128 byte và struct AVBuffer sẽ nằm ngay phía sau
  • Struct AVBuffer chứa một con trỏ hàm dùng làm callback giải phóng
// libavutil/buffer_internal.h
struct AVBuffer {
    uint8_t *data;        // +0
    size_t   size;        // +8
    atomic_uint refcount; // +16
    void (*free)(void *opaque, uint8_t *data); // +24
    void    *opaque;      // +32
    ...
};
  • Tính từ đầu bộ đệm dữ liệu, con trỏ AVBuffer.free nằm ở offset 152
  • Với TD có obu_size = 148, việc ghi sẽ bắt đầu từ pkt->data[148]
  • Byte header TD 0x10 sẽ được diễn giải lại thành độ dài 16, và header cùng payload của OBU 16 byte bị thao túng sẽ được ghi từ offset 148
  • AVBuffer.refcount nằm ở offset 144–147, nên vẫn ở trước điểm bắt đầu ghi là 148 và giữ nguyên giá trị 1
  • Exploit nhét OBU bị thao túng thứ ba vào payload TD để kích hoạt thêm một lần av_grow_packet
  • Vì bộ đệm được tạo bằng av_buffer_alloc chứ không phải av_buffer_realloc, nó không được đánh dấu là có thể realloc, nên FFmpeg đi theo đường cấp phát bộ đệm mới rồi giải phóng bộ đệm cũ
// libavutil/buffer.c:209
if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) || ...) {
    ret = av_buffer_realloc(&new, size);
    memcpy(new->data, buf->data, ...);
    buffer_replace(pbuf, &new);
    return 0;
}
  • buffer_replace giảm refcount của bộ đệm cũ từ 1 xuống 0 và gọi callback giải phóng
// libavutil/buffer.c:129
if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
    b->free(b->opaque, b->data);
}
  • Ở thời điểm đó, con trỏ free đã bị ghi đè sẽ được gọi, cho phép kiểm soát instruction pointer
  • Trong bản build release, một gói RTP 183 byte duy nhất đã khiến rip trở thành 0xdeadbeef
#0  0x00000000deadbeef in ?? ()
rip            0xdeadbeef          0xdeadbeef
#1  buffer_replace (buffer.c:133)
#2  av_buffer_realloc (buffer.c:220)
#3  av_grow_packet (packet.c:151)
#4  av1_handle_packet (rtpdec_av1.c:296)
#5  rtp_parse_packet_internal (rtpdec.c:743)

Phạm vi ảnh hưởng và PoC

  • Các môi trường triển khai nơi FFmpeg được yêu cầu mở URL RTSP mà kẻ tấn công có thể tác động đều nằm trong phạm vi ảnh hưởng của lỗ hổng này
  • Pipeline ingest media lấy stream URL do người dùng cung cấp nằm trong phạm vi ảnh hưởng
  • Các hệ thống giám sát và CCTV lấy RTSP feed nằm trong phạm vi ảnh hưởng
  • Các dịch vụ transcoding xử lý nguồn AV1-over-RTP từ xa nằm trong phạm vi ảnh hưởng
  • Không cần xác thực, không cần tương tác người dùng nào ngoài việc mở luồng, và cũng không cần cờ command-line đặc biệt
  • Lỗ hổng được kích hoạt trong bước RTSP PLAY thông thường mà các client này thực hiện theo thiết kế
  • Mã PoC có tại ffmpeg-dfvuln127

1 bình luận

 
Ý kiến trên Hacker News
  • FFmpeg có thành tích đặc biệt tệ về mặt bảo mật
    Từ lâu, gần như mỗi lần chạy fuzzer là lại lòi ra vô số lỗi hỏng bộ nhớ, và 10 năm trước cũng đã có công sức từ nhân viên Google: https://security.googleblog.com/2014/01/ffmpeg-and-thousand-...
    Vì vậy, dù đây là một màn demo cho thấy năng lực của LLM, nó cũng không phải chuyện đáng ngạc nhiên. Nếu xử lý nội dung không đáng tin cậy hoặc do người dùng cung cấp thì không nên chạy FFmpeg ngoài sandbox, và làm vậy là chấp nhận rủi ro vô lý

    • Phía FFmpeg từ lâu vẫn liên tục phàn nàn rằng có rất nhiều người muốn công bố lỗ hổng của dự án, nhưng số người thực sự bắt tay vào viết bản vá để sửa thì ít hơn không thể so sánh nổi
    • Gần đây các nhà phát triển FFmpeg đã xuất hiện trên podcast của Lex Fridman và cũng có nói về bảo mật
      Có một lỗ hổng trong một codec cực kỳ ngách, kiểu chỉ được dùng trong một trò chơi điện tử từ thập niên 90, và họ nói theo kiểu người báo cáo đã làm quá lên, trong khi thực tế đó là codec gần như không ai dùng nên chẳng có gì to tát
      Nhưng tôi tự hỏi liệu họ có đang bỏ qua chuyện rằng nếu kẻ tấn công có thể cung cấp một tệp video thì hắn có thể tùy ý chọn bất kỳ codec video nào không. Dù nhà phát triển nghĩ codec đó hoàn toàn không được dùng đến, miễn là nó vẫn còn dùng được thì kẻ tấn công vẫn có thể dùng nó
      Không rõ có phải tôi đã bỏ sót điều gì không, hay có lý do xác đáng nào khiến lỗ hổng của codec này thật sự không đáng lo
    • Đương nhiên rồi. Vì ai cũng biết giải pháp thay thế hiển nhiên cho FFmpeg là gì mà
    • Việc sandbox chính FFmpeg thì không khó, nhưng với những thứ như MPV/VLC dùng FFmpeg thì lại phức tạp hơn
      Cho đến gần đây, vẫn chưa có native context cho virtio GPU nên gần như không thể sandbox trình phát video mà không mất toàn bộ tăng tốc phần cứng. Ít nhất là rất khó nếu ép từ bên ngoài; còn từ bên trong thì vẫn có thể cô lập FFmpeg như Chromium làm và khóa chặt bằng seccomp
    • FFmpeg hoạt động trong một lĩnh vực cực kỳ phức tạp, và là phần mềm rất phức tạp đòi hỏi tập trung cực độ vào hiệu năng
      Đây không chỉ là vấn đề riêng của FFmpeg. Apple cũng đã có vô số lỗ hổng trong bộ giải mã ảnh và video. Bản thân lĩnh vực này đã rất khó, còn FFmpeg thì làm nhiều việc hơn bất kỳ ai khác
  • Tôi nghĩ ngành này đang tối ưu sai mục tiêu. Rất dễ để dùng thứ như Mythos preview 1 hay GPT-5.5 tạo ra hàng nghìn báo cáo lỗi do AI viết. Điều khó là thực sự sửa lỗi
    Từ vài tháng nay tôi đang xây một hệ thống thay vì chỉ tìm ra vấn đề bảo mật nghiêm trọng rồi nộp báo cáo thì sẽ mở luôn PR. Tính đến nay tỷ lệ được chấp nhận khoảng 94%. Phần lớn trường hợp thất bại không phải do đánh giá sai lỗ hổng, mà vì các kill switch riêng của từng dự án hoặc các cơ chế nội bộ không được tài liệu hóa
    Có vẻ các nhà phát triển nhìn chung thích cách này hơn. Báo cáo lỗi tạo thêm việc, còn PR tốt thì giảm việc. Nghe có vẻ hiển nhiên, nhưng nhiều sản phẩm bảo mật dường như vẫn chỉ dừng ở mức báo cáo rồi thôi

    • Ngành này thực ra tối ưu cho tốc độ, thời gian ra mắt và tính năng, rồi áp dụng mô hình vùi đầu như đà điểu trước những thứ không tạo doanh thu ngắn hạn như cân nhắc bảo mật, khả năng truy cập, phụ thuộc nhà cung cấp, khả năng tương tác v.v.
      Họ đã luôn như vậy từ khi ngành này tồn tại, và chỉ đến bây giờ chúng ta mới bắt đầu có công cụ thích hợp để đánh giá thiệt hại và mức độ mong manh của toàn bộ hệ sinh thái
    • Có vẻ đang bỏ sót gì đó ở đây. Phần mềm Apple đâu có mã nguồn mở, vậy thì đề xuất bản sửa bằng cách nào nhỉ
  • Lỗi này nghiêm trọng vì khả năng bị chạm tới của nó. Mọi triển khai mà FFmpeg trỏ tới một URL RTSP chịu ảnh hưởng của kẻ tấn công đều bị phơi nhiễm
    Bao gồm các pipeline thu thập media lấy URL stream do người dùng cung cấp, hệ thống giám sát/CCTV lấy feed RTSP, các dịch vụ transcoding xử lý nguồn AV1-over-RTP từ xa, v.v. Thực sự khá nghiêm trọng, đến mức việc nó được công khai còn khiến tôi ngạc nhiên. Ngay lúc này tôi đã nghĩ ra được vài dịch vụ có vẻ có thể bị khai thác

    • Cũng có thể cho rằng nếu biết về một lỗ hổng nghiêm trọng thì việc công khai nó là quan trọng. Vì như vậy những người đang dùng phần mềm theo cách dễ tổn thương có thể thực hiện biện pháp giảm rủi ro
    • Để đi đến khai thác thực tế thì còn cần thêm thứ như rò rỉ ASLR
    • FFmpeg đã nhiều lần thể hiện rõ rằng họ không quan tâm đến lỗi hay báo cáo bảo mật
  • Dù chuyện này có thể không nghiêm trọng như vẻ ngoài kiểu quảng cáo của một công ty bảo mật, nó vẫn nhắc rằng ở đâu đó trong mọi ứng dụng bạn phát hành đều có lỗ hổng bảo mật, và giờ đây ngay cả script kiddie cũng có thể tìm ra nó sau 5 phút phát hành với 2 đô tín dụng
    Nếu bạn không dùng red team để rà soát mã trước khi phát hành, thì hacker sẽ làm thay sau khi phát hành

  • Thuật ngữ zero-day đang bị thổi phồng quá mức. Trong các lỗ hổng được mô tả thì chẳng có cái nào thực sự là zero-day, nhưng gọi vậy nghe kêu và dễ kiếm click hơn

  • Câu “tại thời điểm này một con trỏ free đã bị hỏng được gọi, và chúng ta có quyền kiểm soát con trỏ lệnh” là cực kỳ nghiêm trọng
    Tuy vậy trên thực tế, có vẻ chỉ riêng lỗi này chưa đủ để dẫn tới thực thi mã từ xa tùy ý. Nhất là khi có ASLR, và còn phải có một vùng nhớ nào đó vừa ghi được vừa thực thi được

    • Bài viết lướt khá nhanh qua đoạn này, nhưng có vẻ biến tiếp theo trong struct đúng lúc lại là tham số đầu tiên của hàm, nên có thể dẫn tới thực thi mã tùy ý bằng thứ như system()
      Dù vậy vẫn cần một exploit khác để phá ASLR
  • Đó không phải nghĩa của “zero-day”

    • Có vẻ từ sau khi Stuxnet được đưa tin thì thuật ngữ này phổ biến hóa đến mức mất nghĩa
    • Nếu nói vậy thì mong bạn giải thích luôn ý nghĩa của nó. Có khi chính tôi cũng đang hiểu sai định nghĩa
  • Cấu trúc khuyến khích trong lĩnh vực nghiên cứu bảo mật đã hỏng rất nặng
    Họ giống như tầng quản lý trung gian của thế giới FOSS. Họ được khen vì đẩy thêm việc cho các tình nguyện viên, và việc đó càng khẩn cấp thì càng được khen nhiều hơn. Việc thừa nhận tác động thực tế hay hàm ý thực dụng của một vấn đề lại xung đột với chính cơ chế khuyến khích của họ
    Rất khó để không nhìn họ như những người dọn rác ở đáy ngành phần mềm, và giờ có lẽ nên bắt đầu đối xử với họ như những kẻ bị xa lánh. Hoặc gửi PR đi, hoặc im lặng lại

  • Cá nhân tôi đã dùng FFmpeg từ rất lâu, cả cho mục đích riêng lẫn trong dịch vụ do tôi tạo ra. Fabrice Bellard là một thiên tài, và những nhà phát triển đã đưa FFmpeg đi đến ngày hôm nay đã khiến thế giới phong phú hơn theo cách có thể đo đếm được
    Nhưng khi chạy với đầu vào không đáng tin cậy, tôi khó nghĩ ra chương trình nào đáng để sandbox hơn FFmpeg. Lý do là một khối mã C khổng lồ đang xử lý các codec video và âm thanh phức tạp, vốn nổi tiếng là cực kỳ khó để làm cho hoàn toàn chính xác
    Dù vậy, trên thực tế đây không hẳn là vấn đề quá lớn. Hãy chạy FFmpeg trong VM hoặc gVisor, và đầu ra cuối cùng thường là một tệp video mà bạn sẵn sàng phát trong trình duyệt. Trong trình duyệt nó lại tiếp tục được giải mã bên trong một sandbox khác, nên vốn dĩ đây đã là việc khó rồi

    • Tôi có một dự cảm u ám rằng các công ty nắm giữ bản quyền muốn DRM, “nền tảng đáng tin cậy” và chiếm đoạt chính sách sẽ phóng đại một phần tác hại ở đây
      Sandbox an toàn rất dễ trở thành cơ hội cho việc sao chép không hạn chế
    • Tôi không hiểu “một tệp video mà bạn sẵn sàng phát trong trình duyệt” nghĩa là gì. Chẳng phải sẽ an toàn nếu giả định rằng không có tệp video nào có thể thoát khỏi sandbox giải mã của trình duyệt sao?
    • Nhưng việc mã hóa thường cũng cần bộ tăng tốc phần cứng, nên rốt cuộc vẫn thường phải quay lại dùng C
  • Đây là lỗ hổng trong đó latm_parse_packet() ở mã depacketize ngược RTP LATM thực hiện phép cộng 32-bit có dấu, bị tràn số và vượt qua kiểm tra biên
    Lại thêm một lỗ hổng do phép cộng không được kiểm tra, vậy mà các ngôn ngữ hiện đại như Rust hay Go không ném ngoại lệ khi tràn số, còn các kiến trúc CPU hiện đại như RISC-V cũng không cung cấp bẫy tràn số. Các ngôn ngữ cũ như C hay C++ thì dĩ nhiên cũng không có kiểm tra tràn số
    Thật nực cười. Rõ ràng là không thể tin con người sẽ luôn viết đúng mã số học

    • Rust bật kiểm tra tràn số trong chế độ debug, và cũng có thể bật trong chế độ release. Thực tế là người ta vẫn dùng như vậy
      Hành vi mặc định của tràn số nguyên trong chế độ release của Rust cũng được định nghĩa rõ ràng, chỉ là nó sẽ wrap. Vì vậy khả năng dẫn đến lỗ hổng thấp hơn. Tất nhiên, khi bắt đầu dùng unsafe Rust thì lại là chuyện khác
    • Zig sẽ ném ngoại lệ khi tràn số. Với cộng bão hòa và cộng wrap thì có các toán tử +|=, +%=
      Rust không ném ngoại lệ tràn số theo mặc định, nhưng có thể viết như 123.checked_add(321). Làm vậy thì mã khó đọc hơn, nhưng an toàn trước tràn số
      Thành thật mà nói, với cách tôi viết mã thì một dạng như chú thích cuối dòng sẽ tốt hơn. Ví dụ như var x = y + z; # wrapped
      Khả năng trộn lẫn số học wrap, kiểm tra và bão hòa trong cùng một dòng là rất thấp. Trong Zig, mọi dòng đều phải tự biên dịch được mà không cần ngữ cảnh mã khác, nên không thể có trạng thái trình biên dịch kiểu doing(wrapped) { x + y }. Tên hàm thì quá dài dòng, còn ép kiểu cũng quá dài dòng. Một bộ sửa đổi ở cấp câu lệnh có thể là một phương án thỏa hiệp tốt