☰ Mục lục series
Tài liệu Go tiếng Việt
  1. Bắt đầu (Getting started)
    1. Tổng quan
    2. Tải về và cài đặt
    3. Bắt đầu với Go
    4. Quản lý các bản cài đặt Go
    5. Plugin trình soạn thảo và IDE
  2. Dạo quanh Go (A Tour of Go)
    1. Chào mừng
    2. Package, biến và hàm
    3. Điều khiển luồng
    4. Struct, slice và map
    5. Method và interface
    6. Generics
    7. Xử lý đồng thời
  3. Hướng dẫn (Tutorials)
    1. Danh sách hướng dẫn
    2. Tạo một Go module
    3. Gọi mã của bạn từ một module khác
    4. Trả về và xử lý lỗi
    5. Trả về lời chào ngẫu nhiên
    6. Trả về lời chào cho nhiều người
    7. Thêm một test
    8. Biên dịch và cài đặt ứng dụng
    9. Kết luận
    10. Bắt đầu với workspace nhiều module
    11. Phát triển RESTful API với Go và Gin
    12. Truy cập cơ sở dữ liệu quan hệ
    13. Bắt đầu với generics
    14. Bắt đầu với fuzzing
    15. Làm việc với JSON
    16. Tìm và sửa các dependency có lỗ hổng với govulncheck
    17. Tìm và khắc phục phụ thuộc có lỗ hổng với VS Code Go
    18. Viết ứng dụng web
  4. Viết code Go
    1. Cách viết mã Go
    2. Effective Go
    3. Doc Comment trong Go
  5. Module
    1. Phát triển và publish module
    2. Quản lý phụ thuộc
    3. Tổ chức một module Go
    4. Quản lý mã nguồn của module
    5. Cách đánh số phiên bản module
    6. Quy trình phát hành và đánh phiên bản module
    7. Publish một module
    8. Phát triển một bản cập nhật major version
    9. Tham chiếu tệp go.mod
    10. Ngừng hỗ trợ 'go get' cho việc cài đặt tệp thực thi
  6. Cơ sở dữ liệu (Database)
    1. Truy cập cơ sở dữ liệu quan hệ
    2. Mở một handle cơ sở dữ liệu
    3. Thực thi câu lệnh SQL không trả về dữ liệu
    4. Truy vấn dữ liệu
    5. Dùng prepared statement
    6. Thực thi transaction
    7. Huỷ các thao tác đang chạy
    8. Quản lý kết nối
    9. Tránh rủi ro SQL injection
  7. Chẩn đoán và hiệu năng
    1. Chẩn đoán
    2. Hướng dẫn về Go Garbage Collector
    3. Tối ưu hoá dựa trên profile
    4. Data Race Detector
    5. Gỡ lỗi mã Go bằng GDB
    6. Hỗ trợ coverage profiling cho integration test
  8. Bảo mật (Security)
    1. Tổng quan bảo mật
    2. Thực hành tốt về bảo mật cho lập trình viên Go
    3. Quản lý lỗ hổng trong Go
    4. Cơ sở dữ liệu lỗ hổng của Go
    5. Quét lỗ hổng trong IDE
    6. Chính sách CNA của Go
    7. Go Fuzzing
    8. Chi tiết kỹ thuật của Go Fuzzing
    9. Chính sách bảo mật của Go
    10. Threat Model của Go
    11. Các quyết định về bảo mật của Go
    12. Tuân thủ FIPS 140-3
  9. Công cụ và toolchain
    1. Tài liệu về các lệnh
    2. Về lệnh go
    3. Go Toolchains
    4. Telemetry của Go
    5. Cài đặt Go từ mã nguồn
    6. Cài đặt và sử dụng gccgo
  10. Tham khảo
    1. Câu hỏi thường gặp (FAQ)
    2. Go 1 và tương lai của các chương trình Go
    3. Hướng dẫn chuyển đổi sang encoding/json/v2
    4. Hướng dẫn đóng góp
    5. Đóng góp cho frontend gccgo
  11. Phụ lục
    1. Bảng thuật ngữ
Bảo mật (Security)

Các quyết định về bảo mật của Go

Bản dịch từ go.dev/doc/security/decisions

Tổng quan

Tài liệu này tập hợp các quyết định mà nhóm Go Security đã đưa ra về những vấn đề thường được báo cáo. Nó chủ yếu đóng vai trò tài liệu tham chiếu cho những trường hợp mà chúng tôi không xem là lỗ hổng.

Danh sách này không bao quát toàn bộ.

Nguyên tắc chung

Không phải lỗi nào cũng là lỗ hổng.

Với bất kỳ lỗi nào, gần như luôn có thể dựng lên một kịch bản giả định trong đó lỗi ấy gây ra lỗ hổng.

