JSFUCK 분석

JSFUCK이란?

위키백과에 의하면 Martin Kleppe이 개발한 자바스크립트의 난해한 프로그래밍 스타일이라고 소개되어있다.

(![]+[])[+!+[]]                         // "a"
([][+[]]+[])[!+[]+!+[]]                 // "d"
(!+[]+[])[!+[]+!+[]+!+[]]               // "e"
(![]+[])[+[]]                           // "f"
([][+[]]+[])[!+[]+!+[]+!+[]+!+[]+!+[]]  // "i"
(![]+[])[!+[]+!+[]]                     // "l"
([][+[]]+[])[+!+[]]                     // "n"
(!+[]+[])[+!+[]]                        // "r"
(![]+[])[!+[]+!+[]+!+[]]                // "s"
(!+[]+[])[+[]]                          // "t"
([][+[]]+[])[+[]]                       // "u"

위 코드처럼 [ ], ( ), !, +를 통해 알파벳으로 활용할 수 있다. 또한 숫자로도 변환 가능하다. 또한 한글이나 일본의 가타카나를 통해서도 가능하다. 이러한 방법으로 XSS 필터링을 우회하여 XSS 공격을 시도할 수도 있다.

 

취업 후 취약점 진단을 진행하였는데, XSS 필터링이 걸어져 있어서 JSFUCK을 통해 가볍게 우회에 성공하여 JSFUCK에 대하여 작성하고자 한다.

저런 값들이 왜 출력되는 것일까?

나는 왜 (![]+[])[+!+[]]이 왜 a로 출력이 되는지 궁금하였다. 위키백과나 블로그의 글을 읽어보면 저 조합이 a로 출력된다는데 이유를 적은 글을 보기 힘들었다.

 

몇가지 글을 읽고 나는 이유를 알 수 있었는데, 쉽게 설명하자면 "Boolean과 indexing를 이용했다"라고 말할 수 있다.

 

숫자 결과값

js에선 []은 배열을 뜻한다. 그럼 +를 한다면? 어떻게 될까?

 

0이 나오게 된다.

 

왜 0이 나오게 되는지 조사한 결과 택시 운전사 블로그에서 알 수 있었다.

+[]+는 이진법 더하기 연산자가 아니라, 연산대상을 숫자로 바꿔주는 접두사로 사용된다. 즉, Number()가 작동된다는 뜻이다.

또한 +[]에서 [][].toString()으로 변환이되어 빈 문자열이 출력하게 된다.

 

정리하자면 +[]Number("")으로 변환이 되어 0이 출력하게 된다는 것이다.

 

"0은 알겠다. 그럼 1~9은 어떻게 만들어지는 건지 잘 모르겠다."라는 분들을 위해 설명하겠다.

쉽게 설명하자면, !를 이용하여 0을 ture로 변환 후 Number()를 이용하여 1로 변환하는 것이라고 설명할 수 있다.

 

이해가 안 간다면 위 사진을 참고하면 쉽게 알 수 있을 것이다. !를 사용하면 Not 연산을 하기 위해 boolean으로 변환한다.

이 때문에 0이 Not 연산 후 True가 되어 +를 통해 Number()에 넣어지게 되어 1이 출력되게 된 것이다.

 

+!+[] 말고도 +!![]를 사용하여 1을 출력할 수 있다.

여기서 깊게 고민하신 분들은 "왜 !!flase이 true가 되는 것이지?"라는 의문점이 생길 것이다.

 

이러한 의문점에 대한 해답은 Bugtype - [WTF JS] 3. true == [] 랑 true == ![] 같은 거 알고있지?IfUWanna - [Javascript] 느낌표 두개(!!) 사용법 (논리 연산자)에서 잘 정리되어 있다.

 

결론은 ![]!은 Not 연산을 하는 것이 아니고, Boolean()만 수행하여 false가 출력된 다는 것이다.

 

2~9은 어떻게 해야하냐면 위 사진처럼 1이 출력되는 !![]이나 !+[]를 더하기로 더하면 된다.

 

문자 출력값

문자의 경우 indexing을 이용하여 원하는 문자를 뽑아낸다.

[]+[]은 배열끼리 연산이 되어 빈 문자열이 출력된다. 여기서 !를 이용하여 Boolean을 사용하면, 빈 문자열이 Boolean이 된 후 Boolean이 문자열이 된다. 그래서 문자열로 false이 출력된 것이다.

 

이후 Indexing을 통해 원하는 문자를 출력하는 것이다.

 

여기서 "true, false 문자열의 문자만 갖고 올 수 있는거 아닌가?"이라는 의문점을 가질 수 있다.

 

위 사진처럼 생각하지도 못 했던 곳에서 문자열 생성할 수 있다.

'Security Study' 카테고리의 다른 글

Log4Shell 정리  (0) 2021.12.30