FlawOpen

flawopen.com/Teardowns/cve-2026-25592-semantic-kernel-agent-file-write

● CVE-2026-25592 · CVSS 9.9[2], [4] · 심각
보안 연구 · FlawOpen

CVE-2026-25592: Semantic Kernel 파일 쓰기

CVE-2026-25592는 Semantic Kernel 다운로드 함수를 AI 도구로 노출해 호스트 파일 쓰기를 가능하게 했습니다. 모델 접근을 제거하고 1.71.0 이상으로 업데이트하세요.[2]

💡 알기 쉬운 설명 (ELI5)

배달원은 잠긴 테스트실에서 회사 사무실로 소포를 옮길 수 있습니다. 원래 직원의 요청만 받아야 하지만, 배지가 AI 도우미의 지시도 따르게 만들었습니다. 악성 쪽지가 도우미를 설득해 사무실 서랍을 목적지로 고를 수 있습니다. 수정에서는 모델이 이 보조 함수를 호출하게 해 주는 배지를 제거합니다. 애플리케이션 코드가 직접 호출할 때도 목적지 제한 규칙이 필요합니다.[1], [2]

핵심 개념 및 용어

KernelFunction
Semantic Kernel에서 메서드를 모델이 호출할 수 있는 도구로 공개하는 특성입니다.[1], [2]
SessionsPythonPlugin
에이전트가 격리된 원격 Python 세션의 코드와 상호작용하게 하는 Semantic Kernel 플러그인입니다.[1], [2]
localFilePath
DownloadFileAsync에 전달되는 선택적 호스트 측 저장 경로입니다.[1], [2]
경로 허용 목록
명시적으로 설정하고 정규화한 디렉터리 아래에서만 쓰기를 허용하는 정책입니다.[1], [2], [5]

프레임워크 매핑

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

근본 원인 분석 (Root Cause)

.NET용 Semantic Kernel의 SessionsPythonPlugin은 원격 Python 세션과 애플리케이션 호스트를 연결합니다. DownloadFileAsync는 세션에서 파일을 가져오고 반환된 바이트를 호스트의 localFilePath에 저장할 수 있습니다. 이 메서드에는 KernelFunction 특성이 붙어 있어 모델이 도구를 선택할 때 인수를 볼 수 있었습니다. 공격자가 에이전트 입력에 영향을 줄 수 있다면, 의도하지 않은 목적지로 보조 함수를 호출하도록 유도할 수 있습니다. 이는 도구 권한 부여와 경로 경계의 실패이며, 언어 모델의 결함이나 원격 Python 세션의 sandbox 탈출은 아닙니다. Microsoft 수정은 DownloadFileAsync에서 KernelFunction을 제거해 모델이 호출하지 못하게 합니다. 애플리케이션 코드가 계속 이 보조 함수를 쓴다면 명시적인 허용 디렉터리 정책을 설정하고 강제하세요. 해당 목록이 비어 있으면 upstream 구현은 모든 목적지를 허용합니다. GHSA-2ww3-72rp-wpp4는 NuGet Microsoft.SemanticKernel.Plugins.Core 1.71.0 미만과 PyPI semantic-kernel 1.39.3 미만도 영향을 받는 버전으로 나열합니다. 이 글은 Microsoft가 설명한 .NET 공격 경로에 초점을 둡니다.[1], [2], [3]

패키지 범위 및 수정 버전

패키지 / 범위영향받는 버전 및 수정 버전이 문서에서 다루는 내용
.NET Microsoft.SemanticKernel.Plugins.Core영향받는 버전: < 1.71.0; 수정 버전: 1.71.0 이상.문서화된 SessionsPythonPlugin 경로입니다. 모델이 호출할 수 있는 DownloadFileAsync가 세션 데이터를 호스트 경로에 쓸 수 있었습니다.
Python semantic-kernel영향받는 버전: < 1.39.3; 수정 버전: 1.39.3 이상.권고문에는 이 패키지도 포함됩니다. 이 문서는 Python 고유의 공격 경로를 분석하지 않습니다. Python 패키지는 별도로 업그레이드하세요.
세션 파일을 의도적으로 호스트에 저장하는 애플리케이션모델 호출 경로를 제거한 뒤에도 대상 경로를 제한하세요.Function Invocation Filter 또는 이에 상응하는 권한 계층에서 정규화된 경로의 명시적 허용 목록을 사용하세요. upstream 구현에서 빈 AllowedDownloadDirectories 목록은 모든 전체 경로를 허용합니다.

단계별 공격 실행 흐름

단계 1

신뢰할 수 없는 콘텐츠가 에이전트에 영향

공격자는 처리 대상으로 제공되는 콘텐츠처럼 에이전트 입력에 영향을 줄 방법이 필요합니다. Microsoft가 문서화한 경로에서는 첫 번째 tool 호출이 격리된 원격 Python 세션에 파일을 둡니다. 이 단계에서 파일은 세션 안에 격리되어 있습니다.[1], [2]

단계 2

모델이 호스트 측 보조 함수를 봄

영향받는 .NET 배포에서는 KernelFunction 때문에 DownloadFileAsync가 모델 호출 가능 도구에 포함되었습니다.[1], [2]

단계 3

인수가 신뢰 경계를 넘음

원격 세션 파일을 요청할 때 모델이 localFilePath를 선택할 수 있었습니다. 보조 함수는 호스트 프로세스에서 이 경로를 처리했습니다.[1], [2]

단계 4

호스트 파일 쓰기가 가능해짐

호스트에 쓰려면 모델이 신뢰할 수 없는 입력에 영향을 받은 localFilePath를 사용해 이 helper를 호출해야 하며, 그 경로가 실제로 적용되는 허용 디렉터리 밖이어야 합니다. Microsoft가 설명한 것은 통제된 연구 경로이며 광범위한 악용 보고가 아닙니다.[1], [2]

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

upstream 패치는 DownloadFileAsync에서 KernelFunction 특성을 제거해 도구 등록 경계에서 모델 접근을 차단합니다. 애플리케이션 코드가 의도적으로 사용하는 시그니처는 남습니다. advisory는 Function Invocation Filter와 명시적 경로 허용 목록으로 DownloadFileAsync 및 UploadFileAsync 인수를 검증하는 것도 권고합니다. Path.GetFullPath만으로는 권한 정책이 되지 않으며, upstream 구현에서 AllowedDownloadDirectories가 비어 있으면 경로 제한이 없습니다.[2], [3]

소스 코드 발췌: 해당 메서드: `SessionsPythonPlugin`의 `DownloadFileAsync`

취약한 구현
[KernelFunction, Description("Downloads a file from the current session.")]
public abstract Task<byte[]> DownloadFileAsync(
    string remoteFileName,
    string? localFilePath = null,
    CancellationToken cancellationToken = default);
보안 강화 패치
[Description("Downloads a file from the current session.")]
public abstract Task<byte[]> DownloadFileAsync(
    string remoteFileName,
    string? localFilePath = null,
    CancellationToken cancellationToken = default);

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

출처