JSFuckはJavaScriptの特殊なサブセットで、コードは、、、、、、の6文字のみを使用して記述されます。名前は、句読点のみの最小限のアルファベットを使用する特殊なプログラミング言語である Brainfuck に由来しています。独自のコンパイラまたはインタプリタを必要とする Brainfuck とは異なり、JSFuckは有効な JavaScript コードであるため、JSFuck プログラムは JavaScript を解釈する任意のWeb ブラウザまたはエンジンで実行できます。JavaScript では任意の式を任意の型として評価できるため、JSFuck はこのような限られた文字セットを使用してすべての JavaScript 機能を再現できます。[ 1 ][]()!+
2009 年 7 月、長谷川陽介は、任意の JavaScript を 18 個のシンボルのみを使用して難読化された形式にエンコードできる jjencode という Web アプリケーションを作成しました[]()!+,\"$.:;_{}~=。[ 2 ] [ 3 ] 2010 年 1 月、sla.ckers.org Web アプリケーション セキュリティ サイトの「難読化」フォーラムで、必要な最小文字数を 8 未満に減らす方法を考案するための非公式のコンテストが開催されました。[]()!+,/スレッドの貢献者は、文字,と/文字の必要性を排除することに成功しました。[ 4 ] 2010 年 3 月の時点で、最後の 6 文字のみを使用する JS-NoAlnum というオンライン エンコーダが利用可能になりました。[ 5 ] 2010 年末までに、長谷川は、最小 6 文字のみを使用する JSF*ck という新しいエンコーダを公開しました。[ 6 ] [ 7 ] 2012年に、Martin KleppeはGitHub で「jsfuck」プロジェクトを作成し、[ 8 ]そのエンコーダーの実装を使用したウェブアプリを備えたJSFuck.comウェブサイトを作成しました。[ 9 ]
JSFuckは、Webサイトに送信された悪意のあるコードの検出を回避するために使用できます。たとえば、クロスサイトスクリプティング(XSS)攻撃などです。[ 10 ] JSFuckのもう1つの潜在的な用途は、コードの難読化です。最適化されたJSFuckバージョンは、 JavaScriptライブラリであるjQueryを、わずか6文字で記述された完全に機能するバージョンにエンコードするために使用されています。 [ 11 ]
JSFuck のコードは非常に「冗長」です。JavaScript では、「Hello, World!」というテキストが表示されたポップアップウィンドウを開くコードは 22 文字です。JSFuck では、同じコードの長さは 6448 文字になります。 [ 12 ]特定の単一文字は、JSFuck として展開すると 1000 文字をはるかに超える必要があります。このセクションでは、この展開の仕組みの概要を説明します。alert("Hello, World!")
数値 0 は+[]、 で作成されます。ここで[]は空の配列、+は単項プラスで、右辺を数値 (ここではゼロ) に変換する+!![]ために使用されます。数値 1 は、またはとして形成されます。+!+[]ここで、ブール値true( JSFuck では!![]またはと表現!+[]) は、先頭のプラス記号によって数値 1 に変換されます。数字 2 から 9 は、true適切な回数だけ合計することで形成されます。たとえば、JavaScript ではtrue + true= 2、true= !![]=なので、2 はまたは!+[]と書くことができます。他の数字も同様のパターンに従います。2 桁以上の整数は、プラス演算子を使用して 1 桁の配列を連結することで文字列として書きます。たとえば、文字列 はJavaScript で と表現できます。数字をそれぞれの JSFuck 展開に置き換えると、 となります。文字列ではなく数値を取得するには、前の式を括弧または角括弧で囲み、先頭にプラス記号を付けて、=とします。!![]+!![]!+[]+!+[]"10"[1] + [0][+!+[]]+[+[]]10+([+!+[]]+[+[]])
JSFuckでは、単純なブール値や数値の文字列表現から、インデクサ(角括弧内の数値)を使用して単一の文字にアクセスすることで、一部の文字を取得できます。他の文字を生成するには、別のトリックが必要です。たとえば、文字列を数値にキャストして"false"、文字にアクセスできるようにします。[ 13 ]"true""NaN""undefined"1e1000Infinityy
以下は、最も単純な文字を生成するための構成要素として使用される基本値のリストです。
"a": 文字列から取得"false"。"false" の 2 番目の文字は a であり、次のようにアクセスできます。
"false"[1]は、ブール定数 false と空の配列"false"から作成できます。false+[](false+[])[1]: false は次のように記述します。(![]+[])[1]: 1 は数なので、次のように書くことができます+true。(![]+[])[+true]: false は なので![]、true は です!![]。(![]+[])[+!![]]– これは「a」と評価されます。証明: JavaScript では、alert((![]+[])[+!![]])は と同じことをしますalert("a")。[ 14 ]
コンストラクタFunctionを使用すると、文字列に含まれる JavaScript コードをネイティブ JavaScript であるかのように実行できます。たとえば、ステートメントはalert()と同等ですFunction("alert()")()。コンストラクタは、 ( )などのよく知られた関数のコンストラクタFunctionプロパティにアクセスすることで JSFuck で取得できるため、は で実行できます。最新のブラウザでは、 ( ) [ 15 ]や( ) [ 16 ]などの短い名前の関数が利用可能です。[]["filter"]Array.prototype.filteralert()[]["filter"]["constructor"]("alert()")()[]["flat"]Array.prototype.flat[]["at"]Array.prototype.at
JSFuck展開が最も短い文字を以下に示します。その他のUTF-8文字も表現できますが、生成されるコードはかなり長くなります。
「通常の」JavaScriptの特徴を欠くJSFuckのような難読化技術は、悪意のあるJavaScriptコードが侵入防止システム[ 17 ]やコンテンツフィルタを回避するのに役立つ可能性があります。たとえば、JSFuckには英数字がなく、コンテンツフィルタに欠陥があったため、販売者は任意のJSFuckスクリプトをeBayのオークションページに埋め込むことができました。[ 10 ]