Mã nguồn bảo mật

1. Tổng quan

Các kỹ thuật bảo mật mã nguồn là một tập hợp các phương pháp có thể dùng để cải thiện tính bảo mật của mã nguồn. Các kỹ thuật này có thể giúp xác định và khắc phục các lỗ hổng trong mã nguồn, ngăn chặn hành vi truy cập trái phép vào mã nguồn và bảo vệ mã nguồn khỏi bị sửa đổi.

Sau đây là một số kỹ thuật bảo mật mã nguồn phổ biến:

  • Tìm lỗi mã nguồn: Tìm lỗi mã nguồn là quá trình kiểm tra mã nguồn để tìm lỗi và các vấn đề về kiểu. Quá trình này được thực hiện bằng cách sử dụng một công cụ tìm lỗi mã nguồn. Đây là một chương trình phân tích mã nguồn và xác định các vấn đề tiềm ẩn. Bạn có thể dùng công cụ tìm lỗi mã nguồn để kiểm tra nhiều loại lỗi, bao gồm lỗi cú pháp, lỗi ngữ nghĩa, lỗi kiểu và lỗ hổng bảo mật.
  • Kiểm thử bảo mật ứng dụng tĩnh (SAST): SAST là một loại kiểm thử bảo mật phân tích mã nguồn, mã nhị phân hoặc mã byte để xác định các lỗ hổng bảo mật. Bạn có thể dùng các công cụ SAST để tìm lỗ hổng trong nhiều ngôn ngữ lập trình, bao gồm Go, Java, Python, C++ và C#.
  • Quét giấy phép: Quét giấy phép là quá trình xác định giấy phép của các thành phần phần mềm bên thứ ba được dùng trong một ứng dụng phần mềm. Điều này rất quan trọng vì giúp đảm bảo rằng ứng dụng tuân thủ các điều khoản của giấy phép, từ đó giúp tránh các vấn đề pháp lý.

Bạn có thể dùng các kỹ thuật này để cải thiện tính bảo mật của mã nguồn ở tất cả các giai đoạn của vòng đời phát triển phần mềm. Bạn có thể dùng kỹ thuật tìm lỗi mã nguồn để xác định lỗi ở giai đoạn đầu của quá trình phát triển, dùng SAST để tìm lỗ hổng trước khi biên dịch hoặc triển khai mã và dùng kỹ thuật quét giấy phép để đảm bảo rằng ứng dụng tuân thủ các điều khoản của giấy phép.

Việc sử dụng các kỹ thuật này có thể giúp cải thiện tính bảo mật của mã nguồn và giảm nguy cơ vi phạm bảo mật.

Kiến thức bạn sẽ học được

Phòng thí nghiệm này sẽ tập trung vào các công cụ và kỹ thuật để bảo mật mã nguồn phần mềm.

  • Tìm lỗi mã nguồn
  • Kiểm thử bảo mật ứng dụng tĩnh
  • Quét giấy phép

Tất cả các công cụ và lệnh được dùng trong phòng thí nghiệm này sẽ được thực hiện trong Cloud Shell.

2. Thiết lập và yêu cầu

Thiết lập môi trường tự học

  1. Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Tên dự án là tên hiển thị cho những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn có thể cập nhật tên này bất cứ lúc nào.
  • Mã dự án là mã duy nhất trên tất cả các dự án của Google Cloud và không thể thay đổi (không thể thay đổi sau khi đã đặt). Cloud Console tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là PROJECT_ID). Nếu không thích mã đã tạo, bạn có thể tạo một mã ngẫu nhiên khác. Ngoài ra, bạn có thể thử mã của riêng mình và xem mã đó có dùng được hay không. Bạn không thể thay đổi mã này sau bước này và mã sẽ giữ nguyên trong suốt thời gian diễn ra dự án.
  • Để bạn nắm được thông tin, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả ba giá trị này trong tài liệu.
  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các API/tài nguyên trên đám mây. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, thậm chí là không tốn chi phí. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá toàn bộ dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Bắt đầu Trình chỉnh sửa Cloud Shell

Lớp học lập trình này được thiết kế và kiểm thử để sử dụng với Trình chỉnh sửa Google Cloud Shell. Để truy cập vào trình chỉnh sửa,

  1. Truy cập vào dự án Google của bạn tại https://console.cloud.google.com.
  2. Ở góc trên cùng bên phải, hãy nhấp vào biểu tượng trình chỉnh sửa Cloud Shell

8560cc8d45e8c112.png

  1. Một ngăn mới sẽ mở ra ở cuối cửa sổ
  2. Nhấp vào nút Open Editor (Mở trình chỉnh sửa)

