JSFuck

出典: フリー百科事典『ウィキペディア(Wikipedia)』

これはこのページの過去の版です。Stepney-I.C.I. (会話 | 投稿記録) による 2021年2月6日 (土) 15:25個人設定で未設定ならUTC)時点の版 (内部リンク追加)であり、現在の版とは大きく異なる場合があります。

JSFuckJavaScriptのサブセットである難解プログラミング言語で、コードは[,], ()!+の6文字で構成される。ネーミングセンスはBrainfuckを参考にしていて、難解プログラミング言語の中ではアルファベットが一文字も使われない。コンパイラインタプリタを必要とするBrainfuckとは異なり、WebブラウザJavaScriptエンジンで動作させることができる。JSFuckはJavaScriptが動的型付けのため、完全にJavaScriptの関数を上記の6文字で置き換えることができる。[1] 2009年7月にハセガワヨウスケがJavaScriptを[]()!+,\"$.:;_{}~=の18文字に変換するWebアプリケーションを作った。[2][3]

2010年1月には、 sla.ckers.orgというWebアプリケーションセキュリティサイトの「Obfuscation」フォーラムで非公式の競争が開催され、文字数を(当時そうだろうと考えられていた)必要最小限の8文字([]()!+,/)に抑える方法が考案された。 その後、どうにか ,/ を使わないようにできないか模索され、[4] 同年3月にはJS-NoAlnumと呼ばれる(現在の)6文字で表現されるエンコーダーができた。 [5] 同年の終わり[いつ?]ハセガワはJSF*ckと呼ばれる6文字で表現されるエンコーダーを完成させた。 [6][7] 2012年には、Martin Kleppe が"jsfuck"と名前をつけたプロジェクトをGitHub上で公開した。 [8] そしてJSFuck.comというサイトでエンコーダーの実装を公開している。[9]


JSFuckは悪質なコードウェブサイトクロスサイトスクリプティング (XSS)等によって埋め込むことにも使われたことがある。[10]他の潜在的な使用方法としては、難読化がある。 よく使われるライブラリであるjQueryも、6文字で完全に置き換えられたことがある。[11]

変換の手順

JSFuckは非常に冗長である。JavaScriptではalert("Hello World!")としてポップアップを開くであろうコードは21字である。しかし、同じことを JSFuckでしようとすると22948字にもなる。いくつかの文字はJSFuckで表現しようとすると1000文字を超える。この節はどうやって文字を生成することができるのか説明する。

数字

0は+[]によって作られる。ここで、[]は空の配列であり、+単項プラス英語版である。ここに型変換が働いて、 []は0とみなされる[12]

1は+!![]+!+[]で、論理値true (JSFuckでは!![]!+[]として表現される)が数字の1に変換されたものである[13]

2から9については、!![] (前述の通り1)をその回数だけ繰り返し、それを+で連結すれば良い。 これを踏まえると2は!![]+!![]!+[]+!+[]と書くことができる。 2桁以上の場合は、1桁ずつ数字として配列に詰めたあと、それを1要素連結すればよい。 例として"10"[1] + [0]と書き換えることができる。 前述の0と1の作り方を適用すると、これは[+!+[]]+[+[]]となる。 数字を返したい場合は、頭に+をつける(この例では10 = +([+!+[]]+[+[]]))

文字

JSFuckではいくつかの文字は論理値や"NaN"、"undefined"から添字付き(角括弧の中に数字が入ったもの)で取り出すことになる。 他の文字を生成するためにさらなるトリックが存在する。"1e1000"を数字に型変換すると、Infinityとなり、yを簡単に取り出すことができるようになる。[14]下に記したのは最もシンプルにプリミティブな値を作るコードである。

JSFuck
false ![]
true !![]!+[]
NaN +[![]]
undefined [][[]]
Infinity +(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])

例:"a"の生成

  • "a": 文字列"false"から取ることにする。"false"の2文字目は"a"である。これは
  • "false"[1]としてアクセスできる。"false"false+[]から作ることができる。すなわち、falseと空の配列を足すことになる。
  • (false+[])[1]: falseは![]から生成できるので(論理否定を空の配列に適用する)
  • (![]+[])[1]: 1は数字であるので、これを+trueで置き換えると
  • (![]+[])[+true]: そしてfalseは![]でtrueは!![]なので
  • (![]+[])[+!![]] - これで"a"を返す。

証拠: JavaScriptで実際に試してみると、alert((![]+[])[+!![]])alert("a")は同じ出力である。[15]

他の生成

