괄호 없이 JS 함수를 호출하는 새 기법, prepareStackTrace와 valueOf 트릭 조합
- prepareStackTrace를 덮어써서 Error 객체의 stack 속성에 접근할 때 Function 생성자가 실행되도록 만들어 임의 함수를 생성함
- 스택 배열을 유효한 JS 코드로 바꾸려고 Array.prototype.toString을 덮어쓰거나, Object.prototype.message를 오염시켜 Error의 toString을 가져다 씀
- 함수 호출은 valueOf 트릭으로 하며, 단항 플러스(+x)가 객체를 원시값으로 바꾸는 과정에서 valueOf가 실행됨
- 최종 페이로드는 alert(1337)을 띄우는 한 줄짜리 코드라서 브라우저 콘솔에 붙여 넣으면 바로 확인 가능함
Hacker News opinions
진짜 한 줄 치고 나니 할 말이 없음. JS는 아직도 별 걸 다 할 수 있다는 게 웃기면서도 무섭더라.
어제 쉐이더 코드 다시 보는데, 백틱 나오기 전에 (function(){/* */}).toString().match(...)로 멀티라인 문자열 뽑던 흔적이 나와서 식은땀 났음.
prototype 구조는 주류 언어 중에 독특하고 원리는 단순한데, valueOf랑 암묵적 형변환이 겹치면 프로덕션 코드에서 진짜 골칫거리임. CVE도 꽤 나오더라.
+x는 valueOf를 암묵적으로 부르려고 쓴 거임.
단항 플러스가 객체를 원시값으로 바꾸면서 valueOf를 부르는 구조라서, +x 하나로 실행이 끝나는 거임.
Firefox에선 안 된다고 하네. Error.prepareStackTrace가 옵션 API라서 V8만 구현했다더라.
함수를 인자 뒤에 두면 순서대로 읽혀서 좋겠다는 생각은 나도 함. 근데 그러면 (((x)h)g)f 식이 되는 거 맞지? 실행은 h부터니까.
D에서는 x.h().g().f()나 x.h.g.f처럼 괄호를 생략할 수 있음.
Haskell은 지연 평가라서 인자가 실제로 필요할 때까지 평가가 안 되니까, 실행 순서는 f에서 시작하는 식으로 보임. 그래도 나는 x |> h |> g |> f로 쓰는 게 편함.