FlawOpen

flawopen.com/AI Security/plugin4shell-ai-agent-plugin-sha-pin-bypass

● CWE-345 · 높음
보안 연구 · FlawOpen

Plugin4Shell: 플러그인 SHA 고정 우회

네 가지 AI 에이전트 플러그인 설치기는 Git 리비전을 고정하고도 checkout된 commit을 확인하지 않았습니다. Plugin4Shell은 최종 SHA 검증의 필요성을 보여줍니다.[1]

💡 알기 쉬운 설명 (ELI5)

도서관은 고유한 목록 번호로 특정 판본의 책을 예약합니다. 직원이 그 번호를 요청하고도 서가 표지에 같은 글자가 있으면 다른 책을 건넵니다. SHA 고정값은 목록 번호와 같습니다. 설치기는 플러그인을 신뢰하거나 실행하기 전에 실제 checkout된 commit을 확인해야 합니다.[1]

핵심 개념 및 용어

Commit SHA
특정 Git commit 객체를 식별하는 해시입니다. 안전한 고정 절차는 해석된 checkout을 이 값과 비교해야 합니다.[1], [2]
Git ref 모호성
Git은 객체 ID와 브랜치 같은 이름을 모두 리비전 표현식으로 처리합니다. 조건에 따라 commit ID처럼 보이는 이름이 ref로 해석될 수 있습니다.[1]
플러그인 마켓플레이스
에이전트 확장을 배포하고 검토된 리비전을 기록할 수 있는 카탈로그입니다. 설치 클라이언트도 고정값을 강제해야 합니다.[1]
CWE-345
데이터 진위 검증 부족: 시스템이 데이터가 예상한 진짜 값인지 충분히 확인하지 않고 사용합니다.[5]

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-345

단계별 공격 실행 흐름

단계 1

마켓플레이스가 검토된 commit을 기록

플러그인 항목은 저장소와 설치기가 사용해야 하는 특정 commit SHA를 가리킵니다.[1]

단계 2

저장소 제어자가 ref를 바꿀 수 있음

AIR Security에 따르면 이러한 이름을 허용하는 Git 호스트에서는 저장소 제어자가 요청된 SHA와 이름이 같은 기본 브랜치를 만들 수 있습니다. Gemini CLI에는 FETCH_HEAD ref 해석을 이용하는 별도 경로도 보고됐습니다.[1]

단계 3

설치기가 HEAD를 확인하지 않고 checkout

Codex 수정 전에는 요청한 SHA를 <code>git checkout</code>에 전달하고 Git 명령 성공을 고정값 준수의 증거로 간주했습니다.[1], [2]

단계 4

클라이언트가 실제 트리를 수락하거나 거부

Codex 수정은 checkout 후 <code>git rev-parse HEAD</code>를 읽고 불일치하면 중단합니다. 같은 확인이 없으면 바뀐 플러그인 코드가 에이전트 사용자의 권한으로 설치되어 실행될 수 있습니다.[2], [1]

소스 코드 비교: 취약한 구현 vs 보안 패치

취약한 경로는 이름 해석의 성공을 객체 동일성의 증명으로 혼동했습니다. 패치는 checkout 후 HEAD를 마켓플레이스 고정값과 비교하고 다른 commit의 materialization을 거부합니다. 이 코드 쌍은 Codex 패치이며 다른 제품은 구현이 다르므로 동일한 수정이 적용됐다고 가정하면 안 됩니다.[2], [6]

취약한 구현
// OpenAI Codex PR #34644 수정 전 형태
if let Some(target) = sha.or(ref_name) {
    run_git(&["checkout", target], Some(destination))?;
}
// checkout 성공을 SHA 일치의 증거로 간주했다.
보안 강화 패치
// Codex 수정: 요청 인자만이 아니라 해석된 commit을 검증
if let Some(sha) = sha {
    run_git(&["checkout", sha], Some(destination))?;
    let checked_out_sha =
        run_git_output(&["rev-parse", "HEAD"], Some(destination))?;
    if !checked_out_sha.eq_ignore_ascii_case(sha) {
        return Err(format!(
            "checked out Git SHA {checked_out_sha} does not match requested SHA {sha}"
        ));
    }
} else if let Some(ref_name) = ref_name {
    run_git(&["checkout", ref_name], Some(destination))?;
}

엔지니어링 및 시스템 보안 강화 체크리스트

출처

← AI Security Directory →