コンピューティング において、ポリグロットとは、複数のプログラミング言語またはファイル形式の有効な形式で記述されたコンピュータプログラムまたはスクリプト(またはその他のファイル)のことである。[ 1 ]この名称は、多言語主義との類推から名付けられた。ポリグロットファイルは、2つ以上の異なる形式の構文を組み合わせることによって構成される。[ 2 ]
ファイル形式をコンパイルまたはソースコードとして解釈する場合、そのファイルはポリグロットプログラムであると言えますが、ファイル形式とソースコードの構文はどちらも基本的にバイト列であり、この共通性を活用することがポリグロットの開発の鍵となります。[ 3 ]ポリグロットファイルは互換性において実用的な用途が限られていますが、[ 4 ]検証を回避したり脆弱性を悪用したりするために使用するとセキュリティリスクをもたらす可能性もあります。
多言語プログラムは、少なくとも1990年代初頭からハッカー文化における挑戦や珍品として作られてきた。注目すべき初期の例としては、単にという名前で1991年にUsenetpolyglotグループrec.puzzlesに公開されたものがあり、8つの言語をサポートしていたが、これはさらに以前のプログラムに触発されたものだった。[ 5 ] 2000年には、多言語プログラムが国際難読化Cコードコンテストで優勝した。[ 6 ]
21世紀には、ポリグロットプログラムとファイルがマルウェアの拡散のための隠れたチャネルメカニズムとして注目を集めました。[ 3 ] [ 7 ]ポリグロットファイルは互換性において実用的な用途が限られています。[ 8 ]
ポリグロットは、2 つ以上の異なるフォーマットの構文を組み合わせることによって構成され、フォーマット間で共通するさまざまな構文構造、または言語固有の構造でありながら各言語で異なる意味を持つ構造を活用します。ファイルは、複数の解釈プログラムで正常に解釈できる場合に有効なポリグロットです。たとえば、PDF-Zip ポリグロットは、有効な PDF 文書として開かれ、有効なzipアーカイブとして解凍される可能性があります。解釈プログラム間で有効性を維持するには、ある解釈プログラムに固有の構造が別の解釈プログラムによって解釈されないように、またその逆も行わないようにする必要があります。これは多くの場合、言語固有の構造を、他のフォーマットのコメントまたはプレーン テキストとして解釈されるセグメントに隠すことによって実現されます。[ 1 ]
多言語プログラムを構築する際によく用いられる2つの手法は、コメントに異なる文字を使用する言語を利用することと、さまざまなトークンを異なる言語で別のトークンとして再定義することです。これらの手法は、 ANSI C、PHP、およびbashで書かれたこのパブリックドメインの多言語プログラムで実証されています。
Bash向けにハイライト表示
#define a /* #<?php echo "\010Hello, world!\n" ; // 2 > /dev/null > /dev/null \ ; // 2 > /dev/null ; x = a ; $x = 5 ; // 2 > /dev/null \ ; if (( $x )) // 2 > /dev/null ; then return 0 ; // 2 > /dev/null ; fi #define e ?> #define b */ #include <stdio.h> #define main() int main(void) #define printf printf( #define true ) #define function function main () { printf "Hello, world!\n" true/* 2 > /dev/null | grep -v true*/ ; return 0 ; } #define c /* main #*/PHP向けにハイライト表示されています
#define a /* # <?php echo " \010 Hello, world! \n " ; // 2> /dev/null > /dev/null \ ; // 2> /dev/null; x=a; $x = 5 ; // 2> /dev/null \ ; if (( $x )) // 2> /dev/null; then return 0 ; // 2> /dev/null; fi #define e ?> #define b */ #include <stdio.h> #define main() int main(void) #define printf printf( #define true ) #define function function main () { printf "Hello, world! \n " true /* 2> /dev/null | grep -v true*/ ; return 0 ; } #define c /* main #*/C を強調表示
#define a /* #<?php echo "\010Hello, world!\n";// 2> /dev/null > /dev/null \ ; // 2> /dev/null; x=a; $x=5; // 2> /dev/null \ ; if (($x)) // 2> /dev/null; then return 0; // 2> /dev/null; fi #define e ?> #define b */ #include <stdio.h> #define main() int main(void) #define printf printf( #define true ) #define function function main () { printf "Hello, world! \n " true /* 2> /dev/null | grep -v true*/ ; return 0 ; } #define c /* main #*/以下の点にご注意ください。
<?php」と「」の PHP インジケーターは依然として有効です。?>function main()C #define を使用して " " に変換します。int main(void)if (($x))" は、bash と PHP の両方で有効なステートメントです。printfは、括弧が省略されている点を除けば、C の printfと同一のbashシェル組み込み関数です ( C コンパイラでコンパイルすると、C プリプロセッサが括弧を追加します)。main関数を呼び出すためにbashでのみ使用されます。PHPではmain関数は定義されていますが呼び出されず、C言語では明示的に関数を呼び出す必要はありませんmain。以下は、SNOBOL 4、Win32Forth、PureBasicv 4.x、およびREBOLで同時に記述されたものです。
SNOBOLに注目
* BUFFER : AA ; .( Hello, world !) @ To Including? Macro SkipThis ; OUTPUT = Char ( 10 ) "Hello, World !" ; OneKeyInput Input ( 'Char' , 1 , '[-f2-q1]' ) ; Char End ; SNOBOL4 + PureBASIC + Win32Forth + REBOL = < 3 EndMacro : OpenConsole() : PrintN("Hello, world !") Repeat : Until Inkey() : Macro S omeDummyMacroHere REBOL [ Title : "'Hello, World !' in 4 languages" CopyLeft : "Developed in 2010 by S ociety" ] Print "Hello, world !" EndMacro : func [][] set-modes system / ports / input [ binary : true] Input set-modes system / ports / input [ binary : false] NOP:: EndMacro ;新しい言語で洗練させたいですか?どうぞ!フォースに注目
*BUFFER : AA ; . ( Hello, world !) @ To Including? Macro SkipThis; OUTPUT = Char(10) "Hello, World !" ;OneKeyInput Input('Char', 1 , '[-f2-q1]') ; Char End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3 EndMacro: OpenConsole() : PrintN("Hello, world !") Repeat : Until Inkey() : Macro SomeDummyMacroHere REBOL [ Title: "'Hello, World !' in 4 languages" CopyLeft: "Developed in 2010 by Society" ] Print "Hello, world !" EndMacro: func [][] set-modes system/ports/input [binary: true] Input set-modes system/ports/input [binary: false] NOP:: EndMacro ;新しい言葉でそれを洗練させたいですか?どうぞ!BASIC向けにハイライト表示されています
* BUFFER : A . A ; . ( Hello , world ! ) @ To Including ? Macro SkipThis ; OUTPUT = Char ( 10 ) "Hello, World !" ; OneKeyInput Input ( 'Char', 1, '[-f2-q1]') ; Char End ; SNOBOL4 + PureBASIC + Win32Forth + REBOL = < 3 EndMacro: OpenConsole () : PrintN ( "Hello, world !" ) Repeat : Until Inkey () : Macro SomeDummyMacroHere REBOL [ Title: "'Hello, World !' in 4 languages" CopyLeft: "Developed in 2010 by Society" ] Print "Hello, world !" EndMacro: func [][] set - modes system / ports / input [ binary: true ] Input set - modes system / ports / input [ binary: false ] NOP: : EndMacro ;新しい言語で洗練させたいですか?どうぞ!REBOLに注目
*BUFFER : AA ; .( Hello, world !) @ To Including? Macro SkipThis; OUTPUT = Char ( 10 ) "Hello, World !" ;OneKeyInput Input('Char', 1, '[-f2-q1]') ; Char End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3 EndMacro: OpenConsole () : PrintN ( "Hello, world !" ) Repeat : Until Inkey () : Macro SomeDummyMacroHere REBOL [ Title: "'Hello, World !' in 4 languages" CopyLeft: "Developed in 2010 by Society" ] Print "Hello, world !" EndMacro: func [][] set-modes system /ports/input [ binary: true ] Input set-modes system /ports/input [ binary: false ] NOP:: EndMacro ; 新しい言語で洗練させたいですか? どうぞ!以下のファイルはMS-DOSバッチファイルとして実行され、その後Perlで再実行されます。
DOSバッチ用にハイライト表示されています
@ rem = ' --PERL-- @ echo off perl " %~dpnx0 " %* goto endofperl @ rem '; #!perl print "こんにちは、世界!\n" ; __終わり__ : endofperlPerl向けにハイライト表示されています
@rem = ' --PERL-- @echo off perl "%~dpnx0" %* goto endofperl @rem ' ; #!perl print "Hello, world!\n" ; __END__ :endofperlこれにより、最小限の手間でMS-DOSシステム上で実行可能なPerlスクリプトを作成できます。なお、異なるインタプリタ間でファイルが全く同じ機能を果たす必要はありません。
この例では、JavaScriptString.prototype.replaceとPythonの違いを利用しています。str.replace
JavaScript の強調表示
eval ( [ "console.log('Hello JavaScript')" , "print('Hello Python')" , ][ 1 - eval ( "1+1" . replace ( "1" , "0" ))] )Python向けにハイライト表示されています
eval ( [ "console.log('Hello JavaScript')" , "print('Hello Python')" , ][ 1 - eval ( "1+1" . replace ( "1" , "0" ))] )多言語話者の種類には以下が含まれます: [ 3 ]
ポリグロットマークアップは、 HTML5とXHTMLの利点を組み合わせた便利な方法として提案されています。[ 9 ]このようなドキュメントは、HTML( SGML互換)またはXMLのどちらとしても解析でき、どちらの場合も同じDOM構造を生成します。たとえば、HTML5ドキュメントがこれらの基準を満たすには、HTML5 doctypeを持ち、整形式のXHTMLで記述されている必要があります。同じドキュメントは、ブラウザのサポートとMIMEタイプに応じて、HTMLまたはXHTMLのどちらとしても配信できます。
HTML5の多言語ドキュメントを作成するには、html-polyglotの推奨事項[ 9 ]で示されているように、以下の重要な点に留意する必要があります。
したがって、最も基本的な多言語マークアップ文書は次のようになります。[ 9 ]
< !DOCTYPE html> < html xmlns = " http://www.w3.org/1999/xhtml " lang = " " xml :lang = " " > <head> <title>タイトル要素は空であってはなりません。</title> </head> <body> </body> </html>script多言語マークアップ文書では、空でない要素(<textarea> 、p<textarea>、<textarea>などdiv)は、たとえ空であっても自己閉じタグにすることはできません。これは有効な HTML ではないためです。[ 10 ]例えば、ページに空の textarea を追加するには、<textarea> や <textarea> は使用できず<textarea/>、代わりに <textarea> を使用する必要があります<textarea></textarea>。
DICOM医用画像フォーマットは、TIFF ファイルとの多言語対応を可能にするように設計されており、DICOMビューアまたは TIFF ビューアのどちらでも解釈できるファイルに同じ画像データを効率的に保存できます。[ 11 ]
Python 2とPython 3のプログラミング言語は互換性を持つように設計されていませんが、構文に十分な共通性があるため、両方のバージョンで動作する多言語Pythonプログラムを作成できます。[ 12 ]
2 つのフォーマットのポリグロットは、コメントフィールドに任意のデータを許可するJPEGファイルなど、一見無害で広く受け入れられているラッパー フォーマット内に、ステガノグラフィによって悪意のあるペイロードを組み込むことができます。脆弱な JPEG レンダラーは、ペイロードを実行するように強制され、攻撃者に制御を渡してしまう可能性があります。解釈プログラムが期待するものと、ファイルが実際に含まれているものとの間の不一致が、この脆弱性の根本原因です。[ 1 ]
SQLインジェクションはポリグロット攻撃の単純な形態であり、サーバーはユーザーが制御する入力が特定の制約に準拠することを素朴に期待するが、ユーザーが入力した構文がSQLコードとして解釈されてしまう。
セキュリティの観点からは、ポリグロットファイルが複数のフォーマットで厳密に有効である必要はありません。ファイルが主要なインタプリタによって解釈された際に、意図しない動作を引き起こすだけで十分です。
柔軟性や拡張性に優れたファイル形式は、多言語化の余地が大きく、そのため、より厳密に制約された解釈は、多言語技術を用いた攻撃に対するある程度の緩和策となります。たとえば、PDF ファイル形式では、マジックナンバーが%PDF-ファイル内のどこにでも出現することが許可されており、[ 13 ]多くの PDF インタープリタは、最初の 1024 バイト内にその文字列が出現する限り、ファイルを有効な PDF として受け入れます。これにより、多言語 PDF ファイルがファイルのヘッダーに PDF 以外のコンテンツを密かに持ち込む機会が生まれます。[ 3 ] PDF 形式は「多様で曖昧」と表現されており、異なる PDF 解析エンジン間で動作が大きく異なるため、2 つの異なる PDF リーダーで 2 つの異なるドキュメントとしてレンダリングされる PDF-PDF 多言語を作成することが可能です。[ 14 ]
多言語ファイル内に隠されたマルウェアを検出するには、ファイルなどのファイルタイプ識別ユーティリティに頼るよりも高度な分析が必要です。2019年に行われた市販のマルウェア対策ソフトウェアの評価では、そのようなパッケージのいくつかがテスト対象の多言語マルウェアを一切検出できないことが判明しました。[ 3 ] [ 2 ]
2019年、DICOM医療画像ファイル形式がPE -DICOMポリグロット技術を用いたマルウェア注入に対して脆弱であることが判明した。[ 15 ]攻撃のポリグロット性は、規制上の考慮事項と相まって、駆除の複雑さを招いた。「マルウェアは基本的に正規の画像ファイルに融合されている」ため、「インシデント対応チームやA/Vソフトウェアは、保護された患者の健康情報が含まれているマルウェアファイルを削除できない」。[ 16 ]
Graphics Interchange Format Java Archives ( GIFAR ) は、 GIF ファイル形式とJARファイル形式の両方を含む多言語ファイルです。 [ 17 ]この手法は、セキュリティの脆弱性を悪用するために使用できます。たとえば、画像アップロードを許可する Web サイト (有効な GIF ファイルであるため) に GIFAR をアップロードし、GIFAR の Java 部分を Web サイトの意図されたコードの一部であるかのように実行させ、同じオリジンからブラウザに配信することができます。[ 18 ] Java は JRE 6 Update 11 でパッチが適用され、2008 年 12 月に CVE が公開されました。[ 19 ] [ 20 ]
GIFARが可能なのは、GIF画像がファイルの先頭にヘッダーを保存し、JARファイル(ZIPアーカイブベースのフォーマットと同様)が末尾にデータを保存するためです。[ 21 ]
{{cite web}}: CS1 maint: url-status (リンク){{cite book}}: CS1 maint: 数値名: 著者リスト (リンク)