flawopen.com/Teardowns/cve-2026-25592-semantic-kernel-agent-file-write
CVE-2026-25592: Semantic Kernel 파일 쓰기
CVE-2026-25592는 Semantic Kernel 다운로드 함수를 AI 도구로 노출해 호스트 파일 쓰기를 가능하게 했습니다. 모델 접근을 제거하고 1.71.0 이상으로 업데이트하세요.[2]
배달원은 잠긴 테스트실에서 회사 사무실로 소포를 옮길 수 있습니다. 원래 직원의 요청만 받아야 하지만, 배지가 AI 도우미의 지시도 따르게 만들었습니다. 악성 쪽지가 도우미를 설득해 사무실 서랍을 목적지로 고를 수 있습니다. 수정에서는 모델이 이 보조 함수를 호출하게 해 주는 배지를 제거합니다. 애플리케이션 코드가 직접 호출할 때도 목적지 제한 규칙이 필요합니다.[1], [2]
핵심 개념 및 용어
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 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 목록은 모든 전체 경로를 허용합니다. |
단계별 공격 실행 흐름
소스 코드 비교: 취약한 구현 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);
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓Microsoft.SemanticKernel.Plugins.Core를 1.71.0 이상으로 업그레이드하고 프로젝트 파일뿐 아니라 lockfile과 실제 runtime assembly를 확인하세요.[2]
- ✓SessionsPythonPlugin을 등록한 에이전트를 조사하고 모델 도구 schema에 DownloadFileAsync가 없는지 확인하세요.[1], [2]
- ✓애플리케이션 코드가 DownloadFileAsync 또는 UploadFileAsync를 호출한다면 Function Invocation Filter 등에서 정규화된 경로 허용 목록을 강제하세요.[2]
- ✓목적지 제한이 필요하면 AllowedDownloadDirectories를 비워 두지 마세요. upstream 구현은 빈 목록을 모든 전체 경로 허용으로 처리합니다.[3]
- ✓취약 배포 기간의 호스트 파일 쓰기 telemetry를 검토하고 승인된 디렉터리 밖에 대한 에이전트 프로세스 쓰기를 조사하세요. 노출 증거가 있을 때만 자격 증명을 교체하세요.
- ✓모델에 등록된 tool schema와 호스트 권한을 점검하고, 명시적으로 승인된 디렉터리 밖에 쓸 수 있는 에이전트 도구가 없는지 확인하세요.[1]