JSFuck
JSFuck(或为了避讳脏话Fuck写作 JSF*ck )是一种深奥的 JavaScript 编程风格。以这种风格写成的代码中仅使用 [
、]
、(
、)
、!
和 +
六种字符。此编程风格的名字衍生自仅使用较少符号写代码的Brainfuck语言。与其他深奥的编程语言不同,以JSFuck风格写出的代码不需要另外的编译器或解释器来执行,无论浏览器或JavaScript引擎中的原生 JavaScript 解释器皆可直接运行。鉴于 JavaScript 是弱类型语言,编写者可以用数量有限的字符重写 JavaScript 中的所有功能,且可以用这种方式执行任何类型的表达式。[1]
缘起
长谷川阳介[註 1](Yosuke Hasegawa)于2009年7月创建了一个名为“jjencode”的网络应用程序,可将一切的JavaScript代码混淆为[]()!+,\"$.:;_{}~=
这十八个字符的排列组合[2][3]。
2010年1月,在一个Web应用程序安全站点上的“混淆”版块内,举行了一场非正式的竞赛。这场竞赛的目标是让JavaScript编程将所需的最少字符降至八个以下([]()!+,/
),而该帖文的回复者们设法消除了对,
和/
字符的需求[4]。截至2010年3月,网上有一个名为“JS-NoAlnum”的在线编码器,它只使用六个字符来混淆JavaScript[5]。
2010年底,长谷川洋介制作了一个名为JSF*ck的新编码器,它只使用了六个字符来混淆JavaScript[6][7]。2012年,马丁·克莱普在GitHub上创建了一个编码器项目“jsfuck”[8],并创建了JSFuck.com网站,放置了一个使用该编码器实现的Web应用程序[9]。
用途与安全性
JSFuck可用于代码混淆,一个优化版JSFuck编码器已经被用于混淆jQuery代码,使这一流行的JavaScript函数库可以仅使用六个字符来实现原本的所有功能[10]。
此外,JSFuck可用于绕过恶意代码检测,且可以被用于跨站脚本攻击[11]。因为缺乏原生JavaScript应有的特征,类似JSFuck的JavaScript混淆技术可帮助恶意代码绕过入侵防御系统或内容过滤器[12]。现实中,因为JSFuck中缺少字母数字字符,且eBay中的内容过滤器曾存在缺陷,使得卖家曾经可以在他们的eBay拍卖页面中嵌入任意JSFuck脚本[11]。
编码方式
JSFuck代码非常冗长。在JavaScript中,alert("Hello World");
这一代码将导致弹窗并显示“Hello World”字符串,这一代码的长度为21个字符。在使用JSFuck.com提供的JSFuck混淆程序后,转换出对应的相同效果代码长度为24691个字符。本节概述此转换方式的工作原理。
数字
数字0使用+[]
来构造,其中[]
代表空数组,而+
是一元加运算符。
数字1则以+!![]
或+!+[]
来构造,其中!![]
或!+[]
代表布尔值为真(true
),而前置的一元加运算符将真值转换为数字1。
数字2至9则以将“真”加和多次后转换为数值的类似方式来构造。例如,由true + true
这一表达式在JavaScript中输出结果为2,又true
可写作!![]
或!+[]
,故2可转写作!![]+!![]
或!+[]+!+[]
。
多位的整数则可将各数位分别表示,并使用串接运算符+
进行字符串串接。例如字符串"10"
可表达为两个数组串接的形式([1] + [0]
),将各数位替换为对应的JSFuck表达式后,即可将这一字符串表达为[+!+[]]+[+[]]
;若要将字符串转化为数字,可将前述的表达式括在括号或方括号中,并加上一个+
运算符,因此,数字值10可在JSFuck中表达为+([+!+[]]+[+[]])
。[13]
字母
通过使用索引器(即方括号中的数字)的方式,可以访问简单布尔值或数值对应字符串表示形式(如false
、true
、NaN
、undefined
)中的单个字符,而JSFuck可以借此转换一部分字母。此外,转换另一部分字母需要其他技巧,例如将字符串1e1000
转换为数字,这样就会产生无穷大值(Infinity
),而Infinity
中的字符可以用于获取字母y
。[13]
值 | 经JSFuck转化后 |
---|---|
false | ![] |
true | !![] 或!+[] |
NaN | +[![]] 或+[][[]] |
undefined | [][[]] |
Infinity | +(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]]) |
其他构造方法
在JavaScript中,Function
函数这种构造器可被用于触发执行包含在字符串中的JavaScript代码,正如像执行原生JavaScript代码那样。例如,语句alert(1)
等价于Function("alert(1)")()
。而Function
构造器在JavaScript中是任何常用函数的constructor
属性,此处所言的常见函数指的是像[]["filter"]
(即Array.prototype.filter)之类的函数。于是,这个构造器便可以通过访问一个空数组的filter
属性下的constructor
属性来构造。例如,alert(1)
可被等价转换为[]["filter"]["constructor"]("alert(1)")()
,并使用JSFuck进一步转换。[13]
参考来源
- Jane Bailey. . The Daily WTF. 2016-02-29 [2018-07-12]. (原始内容存档于2016-03-02).
- Hasegawa, Yosuke. . utf-8.jp. 2009-07-10 [2017-10-25]. (原始内容存档于2009-07-15).
- Hasegawa, Yosuke. . utf-8.jp. 2009-07-28 [2017-10-25]. (原始内容存档于2009-07-28).
- . Sla.ckers. 2010-01-14 [2017-10-25]. (原始内容存档于2011-03-01).
- . discogscounter.getfreehosting.co.uk. [2017-10-25]. (原始内容存档于2010-03-01).
- Hasegawa, Yosuke. . utf-8.jp. November 2010 [2017-10-25]. (原始内容存档于2010-12-01).
- Hasegawa, Yosuke. . utf-8.jp. 2010-11-30 [2017-10-25]. (原始内容存档于2010-11-30).
- Kleppe, Martin. . Github. 2012-07-16 [2017-10-25]. (原始内容存档于2018-07-13).
- . JSFuck. [2018-07-12]. (原始内容存档于2018-07-01).
- Trotta, Francesco. . GitHub. [2018-07-12]. (原始内容存档于2016-03-06).
- . rstechnica. 2016-02-03 [2018-07-12]. (原始内容存档于2016-12-02).
- . INFOBYTE SECURITY RESEARCH LABS. 2012-09-17 [2018-07-13]. (原始内容存档于2018-03-07).
- . GitHub. [2018-07-12]. (原始内容存档于2018-07-13).
外部链接
- JSFuck - Write any JavaScript with 6 Characters: []()!+ – 将原生JavaScript转换为JSFuck的Web应用程序
- Yosuke Hasegawa创作的JSF*ck在线应用页面存档备份,存于
- JSfuck.com所用的转换脚本 页面存档备份,存于