9e504cb98a6a8005.png

  1. Trình chỉnh sửa sẽ mở ra với một trình khám phá ở bên phải và trình chỉnh sửa ở khu vực trung tâm
  2. Một ngăn Terminal cũng sẽ có ở cuối màn hình
  3. Nếu dòng lệnh KHÔNG mở, hãy sử dụng tổ hợp phím `ctrl+`` để mở một cửa sổ dòng lệnh mới

Thiết lập môi trường

Đặt GOPATH thành một thư mục duy nhất để đơn giản hoá các lệnh được dùng trong phòng thí nghiệm này.

export GOPATH=$HOME/gopath

Tạo một thư mục để lưu giữ công việc của chúng ta

mkdir -p workspace
cd workspace

Nhân bản kho lưu trữ mã nguồn

git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)

3. Tìm lỗi mã nguồn

Tìm lỗi mã nguồn được dùng để kiểm tra các lỗi hoặc khiếm khuyết phổ biến dựa trên kiểu liên quan đến cú pháp. Tìm lỗi mã nguồn hỗ trợ bảo mật bằng cách cung cấp một mẫu cú pháp phổ biến cho nhiều nhóm, giúp đẩy nhanh quá trình xem xét mã, chia sẻ kiến thức và làm rõ mã.

Ngoài ra, tìm lỗi mã nguồn còn xác định các lỗi cú pháp phổ biến có thể dẫn đến các lỗ hổng phổ biến, chẳng hạn như sử dụng thư viện hoặc API cốt lõi không đúng cách hoặc kém hiệu quả.

Cài đặt công cụ liên kết staticcheck

 go get honnef.co/go/tools/cmd/staticcheck@latest

Chạy Go Linter (staticcheck) trong thư mục gốc của dự án

 staticcheck

Xem kết quả

main.go:42:29: unnecessary use of fmt.Sprintf (S1039)

Bạn gặp lỗi vì http.ListenAndServe() chấp nhận một Chuỗi và mã hiện tại sử dụng Sprintf mà không truyền biến vào chuỗi

Xem trạng thái thoát lệnh.

echo $?

Trong trường hợp này, vì lệnh dẫn đến lỗi, nên trạng thái thoát sẽ là 1 trở lên. Đây là một phương thức có thể dùng trong quy trình CI/CD để xác định mức độ thành công/thất bại của công cụ.

Chỉnh sửa tệp main.go và sửa mã:

  • Chú thích dòng bên dưới LINTING - Step 1 bên trong phương thức main() bằng cách thêm dấu gạch chéo ở đầu(//).
  • Bỏ chú thích hai dòng ngay bên dưới LINTING - Step 2 bên trong phương thức main() bằng cách xoá dấu gạch chéo ở đầu.

Chạy lại staticcheck trong thư mục gốc của dự án

staticcheck

Lệnh này không được trả về bất kỳ kết quả nào (tức là một dòng trống).

Kiểm tra trạng thái thoát của lệnh.

  echo $?

Trong trường hợp này, vì lệnh không dẫn đến lỗi, nên trạng thái thoát sẽ là không.

4. Kiểm thử bảo mật ứng dụng tĩnh

Kiểm thử bảo mật AST/Tĩnh – Cung cấp dữ liệu phân tích mã tĩnh để tìm các điểm yếu và lỗ hổng phổ biến ( CWE)

Cài đặt công cụ AST (gosec)

    export GOSEC_VERSION="2.15.0"
    curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | \
          sh -s -- -b $(go env GOPATH)/bin v${GOSEC_VERSION}

Chạy gosec bằng tệp chính sách đối với mã nguồn

gosec -conf policies/gosec-policy.json -fmt=json ./...

Kết quả sẽ có dạng như sau

{
    "Golang errors": {},
    "Issues": [
        {
            "severity": "HIGH",
            "confidence": "LOW",
            "cwe": {
                "ID": "798",
                "URL": "https://cwe.mitre.org/data/definitions/798.html"
            },
            "rule_id": "G101",
            "details": "Potential hardcoded credentials",
            "file": "/home/random-user-here/shift-left-security-workshop/labs/source-code-lab/main.go",
            "code": "31: \t// STEP 2: Change this and the reference below to something different (ie, not \"pawsword\" or \"password\")\n32: \tvar pawsword = \"im-a-cute-puppy\"\n33: \tfmt.Println(\"Something a puppy would use: \", username, pawsword)\n",
            "line": "32",
            "column": "6"
        }
    ],
    "Stats": {
        "files": 1,
        "lines": 89,
        "nosec": 0,
        "found": 1
    }
}

Công cụ này đã xác định một vấn đề tiềm ẩn: Potential hardcoded credentials (Thông tin đăng nhập được mã hoá cứng tiềm ẩn)

5. Quét giấy phép

Giấy phép rất quan trọng đối với tính bảo mật vì chúng có thể yêu cầu pháp lý bạn phải tiết lộ mã nguồn mà bạn có thể không muốn tiết lộ. Khái niệm này được gọi là giấy phép "copyleft" yêu cầu bạn phải công khai mã nguồn nếu sử dụng các phần phụ thuộc có giấy phép đó.

Cài đặt golicense

mkdir -p /tmp/golicense
wget -O /tmp/golicense/golicense.tar.gz https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz
pushd /tmp/golicense
tar -xzf golicense.tar.gz
chmod +x golicense
mv golicense $(go env GOPATH)/bin/golicense
popd

Tạo tệp nhị phân

go build

Chạy kiểm tra giấy phép bằng tệp chính sách hiện tại không cho phép giấy phép "BSD-3-Clause"

golicense policies/license-policy.hcl hello-world

LƯU Ý: Lệnh này sẽ không thành công với kết quả tương tự:

 🚫 rsc.io/sampler    BSD 3-Clause "New" or "Revised" License
 🚫 rsc.io/quote      BSD 3-Clause "New" or "Revised" License
 🚫 golang.org/x/text BSD 3-Clause "New" or "Revised" License

Sửa đổi tệp chính sách policies/license-policy.hcl để di chuyển "BSD-3-Clause" từ danh sách deny sang danh sách allow.

Chạy lại kiểm tra giấy phép

golicense policies/license-policy.hcl hello-world

LƯU Ý: Lệnh này sẽ thành công với kết quả tương tự:

    ✅ rsc.io/quote      BSD 3-Clause "New" or "Revised" License
    ✅ rsc.io/sampler    BSD 3-Clause "New" or "Revised" License
    ✅ golang.org/x/text BSD 3-Clause "New" or "Revised" License

6. Xin chúc mừng

Xin chúc mừng, bạn đã hoàn thành lớp học lập trình này!

Kiến thức bạn học được

  • Các công cụ và kỹ thuật để bảo mật mã nguồn

Cập nhật lần gần đây nhất: 23/3/2023