JSFuck
JavaScript编程风格 来自维基百科,自由的百科全书
JSFuck(或為了避諱髒話Fuck寫作 JSF*ck )是一種深奧的 JavaScript 編程風格。以這種風格寫成的代碼中僅使用 [
、]
、(
、)
、!
和 +
六種字符。此編程風格的名字衍生自僅使用較少符號寫代碼的Brainfuck語言。與其他深奧的編程語言不同,以JSFuck風格寫出的代碼不需要另外的編譯器或解釋器來執行,無論瀏覽器或JavaScript引擎中的原生 JavaScript 解釋器皆可直接運行。鑑於 JavaScript 是弱類型語言,編寫者可以用數量有限的字符重寫 JavaScript 中的所有功能,且可以用這種方式執行任何類型的表達式。[1]


alert(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]
備註
參考來源
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.