FunctionコンストラクタはJavaScriptとして有効なコードを実行することができるので、alert(1)Function("alert(1)")()と同じである。Functionのコンストラクタは、[]["filter"] (Array.prototype.filter) のようによく知られた[誰によって?]関数のconstructorプロパティから取り出すことができる。このことを踏まえると、alert(1)[]["filter"]["constructor"]("alert(1)")()と書き換えることができる。

文字表

文字を作ることができる一番短いコードを下に記した。他の文字も生成できるがおそらくもっと長くなるだろう。

文字 JSFuck
+ (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]]
. (+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]
0 +[]
1 +!![]+!+[]
2 !![]+!![]!+[]+!+[]
3 !![]+!![]+!![]!+[]+!+[]+!+[]
4 !![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]
5 !![]+!![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]+!+[]
6 !![]+!![]+!![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
7 !![]+!![]+!![]+!![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
8 !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
9 !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]
a (![]+[])[+!+[]]
d ([][[]]+[])[!+[]+!+[]]
e (!![]+[])[!+[]+!+[]+!+[]]
f (![]+[])[+[]]
i ([![]]+[][[]])[+!+[]+[+[]]]
I (+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))+[])[+[]]
l (![]+[])[!+[]+!+[]]
N (+[![]]+[])[+[]]
n ([][[]]+[])[+!+[]]
r (!+[]+[])[+!+[]]
s (![]+[])[!+[]+!+[]+!+[]]
t (!+[]+[])[+[]]
u ([][[]]+[])[+[]]
y (+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))])[+!+[]+[+[]]]

セキュリティ

JSFuckのような難読化技術は、「通常の」JavaScriptに備わる"クラッキング防止システム"が存在しない[16]ため、eBayのオークションのページにJSFuckで書かれたスクリプトを埋め込むことができた [17]

脚注

  1. ^ Jane Bailey/The Daily WTF: "Bidding on Security". http://thedailywtf.com/articles/bidding-on-security
  2. ^ Hasegawa, Yosuke (2009年7月10日). “jjencode - Encode any JavaScript program using only symbols”. utf-8.jp. 2009年7月15日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  3. ^ Hasegawa, Yosuke (2009年7月). “UTF-8.jp [2009-07-28]”. utf-8.jp. 2009年7月28日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  4. ^ Yet Another Useless Contest (but fun!) Less chars needed to run arbitrary JS code”. sla.ckers.org (2010年1月14日). 2011年3月1日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  5. ^ js-noalnum_com.php”. discogscounter.getfreehosting.co.uk. 2010年3月1日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  6. ^ Hasegawa, Yosuke (2010年11月). “JSF*ck - [()!+]”. utf-8.jp. 2010年12月1日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  7. ^ Hasegawa, Yosuke (2010年11月). “UTF-8.jp [2010-11-30]”. utf-8.jp. 2010年11月30日時点のオリジナルよりアーカイブ。2017年10月25日閲覧。
  8. ^ Kleppe, Martin (2012年7月16日). “Commits · aemkei/jsfuck”. github.com. 2017年10月25日閲覧。
  9. ^ Kleppe, Martin (2012年9月). “Site report for www.jsfuck.com”. toolbar.netcraft.com. 2017年10月25日閲覧。
  10. ^ https://arstechnica.com/security/2016/02/ebay-has-no-plans-to-fix-severe-bug-that-allows-malware-distribution/ Ars Technica: Ebay has no plans to fix severe bug that allows malware distribution
  11. ^ https://github.com/fasttime/jquery-screwed jQuery JavaScript library made of only six different characters: ! ( ) + [ ]
  12. ^ 単項和演算子 + を付けられた項は暗黙的に数値に型変換される。配列を数値に変換するとその文字列の表す数値が得られる(参照:Arithmetic operators (Web technology for developers)”. 2019年10月12日閲覧。)が、[](空配列)の場合得られる値 +[] はゼロである。
  13. ^ [](空配列)は論理値 true を持つと定義されている(すなわちtruthyである(参照:Truthy (Web technology for developers)”. 2019年10月12日閲覧。))ため、これに二重not演算した !![] はtrueであり、それを数値に型変換した +!![] は1になる。
  14. ^ http://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html "Brainfuck Beware: JavaScript is after you!"
  15. ^ Adapted from: https://esolangs.org/wiki/JSFuck
  16. ^ Ré Medina, Matías A. (2012-09). Bypassing WAFs with non-alphanumeric XSS. Retrieved from http://blog.infobytesec.com/2012/09/bypassing-wafs-with-non-alphanumeric-xss.html.
  17. ^ eBay has no plans to fix "severe" bug that allows malware distribution [Updated]”. Ars Technica (2016年2月4日). 2018年9月8日閲覧。

外部リンク