Lỗi về tính toàn vẹn của phần mềm và dữ liệu liên quan đến mã và cơ sở hạ tầng không bảo vệ khỏi các hành vi vi phạm tính toàn vẹn. Đây là một hạng mục mới trong Top 10 OWASP năm 2021, kết hợp quá trình khử tuần tự không an toàn với những lo ngại về an ninh chuỗi cung ứng.
Thất bại về tính toàn vẹn là gì?
Lỗi toàn vẹn xảy ra khi:
- Các ứng dụng dựa vào plugin, thư viện hoặc mô-đun từ các nguồn không đáng tin cậy
- CI/CD pipeline không xác minh tính toàn vẹn của mã trước khi triển khai
- Chức năng tự động cập nhật tải xuống các bản cập nhật mà không cần xác minh chữ ký
- Các đối tượng hoặc dữ liệu được giải tuần tự hóa từ các nguồn không đáng tin cậy
Khi tính toàn vẹn bị xâm phạm, kẻ tấn công có thể đưa mã độc vào chuỗi cung ứng phần mềm của bạn.
Các mẫu lỗ hổng phổ biến
1. Quá trình khử lưu huỳnh không an toàn
Vấn đề:
Việc giải tuần tự hóa dữ liệu không đáng tin cậy có thể dẫn đến việc thực thi mã từ xa.
// VULNERABLE: Deserializing user-controlled data
app.post('/api/import', (req, res) => {
// User sends serialized JavaScript object
const data = eval('(' + req.body.data + ')'); // DANGEROUS!
// ...
});
// VULNERABLE: Deserializing YAML without restrictions
const yaml = require('js-yaml');
app.post('/config', (req, res) => {
const config = yaml.load(req.body.yaml); // Can execute code!
});
Trình phân tích cú pháp YAML với sự hỗ trợ đầy đủ tính năng có thể khởi tạo đối tượng và gọi hàm tạo, dẫn đến thực thi mã.
Triển khai an toàn:
// SECURE: Use JSON for data interchange
app.post('/api/import', (req, res) => {
try {
const data = JSON.parse(req.body.data); // Safe
// Validate the structure
if (!validateSchema(data)) {
return res.status(400).json({ error: 'Invalid data format' });
}
} catch (e) {
return res.status(400).json({ error: 'Invalid JSON' });
}
});
// SECURE: Use safe YAML loading
const yaml = require('js-yaml');
app.post('/config', (req, res) => {
try {
// safeLoad only parses basic types, no code execution
const config = yaml.load(req.body.yaml, { schema: yaml.SAFE_SCHEMA });
} catch (e) {
return res.status(400).json({ error: 'Invalid YAML' });
}
});
2. Phụ thuộc không đáng tin cậy
Vấn đề:
Cài đặt các gói từ cơ quan đăng ký công cộng mà không cần xác minh.
# VULNERABLE: Installing without verification
npm install some-random-package
# VULNERABLE: Using unverified CDN scripts
<script src="https://cdn.example.com/library.js"></script>
Thực hành bảo mật:
# Use lock files with integrity hashes
npm ci # Installs from lock file, verifies integrity
# Verify package signatures
npm audit signatures
Đối với tập lệnh CDN, hãy sử dụng Tính toàn vẹn của nguồn phụ (SRI):
<!-- SECURE: Verify script integrity -->
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous">
</script>
3. CI/CD không an toàn pipeline
Vấn đề:
CI/CD pipeline không xác minh tính toàn vẹn của mã có thể triển khai mã độc.
# VULNERABLE: No code signing or verification
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install
- run: npm run build
- run: ./deploy.sh # Deploys whatever was built
Bảo mật pipeline:
# SECURE: Verify commits and artifacts
name: Deploy
on:
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Verify GPG signature on commits
- name: Verify commit signature
run: |
git verify-commit HEAD || {
echo "Commit is not signed!"
exit 1
}
# Lock file verification
- name: Install dependencies
run: npm ci # Strict installation from lock file
# Security scan before build
- name: Security audit
run: npm audit --audit-level=high
build:
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
# Sign the artifact
- name: Sign artifact
run: |
cosign sign-blob --key cosign.key dist/app.js
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
# Verify artifact signature before deploy
- name: Verify artifact
run: |
cosign verify-blob --key cosign.pub dist/app.js
- run: ./deploy.sh
4. Tự động cập nhật chưa được ký
Vấn đề:
Cơ chế tự động cập nhật không xác minh chữ ký có thể cài đặt các bản cập nhật độc hại.
// VULNERABLE: Download and execute without verification
async function checkForUpdates() {
const response = await fetch('https://updates.example.com/latest');
const update = await response.json();
if (update.version > currentVersion) {
const binary = await fetch(update.downloadUrl);
// Install without verification!
await installUpdate(binary);
}
}
Triển khai an toàn:
const crypto = require('crypto');
// Public key for update verification
const UPDATE_PUBLIC_KEY = process.env.UPDATE_PUBLIC_KEY;
async function checkForUpdates() {
const response = await fetch('https://updates.example.com/latest');
const update = await response.json();
if (update.version > currentVersion) {
// Download the update
const binaryResponse = await fetch(update.downloadUrl);
const binary = await binaryResponse.buffer();
// Download the signature
const sigResponse = await fetch(update.signatureUrl);
const signature = await sigResponse.text();
// Verify signature
const verify = crypto.createVerify('SHA256');
verify.update(binary);
if (!verify.verify(UPDATE_PUBLIC_KEY, signature, 'base64')) {
console.error('Update signature verification failed!');
return;
}
// Verify checksum
const hash = crypto.createHash('sha256').update(binary).digest('hex');
if (hash !== update.checksum) {
console.error('Update checksum mismatch!');
return;
}
// Now safe to install
await installUpdate(binary);
}
}
An ninh chuỗi cung ứng
Hóa đơn vật liệu phần mềm (SBOM)
Tạo SBOM để theo dõi tất cả các thành phần trong phần mềm của bạn:
# Generate SBOM using Syft
syft packages dir:. -o spdx-json > sbom.json
# Generate SBOM for container
syft packages docker:myapp:latest -o cyclonedx-json > sbom.json
Ký container image
Ký container image để đảm bảo tính toàn vẹn:
# Sign with Cosign
cosign sign --key cosign.key myregistry/myapp:v1.0.0
# Verify before deploying
cosign verify --key cosign.pub myregistry/myapp:v1.0.0
Thực thi xác minh chữ ký trong Kubernetes:
# Kyverno policy to require signed images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: enforce
rules:
- name: verify-signature
match:
resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "myregistry/*"
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Bài học chính
- Không bao giờ giải tuần tự hóa dữ liệu không đáng tin cậy - sử dụng JSON, tránh eval
- Sử dụng tệp khóa và xác minh tính toàn vẹn của gói
- Mã ký hiệu và tạo phẩm trong CI/CD pipeline của bạn
- Xác minh chữ ký trước khi triển khai hoặc cài đặt bản cập nhật
- Tạo SBOMs để theo dõi chuỗi cung ứng phần mềm của bạn
- Sử dụng tính toàn vẹn của nguồn phụ cho các tập lệnh được lưu trữ trên CDN
- Sign container image và thực thi xác minh
- Yêu cầu cam kết đã ký đối với các kho lưu trữ nhạy cảm
Các cuộc tấn công chuỗi cung ứng phần mềm ngày càng tinh vi. Việc xây dựng xác minh tính toàn vẹn trong quá trình phát triển và triển khai của bạn là điều cần thiết để bảo vệ.