← All issues

[17] [JSC] Save source offset for evaluating Wasm constant expressions

Severity: Medium | Component: JSC WebAssembly module loader | b05d16f

extended constant expression 평가가 실패할 때마다 초기화되지 않은 64비트 스택 워드 하나가 WebAssembly.RuntimeError.message를 통해 유출됩니다. ASLR을 무력화하기에 충분한 info-leak primitive로 작동하지만, 공격자가 선택한 주소를 직접 읽는 primitive는 아닙니다. 이 점에서 Medium으로 평가합니다.

Source/JavaScriptCore/wasm/WasmConstExprGenerator.cpp

- ConstExprGenerator(Mode mode, const ModuleInformation& info, JSWebAssemblyInstance* instance)
+ ConstExprGenerator(Mode mode, size_t offsetInSource, const ModuleInformation& info, JSWebAssemblyInstance* instance)
: m_mode(mode)
+ , m_offsetInSource(offsetInSource)
, m_info(info)
, m_instance(instance)
...
Mode m_mode;
- size_t m_offsetInSource;
+ size_t m_offsetInSource { 0 };

ConstExprGenerator의 Evaluate 모드 생성자에 offsetInSource 파라미터가 추가되었으며, 이 값은 evaluateExtendedConstExprWebAssemblyModuleRecord::evaluateConstantExpression을 통해 전달됩니다. ModuleInformation::constantExpressions의 타입은 Vector<std::pair<Vector<uint8_t>, size_t>>(ConstantExpressionAndSourceOffset)으로 변경되었으며, SectionParser::parseInitExpr도 expression 바이트와 함께 initialOffset + m_offsetInSource 값을 기록하게 됩니다. 추가적인 방어 조치로, m_offsetInSource 선언에 기본값 { 0 }을 추가하여 기존의 미초기화 선언을 대체했습니다.

스택에 할당된 객체의 초기화되지 않은 멤버가 정수-텍스트 변환을 통해 웹에서 접근 가능한 error 문자열로 노출됩니다.

Wasm extended constant expression(GC / ext-const proposal)은 초기화 위치에서 단순 상수를 넘어서는 연산을 허용합니다. array.new, struct.new, i32.add 등이 그 예입니다. 이 expression들은 모듈 컴파일 시점에 파싱되고, import/global에 의존하는 결과를 도출하기 위해 instance 생성 시점에 다시 실행됩니다. JSC는 두 단계를 모두 ConstExprGenerator를 통해 처리하며, 두 가지 모드로 동작합니다. SectionParser::parseInitExpr 단계에서는 Validate 모드, WebAssemblyModuleRecord::evaluateConstantExpression 단계에서는 Evaluate 모드입니다. 두 모드는 공통 fail() 헬퍼를 공유하는데, 이 헬퍼는 m_parser->offset() + m_offsetInSource를 사용해 WebAssembly.Module doesn't parse at byte N: ... 형식의 문자열을 구성합니다. fail() 내부에서 발생한 오류는 JS로 throw되는 JSWebAssemblyRuntimeError.message가 됩니다.

ConstExprGenerator::m_offsetInSource는 초기화 없이 선언되어 있었습니다. Validate 모드 생성자만 offsetInSource 파라미터를 받았고, Evaluate 모드 생성자는 이 필드를 할당하지 않았습니다. ConstExprGeneratorevaluateExtendedConstExpr 내부에서 스택에 할당되므로, 해당 필드에는 이전 프레임의 임의적인 스택 데이터가 담기게 됩니다.

🔒

An information-disclosure path through the WebAssembly module loader, including the chain that converts a parser diagnostic into a leaked memory primitive.

더 확인하려면 구독해 주세요

🔒

Several reusable audit patterns identified across JSC parsers and error formatters, with concrete starting greps for variant discovery.

더 확인하려면 구독해 주세요