I've proven that you don't need quotes or parentheses in JavaScript
JavaScript에서 따옴표와 괄호 없이 문자열을 만드는 방법
JavaScript의 Error.prepareStackTrace와 내장 메서드를 조합해 따옴표나 괄호 없이 임의의 문자열을 생성하는 기법을 설명합니다. 생성한 문자열을 Function 생성자나 eval에 넣어 코드를 실행하는 방법도 제시하며, 작성자는 실용성은 거의 없지만 WAF 우회에는 쓰일 수 있다고 말합니다.
- 주제
에디터 노트
괄호를 막는 필터가 JavaScript 실행을 막아준다고 단정하기 어렵다는 점은 이 기법이 보여줍니다. Error.prepareStackTrace와 프로토타입 메서드를 조합해 문자를 만들고 Function 생성자나 eval에 전달하는 과정이 구체적으로 제시됐으며, 작성자도 WAF 우회 가능성을 언급합니다. 다만 글은 이 방식의 일반적인 공격 성공률이나 실제 방어 우회 사례를 수치로 보여주지 않습니다. 댓글에서는 PortSwigger XSS 치트시트에 이미 비슷한 기법이 실렸다는 보완이 나왔고, 작성자도 이를 확인합니다. 따라서 이 사례의 가치는 새로운 범용 공격 도구라기보다 제한된 문자 필터가 코드 실행을 충분히 통제하지 못한다는 구체적인 예시에 있습니다. AI 역공학이 보안 도구의 가치를 없앤다는 댓글은 근거를 제시하지 않은 의견입니다.
AI 요약
JavaScript에서 따옴표와 괄호를 쓰지 않고 문자열을 만들려면 Error.prepareStackTrace와 프로토타입 메서드를 연결할 수 있습니다. Error.prepareStackTrace는 오류 객체의 stack 속성을 읽을 때 호출되며, Error 함수와 오류 객체, 구조화된 스택 정보를 인수로 받습니다. 글은 이 동작을 이용해 String 메서드 같은 함수를 괄호 없이 호출하는 과정을 설명합니다.
Error.prepareStackTrace로 메서드 호출하기
Error.prepareStackTrace에 String.prototype.concat 같은 함수를 지정하면 stack을 읽는 시점에 해당 함수가 호출됩니다. Error 함수와 오류 객체, Array 프로토타입의 toString 동작을 바꾸면 함수에 전달되는 this와 인수 값을 조정할 수 있습니다. 다만 값이 들어가는 문맥에 따라 내부의 toString 변환이 일어나지 않을 수 있어 모든 함수 호출에 적용되지는 않습니다.
문자열과 숫자 만들기
글은 String.prototype.split을 이용해 문자열을 문자 배열로 나누고, Array.prototype.join과 lastIndexOf 등을 이용해 빈 문자열과 -1을 얻는 절차를 제시합니다. 배열의 shift를 연속 호출하면 대괄호 인덱싱 없이 원하는 위치의 문자를 꺼낼 수 있습니다. Array.prototype.indexOf가 반환하는 -1을 조합하고 값을 더하거나 빼서 숫자를 만든 뒤 join으로 문자열로 바꾸면 숫자 문자열도 준비할 수 있습니다.
이 문자와 숫자를 조합해 String.fromCharCode 호출을 담은 표현식을 만들고, 이를 Function 생성자에 전달하면 원하는 문자열을 반환하는 함수를 구성할 수 있습니다. 글은 반환된 문자열 대신 문자 코드로 인코딩한 JavaScript를 eval에 전달하면 임의 코드를 실행하는 형태로 확장된다고 설명합니다. 전체 페이로드는 길고 읽기 어려우며, 작성자는 실용성은 거의 없고 WAF 우회 가능성이 있을 수 있다고 언급합니다.
Reddit 반응
- @DrAdalbbert — Error.prepareStackTrace를 String 프로토타입 함수로 덮어써 괄호 없이 호출하고, Error와 Array 프로토타입을 조정해 인수를 제어할 수 있습니다. JSFuck에서 착안한 기법을 더하면 제한된 문자만으로 JavaScript 문자열을 만들고 실행할 수 있습니다.
- @Designer_Mountain_84 — 그런데 왜 필요한가요?
- @DrAdalbbert — 왜 안 되겠어요. WAF 우회 정도를 빼면 실제 용도는 전혀 없지만 재미있습니다.
- @Ahri — 실용적인 용도가 꽤 있습니다. PortSwigger의 XSS 치트시트를 보세요.
- @DrAdalbbert — 맞습니다. 이미 치트시트에 Error.prepareStackTrace에서 Function 생성자를 괄호 없이 쓰는 방법으로 들어 있습니다.
- @Spleeeee — 주된 용도는 유희입니다.
- @Valkertok — AI가 컴파일된 코드를 효율적으로 역공학하는 시대라면 사이버보안 도구로는 쓸모가 없습니다.
- @jippen — jsfuck 트랜스파일러의 혼란스러운 결과를 본 적 있나요? 이것도 재미있어할 것 같습니다.
- @DrAdalbbert — 제 방식은 JSFuck의 정반대라고 생각합니다. 일부 문자를 얻는 기법은 JSFuck에서 빌렸습니다. 물론 괄호 없이 적용했습니다.
원문: blog.ikaes.de / 번역·요약: Trawling