[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 };
Patch Details
ConstExprGenerator의 Evaluate 모드 생성자에 offsetInSource 파라미터가 추가되었으며, 이 값은 evaluateExtendedConstExpr와 WebAssemblyModuleRecord::evaluateConstantExpression을 통해 전달됩니다. ModuleInformation::constantExpressions의 타입은 Vector<std::pair<Vector<uint8_t>, size_t>>(ConstantExpressionAndSourceOffset)으로 변경되었으며, SectionParser::parseInitExpr도 expression 바이트와 함께 initialOffset + m_offsetInSource 값을 기록하게 됩니다. 추가적인 방어 조치로, m_offsetInSource 선언에 기본값 { 0 }을 추가하여 기존의 미초기화 선언을 대체했습니다.
스택에 할당된 객체의 초기화되지 않은 멤버가 정수-텍스트 변환을 통해 웹에서 접근 가능한 error 문자열로 노출됩니다.
Background
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가 됩니다.
Analysis
ConstExprGenerator::m_offsetInSource는 초기화 없이 선언되어 있었습니다. Validate 모드 생성자만 offsetInSource 파라미터를 받았고, Evaluate 모드 생성자는 이 필드를 할당하지 않았습니다. ConstExprGenerator는 evaluateExtendedConstExpr 내부에서 스택에 할당되므로, 해당 필드에는 이전 프레임의 임의적인 스택 데이터가 담기게 됩니다.
Aaaaaaaa Aaaaaaaa Aaaaaaaaaa Aaa Aaaaaaa Aaa Aa Aaaaaaaaaaa Aaa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaaa Aaa Aaaaa Aaaa Aaaaaa a Aaaa Aaaaa Aa Aaaa Aa Aaa Aaaa Aaaaaaaa Aaaaaa Aaa Aaa Aaa Aaaaa Aa Aa Aa Aaa Aaa Aaa Aaaaaaaaaaaaaaaa Aa Aaaa Aaaaa Aaaaaaaaaaa Aa Aa Aa Aaa Aaaa Aaaa Aa Aaaaa Aaaaaaaaaaaaaaaaaa Aaa Aa Aa Aaa Aaa Aaaaaa Aaa a a Aaaaa
Aaaaaaaa Aaa Aaaa a Aa Aaaaa Aaaaa Aaa Aaaaaa Aaa Aa Aa Aaa Aaaa Aaa a Aa Aaaa Aa Aaaaa Aaa Aaaaaa Aaa Aaaa Aa Aaaa Aaa Aa Aa Aaa Aaaaa Aaa a Aaaaa Aa Aaaa Aa Aaa Aaaaa Aaaa Aa Aaaa Aaa Aaaaa Aaa Aaaaaaaaaaaaaaaa Aa Aa Aaa Aaaaa Aaa Aaa Aaaaa
a Aaaaaaaaaaaaaa Aaaa Aaaaaaa Aaaa Aaaa Aa Aaa Aaaa Aaaa Aaaaaaaaaaaaa Aaa Aaaaaaa
🔒An information-disclosure path through the WebAssembly module loader, including the chain that converts a parser diagnostic into a leaked memory primitive.
더 확인하려면 구독해 주세요
Audit directions
a Aaaaa Aaa Aaaaaaaaaaaaaaaaa Aaaaa Aa Aaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aa Aaa Aaaa Aaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaa a Aaa Aa Aaaaa Aaaaaa Aaaaaa
a Aaaa Aaa Aaaa Aa Aaa a Aaa Aaaaa Aaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaa Aaaaaa Aaaaa Aaa Aaaaaaaaaaa Aaaaa Aaaaaa
a Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaaaa Aaaaaaa Aaaaaaaa Aaaaaa Aaaaaaaaaaaaaaa a Aaaaaaa Aaaaaaaaaa Aaa Aaaaa Aaaa Aaaa Aaaaa Aaaaaa
a Aaaaaa Aaaaaaa Aaaa Aaaa Aa Aaa Aaaaa Aaaaaaaa Aaaa Aaaaa Aaaaaaaaaaaaaa Aaa Aaaaaaaa Aaa Aaaaa Aaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaa Aaaa Aaa Aaaaaa
🔒Several reusable audit patterns identified across JSC parsers and error formatters, with concrete starting greps for variant discovery.
더 확인하려면 구독해 주세요