Ví dụ, hãy hình dung một lỗi trong bộ giải mã ảnh khiến nó giải mã sai một số dữ liệu đầu vào. Giờ hãy hình dung một hệ thống giả định nhận ảnh chụp séc viết tay và thực hiện chuyển khoản ngân hàng để thanh toán các tờ séc đó. Nếu hệ thống này gồm một gateway để kiểm tra tính hợp lệ của yêu cầu và một backend thực hiện chuyển khoản, thì sai khác giữa hai bộ phân tích ảnh mà gateway và backend sử dụng có thể khiến gateway chuyển một thao tác độc hại xuống backend.

Xếp một lỗi phân tích ảnh sai vào loại lỗ hổng dựa trên kịch bản này không phục vụ mục đích hữu ích nào. Cảnh báo người dùng rằng họ bị ảnh hưởng bởi một “lỗ hổng” kiểu như vậy chỉ là nhiễu, vì gần như không có người dùng nào thực sự bị ảnh hưởng. Gọi đây là lỗ hổng còn có hại cho bảo mật, vì nó tập cho người dùng thói quen phớt lờ các report do phần lớn chúng vô nghĩa.

Kịch bản này cũng là ví dụ cho thấy vì sao chúng tôi không gán nhãn mức độ nghiêm trọng cho các vấn đề bảo mật: với hệ thống xử lý séc giả định kia đây có thể là vấn đề nghiêm trọng cao, nhưng với đa số người dùng thì nó hoàn toàn không phải vấn đề gì.

Theo nguyên tắc chung, việc chỉ đơn thuần dựng được một kịch bản giả định trong đó một lỗi gây ra vấn đề bảo mật không đủ để chúng tôi xử lý nó như một vấn đề bảo mật.

Lỗ hổng

Thực thi mã từ xa

Một kịch bản cho phép attacker thực thi mã trong tình huống mà việc thực thi mã là không được trông đợi là lỗ hổng thuộc nhánh PRIVATE. Quyết định này được ưu tiên hơn mọi quyết định khác.

Quyết định này không áp dụng cho các hàm vốn được trông đợi là sẽ thực thi mã.

Được tính:

  • Một hàm phân tích cú pháp thực thi mã khi gặp dữ liệu đầu vào độc hại.
  • Một request độc hại khiến HTTP server thực thi mã.

Không được tính:

  • Câu lệnh go test chạy các bài test. Chạy go test trên các bài test do attacker kiểm soát không nằm trong threat model (mô hình mối đe doạ) của chúng tôi.

Panic

Một panic khi xử lý dữ liệu đầu vào do attacker kiểm soát có thể là một lỗ hổng.

Một panic trong server vốn được trông đợi phải xử lý các request do attacker kiểm soát, chẳng hạn server net/http, thường là lỗ hổng thuộc nhánh PRIVATE.

Một panic trong client, chẳng hạn client net/http, thường là lỗ hổng thuộc nhánh PUBLIC.

Một panic trong hàm phân tích cú pháp của một package chuyên xử lý dữ liệu đầu vào có khả năng độc hại, chẳng hạn archive/zip hay image/png, thường là lỗ hổng thuộc nhánh PUBLIC.

Một dữ liệu đầu vào gây panic chỉ vì kích thước tự nhiên của nó, chẳng hạn một tấm ảnh rất lớn, thường không được xếp là lỗ hổng.

Dữ liệu đầu vào không hợp lệ đưa vào những hàm không được thiết kế rõ ràng để phân tích dữ liệu có thể độc hại thì không nằm trong threat model của chúng tôi và nhìn chung nằm ngoài phạm vi lỗi bảo mật. Ví dụ, bộ parser ảnh được trông đợi phải chống đỡ dữ liệu đầu vào không hợp lệ, nhưng một panic trong bộ encoder ảnh có thể là lỗi nhưng sẽ không được xử lý như một lỗ hổng.

Một panic trong hàm đã deprecated không phải lỗ hổng; xem quyết định về API deprecated bên dưới.

Tiêu thụ tài nguyên quá mức

Chúng tôi thường xem việc tiêu thụ CPU hoặc bộ nhớ quá mức, chẳng hạn một hàm có thời gian chạy O(n²) theo kích thước dữ liệu đầu vào, là tương đương với một panic.

Build mã độc hại

Việc build một chương trình do attacker kiểm soát phải an toàn, ngay cả khi việc chạy nó thì không. Ví dụ, chúng tôi chủ ý để việc build mã không đáng tin rồi chạy nó trong sandbox là an toàn. Chúng tôi đặc biệt khuyến nghị bất kỳ ai build mã không đáng tin hãy xem đây là một biện pháp phòng thủ nhiều lớp, và việc build mã không đáng tin cũng nên được thực hiện trong môi trường sandbox không có đặc quyền.

