White-Box Auditing & Săn Bug Thực Chiến
~15 phútTaint Analysis & Static Code AuditingMiễn phí

Mini-challenge: Xây dựng Bộ Semgrep Rules chặn Lỗ hổng 0-Day

Thử thách độc lập: Viết bộ quy tắc Semgrep hoàn chỉnh để quét và phát hiện tự động một chuỗi lỗ hổng SpEL Injection và SSRF trong một repository mẫu.

TL;DR: Thử thách này đặt bạn vào vị trí của một AppSec Engineer chịu trách nhiệm bảo vệ một hệ sinh thái microservices Java & Go. Nhóm phát triển vừa báo cáo một mẫu code có nguy cơ dính SpEL Injection và SSRF do dùng thư viện nạp tài nguyên sai quy chuẩn. Nhiệm vụ của bạn là viết một bộ quy tắc audit-rules.yml bằng Semgrep, định nghĩa chính xác pattern và taint sources, kiểm thử để bắt đúng 100% các dòng code vi phạm mà không sinh ra bất kỳ false positive nào.

1. Tình huống thử thách

Công ty của bạn đang chuẩn bị phát hành phiên bản mới của một cổng API Core. Trước khi hợp nhất mã nguồn vào nhánh chính, bạn nhận được đoạn mã nguồn của 2 microservices sau:

File 1: NotificationService.java (Spring Boot)

Java
package com.corp.service;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.web.bind.annotation.*;

@RestController
public class NotificationService {
    private final ExpressionParser parser = new SpelExpressionParser();

    // DANGEROUS: SpEL RCE Vulnerability
    @PostMapping("/send")
    public String notify(@RequestParam("tpl") String tpl, @RequestBody User user) {
        StandardEvaluationContext ctx = new StandardEvaluationContext(user);
        return parser.parseExpression(tpl).getValue(ctx, String.class);
    }

    // SAFE: Static string parsing, no user input
    @GetMapping("/version")
    public String getVersion() {
        return parser.parseExpression("'v1.0.0'").getValue(String.class);
    }
}

File 2: WebhookDispatcher.java (Spring Boot)

Java
package com.corp.service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import org.springframework.web.bind.annotation.*;

@RestController
public class WebhookDispatcher {
    private final HttpClient client = HttpClient.newHttpClient();

    // DANGEROUS: SSRF Vulnerability
    @PostMapping("/dispatch")
    public void dispatchWebhook(@RequestParam("targetUrl") String targetUrl) {
        HttpRequest req = HttpRequest.newBuilder().uri(URI.create(targetUrl)).build();
        client.sendAsync(req, null);
    }

    // SAFE: Hardcoded domain
    @PostMapping("/ping-home")
    public void pingHome() {
        HttpRequest req = HttpRequest.newBuilder().uri(URI.create("https://internal.corp/ping")).build();
        client.sendAsync(req, null);
    }
}

2. Nhiệm vụ của bạn

Hãy vận dụng kiến thức về Metavariables, Taint Analysis và cú pháp Semgrep để viết file audit-rules.yml hoàn chỉnh thực hiện hai nhiệm vụ:

  1. Nhiệm vụ 1 (Chặn SpEL RCE): Bắt chính xác lời gọi parser.parseExpression(tpl) nhận đối số là một biến tham số từ @RequestParam, nhưng bỏ qua lời gọi an toàn parser.parseExpression("'v1.0.0'").
  2. Nhiệm vụ 2 (Chặn SSRF): Bắt chính xác lời gọi URI.create(targetUrl) nhận đối số là biến từ controller, nhưng bỏ qua các chuỗi URL tĩnh cố định "https://internal.corp/ping".

Dưới đây là câu hỏi dự đoán trước khi bạn xem lời giải mẫu:

Dự đoán hành vi: Cách Semgrep phân biệt hằng số và biến

Trong pattern của Semgrep, cú pháp nào dưới đây bắt buộc đối số truyền vào hàm URI.create() phải là một biến động chứ không phải một hằng số chuỗi ký tự '...'?

3. Lời giải mẫu & Đối chiếu thực nghiệm

Tự mình hoàn thành thử thách trước khi đối chiếu với lời giải chi tiết dưới đây:

Tự kiểm tra
0/3 câu đã trả lời
  1. Q1
    File quy tắc audit-rules.yml hoàn chỉnh của Semgrep để vượt qua thử thách này được viết như thế nào?
  2. Q2
    Tại sao chỉ thị 'pattern-not: ...("...")' lại có ý nghĩa sống còn trong việc giảm false positives?
  3. Q3
    Làm thế nào để kiểm thử bộ rule này cục bộ trên máy tính bằng lệnh Semgrep CLI?

4. AI Copilot Slot: Thử thách code review an toàn cùng AI

Khi lập trình viên nhờ AI viết rule SAST, các mô hình ngôn ngữ thường có xu hướng viết rule quá đơn giản dẫn tới cảnh báo tràn lan. Hãy thử nghiệm năng lực sinh rule của AI.

[!TIP] Prompt thử nghiệm (Copy & Test trên AI của bạn): "Hãy viết cho tôi một rule Semgrep YAML bằng ngôn ngữ Java để phát hiện lỗ hổng SpEL Injection khi gọi hàm parser.parseExpression(). Chú ý: tôi không muốn rule báo lỗi nếu đối số là một chuỗi hằng số tĩnh."

Đối chiếu thực tế: Quan sát xem AI có nhớ thêm khối pattern-not: $PARSER.parseExpression("...") để lọc chuỗi tĩnh hay không. Một chuyên gia bảo mật luôn kiểm tra xem rule có sinh ra false positive trên mã nguồn sạch hay không trước khi đưa vào CI/CD.

5. Liên hệ các bài khác

Bài tiếp theo: Tổng kết module Taint Analysis & Static Code Auditing

Bài này có giúp bạn hiểu bản chất không?

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Thảo luận & góp ý

Hỏi đáp về bài này

Bài tiếp theo

Tổng kết module Taint Analysis & Static Code Auditing