0. 문제

 

function escape(text) {
  var i = 0;
  window.the_easy_but_expensive_way_out = function() { alert(i++) };

// "A JSON text can be safely passed into JavaScript's eval() function
// (which compiles and executes a string) if all the characters not
// enclosed in strings are in the set of characters that form JSON
// tokens."

  if (!(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
          text.replace(/"(\\.|[^"\\])*"/g, '')))) {
    try { 
      var val = eval('(' + text + ')');
      console.log('' + val);
    } catch (_) {
      console.log('Crashed: '+_);
    }
  } else {
    console.log('Rejected.');
  }
}

 

1. 풀이

 

 해당 문제에서의 필터링은 text.replace(/"(\\.|[^"\\])*"/g, '')을 검사하기 때문에  "" 안에 있는 문자열은 검사에서 제외된다.

 

 이것을 이용해 alert(1)을 일으키면 되는데

 

 {}는 Object를 만드는 데 사용한다.

 

 Object의 기본 함수로 valueOf 이라는 함수가 존재하는데 이 함수의 리턴값을 해당 Object가 연산을 할때 사용하게 된다.

 

 따라서 valueOf 함수에 the_easy_but_expensive_way_out 함수를 넣어줘서 숫자와 연산을 진행하면 된다.

 

 (Object의 기본 함수중 toString 함수에 the_easy_but_expensive_way_out 함수를 넣어주고 문자열과 연산해도 괜찮음.)

 

 아래는 최종 payload이다.

 

0+{"valueOf":self["the_easy_but_expensive_way_out"]}+{"valueOf":self["the_easy_but_expensive_way_out"]}

 

 self는 window의 함수를 가져오는데에 사용된다.

 

 self["the_easy_but_expensive_way_out"]는 self.the_easy_but_expensive_way_out를 의미한다.

 

 그렇게 {"valueOf":self["the_easy_but_expensive_way_out"]} 라는 이 오브젝트의 연산 값을 the_easy_but_expensive_way_out()의 리턴값으로 정해주는 것이다.

 

 그러면 숫자와의 연산을 진행할때 alert(i++)이 실행되게 되고 첫 번째 연산때 alert(0)이 실행되고

 

 두 번째 연산때 alert(1)이 연산되어서 문제를 풀 수 있다.

 

 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

 글을 쓰다가 101글자짜리 payload를 찾아냈다.

 

 굳이 0이랑 연산을 안하고 오브젝트끼리 연산을 진행하게 해도 상관없으므로 '0+'를 빼도 alert(1)이 정상 실행된다.

 

 

 최종 payload:

{"valueOf":self["the_easy_but_expensive_way_out"]}-{"valueOf":self["the_easy_but_expensive_way_out"]}

 

 

 

 

 여기서 self["alert"]를 넣으면 안되는 이유는 alert()에는 인자가 필요하기 때문에 안되는 것 같다.

 

 

 라고 생각했지만 

 

 

 ....

 

 사용자 정의함수만 가능한건가..?

 

 1. alert(n)은 인자를 받기 때문에 valueOf에 들어갈 수 없다.

 

 2. alert(n)은 기본 내장 함수이기 때문에 valueOf에 들어갈 수 없다.

 

 둘중에 하나 같은데.. 찾아보고 다시 포스팅 해야겠다.

 

[Reference]

 

https://stackoverflow.com/questions/35949554/invoking-a-function-without-parentheses

 

Invoking a function without parentheses

I was told today that it's possible to invoke a function without parentheses. The only ways I could think of was using functions like apply or call. f.apply(this); f.call(this); But these require

stackoverflow.com

 

+ Recent posts