Rò rỉ dữ liệu không nằm trong threat model của chúng tôi. Build một chương trình do attacker kiểm soát có thể tạo ra đầu ra chứa nội dung của các tệp cục bộ tuỳ ý.

Thực thi mã độc hại cũng không nằm trong threat model của chúng tôi. Chạy một chương trình độc hại hiển nhiên cho phép nó làm những việc độc hại.

Là lỗ hổng, thường thuộc nhánh PRIVATE:

  • Một module độc hại có thể khiến “go build” thực thi mã tuỳ ý.

Không được xử lý như vấn đề bảo mật:

  • “go build” tạo ra lỗi chứa văn bản lấy từ một tệp cục bộ tuỳ ý.
  • Một tệp thực thi đã biên dịch chứa nội dung từ một tệp cục bộ tuỳ ý.
  • Một chương trình độc hại có thể làm hỏng trạng thái của runtime và thực thi mã tuỳ ý.
  • Một lỗi biên dịch cho phép che giấu mã độc hại.

Những trường hợp không phải lỗ hổng

Môi trường do attacker kiểm soát

Nếu một cuộc tấn công dựa vào việc attacker kiểm soát được môi trường mà chương trình chạy trong đó, thì đó không phải lỗ hổng.

Điều này bao gồm, nhưng không giới hạn ở, attacker có khả năng thêm chương trình vào $PATH hoặc đặt các biến môi trường tuỳ ý.

API deprecated

Ngưỡng để một lỗi trong API deprecated được xem là vấn đề bảo mật cao hơn so với API còn được hỗ trợ.

Cụ thể, một panic hoặc việc tiêu thụ tài nguyên quá mức trong API deprecated không bao giờ được xử lý như lỗ hổng. Người dùng cần gia cố bảo mật nên dùng các API còn được hỗ trợ.

image, x/image: Ảnh lớn

Phân tích một tấm ảnh lớn có thể cấp phát một lượng bộ nhớ lớn. Ví dụ, một ảnh màu 32-bit kích thước 65536x65536 cần 16MiB để lưu ở dạng không nén.

Nhiều định dạng nén ảnh có thể thu một tấm ảnh lớn, đơn giản xuống kích thước tệp rất nhỏ. Giải mã tệp nhỏ đó có thể cấp phát một lượng bộ nhớ lớn.

Người dùng phân tích ảnh không đáng tin nên kiểm tra kích thước ảnh trước khi phân tích, bằng một hàm như image.DecodeConfig.

Chúng tôi không xem việc một hàm phân tích ảnh giải mã một tấm ảnh lớn, được nén tốt là lỗ hổng.

net/http: Chuyển hướng

HTTP client của package net/http có xử lý chuyển hướng. Nó hiện thực các hành vi liên quan đến bảo mật khi xử lý chuyển hướng. Ví dụ, nó loại bỏ header “Authorization” khi đi theo một chuyển hướng tới tên miền không phải tên miền con và cũng không trùng khớp với tên miền của request ban đầu.

Việc loại bỏ header là một biện pháp phòng thủ nhiều lớp, tránh trường hợp một server bị cấu hình sai hoặc bị xâm nhập vô tình chuyển tiếp request của client chứa các header nhạy cảm tới một đích không đáng tin. Bản thân việc không loại bỏ header khi chuyển hướng không cho phép attacker lấy được thông tin xác thực truyền trong header. Tuy nhiên, nó có thể kết hợp với các lỗ hổng khác (ví dụ, một server có lỗ hổng open redirect) để làm được điều đó.

Thay đổi hành vi của HTTP client có rủi ro cao làm hỏng những người dùng hiện tại vốn phụ thuộc vào hành vi hiện hành. Ví dụ, chính sách same origin của client hiện cho phép tên miền con (một chuyển hướng từ example.com sang www.example.com sẽ giữ lại các header), trong khi chuẩn WHATWG Fetch thì không. Đưa client về đúng chuẩn có thể là việc đáng làm, nhưng làm điều đó trong một bản phát hành bảo mật nhiều khả năng gây phiền toái cho người dùng hiện tại hơn là khắc phục được lỗ hổng thực sự.

Vì việc làm sạch chuyển hướng là biện pháp phòng thủ nhiều lớp, và thay đổi nó là rủi ro, chúng tôi xem mọi khía cạnh của việc chuyển hướng trong HTTP client là nằm ngoài phạm vi của quy trình xử lý lỗi bảo mật.

Nội dung gốc: Go Documentation © The Go Authors, giấy phép CC BY 3.0. Bản dịch và ghi chú: Lê Văn Dũng.