基本的なHTML埋め蟌みスクリプトの脆匱性

問題の本質を説明するために、HTMLの䞀般的な配眮方法を䌝える必芁がありたす。 おそらく䞀般的な甚語で想像したず思いたすが、理解に必芁な䞻な点に぀いおは簡単に説明したす。 誰かが埅おない堎合は、ポむントに盎行しおください 。


HTMLはハむパヌテキストマヌクアップ蚀語です。 この蚀語を話すには、その圢匏に埓う必芁がありたす。そうしないず、曞かれたものを読む人はあなたを理解できたせん。 たずえば、HTMLでは、タグには次の属性がありたす。


<p name="value"> 

ここで、 [name]は属性の名前、 [value]はその倀です。 この蚘事では、コヌドの前埌に角かっこを䜿甚しお、コヌドの開始䜍眮ず終了䜍眮を明確にしたす。 名前の埌に等号があり、その埌に匕甚笊で囲たれた倀がありたす。 属性倀は、最初の匕甚文字の盎埌から始たり、どこにいおも次の匕甚文字の盎前で終わりたす。 これは、 [value]代わりに[value] [OOO " ".] [value]を曞く堎合、 name属性の倀は[OOO ]になり、芁玠には名前を持぀他の3぀の属性[] 、 []および["."] 、しかし意味なし。


 <p name="OOO "  "."></p> 

これが予期したものでない堎合は、属性の倀を䜕らかの方法で倉曎しお、匕甚笊が衚瀺されないようにする必芁がありたす。 あなたが考えるこずができる最も簡単なこずは、単に匕甚笊を切り取るこずです。


 <p name="OOO   ."></p> 

HTMLパヌサヌは倀を正しく読み取りたすが、問題は倀が異なるこずです。 あなたは[OOO " "]望んでいたしたが、あなたは[OOO .]を手に入れたした。 堎合によっおは、この違いが重芁になるこずがありたす。


倀ずしお任意の文字列を指定できるように、HTML蚀語圢匏は属性倀を゚スケヌプする機胜を提䟛したす。 倀文字列の匕甚笊の代わりに、䞀連の文字[&quot;]を蚘述でき[&quot;]パヌサヌは、属性倀ずしお䜿甚する元の文字列のこの堎所に匕甚笊があったこずを理解したす。 このようなシヌケンスはHTML゚ンティティず呌ばれたす。


 <p name="OOO &quot;  &quot;."></p> 

同時に、実際に゜ヌス文字列に文字シヌケンス[&quot;]があった堎合、パヌサヌが匕甚笊に倉換しないように蚘述する機䌚がありたす。これを行うには、 [&]蚘号を文字シヌケンス[&amp;]に眮き換え[&amp;] 、぀たり、 [&quot;]代わりに、生テキストに[&amp;quot;]を蚘述する必芁がありたす。


元の文字列から2぀の匕甚笊の間に蚘述した文字列ぞの倉換は、 明確で可逆的であるこずがわかりたす。 これらの倉換のおかげで、HTMLタグの属性ずしお、その内容の本質に觊れるこずなく、 任意の行を読み曞きできたす。 圢匏に埓うだけで、すべおが機胜したす。


実際、これは私たちが遭遇するほずんどのフォヌマットがこのように機胜する方法です構文があり、この構文からコンテンツを゚スケヌプする方法があり、そのようなシヌケンスが元の行にある堎合に゚スケヌプ文字を゚スケヌプする方法がありたす。 ほずんどですが、そうではありたせん...


<script>タグ


<script>タグは、他の蚀語で蚘述されたHTMLフラグメントを埋め蟌むために䜿甚されたす。 今日では99のケヌスでJavascriptです。 スクリプトは、開始<script>タグの盎埌から開始し、終了</ script>タグの盎前で終了したす。 HTMLパヌサヌはタグの内郚を調べたせん。これは、Javascriptパヌサヌに枡すテキストの䞀郚にすぎないためです。


Javascriptは、独自の構文を持぀独立した蚀語であり、䞀般的に、HTMLに埋め蟌たれるもののための特別な方法で蚭蚈されおいたせん。 その䞭には、他の蚀語ず同様に、䜕でもできる文字列リテラルがありたす。 たた、既に掚枬しおいるように、終了</ script>タグを意味する䞀連の文字が存圚する堎合がありたす。


 <script> var s = "surprise!</script><script>alert('whoops!')</script>"; </script> 

起こるべきこず s倉数には無害な文字列を割り圓おる必芁がありたす。


ここで実際に起こるこず倉数s宣蚀されおいるスクリプトは、実際には次のように終了したす [var s = "surprise!] 、構文゚ラヌになりたす。その埌のすべおのテキストは玔粋なHTMLずしお解釈され、テキストを埋め蟌むこずができたすマヌクアップこの堎合、新しい<script>タグが開かれ、悪意のあるコヌドが実行されたす。


属性倀に匕甚笊がある堎合ず同じ効果が埗られたした。 ただし、属性倀ずは異なり、<script>タグで元のコンテンツを゚スケヌプする方法はありたせん。 <script>タグ内のHTML゚ンティティは機胜せず、倉曎せずにJavascriptパヌサヌに枡されたす。぀たり、゚ラヌが発生したり、意味が倉わったりしたす。 HTML暙準では、<script>タグのコンテンツには、どのような圢匏でも文字シヌケンス</ script>を含めるこずはできたせん。 たた、Javascript暙準では、このようなシヌケンスが文字列リテラルのどこかにあるこずを犁止しおいたせん。


逆説的な状況が刀明したした。 有効なJavascriptを完党に有効な手段で有効なHTMLドキュメントに埋め蟌んだ埌、無効な結果を埗るこずができたす 。


私の意芋では、これは実際のアプリケヌションの脆匱性に぀ながるHTMLマヌクアップの脆匱性です。


脆匱性の悪甚方法


もちろん、コヌドを蚘述するだけでは、</ script>行に䜕を曞くか想像するのは難しく、問題に気付かないでしょう。 少なくずも、構文の匷調衚瀺により、タグが事前に閉じられおいるこずがわかりたす。最倧で、䜜成したコヌドは開始されず、䜕が起こったのかを長時間探したす。 しかし、これはこの脆匱性の䞻な問題ではありたせん。 HTMLを生成するずきにJavascriptにコンテンツを埋め蟌むず問題が発生したす。 次に、reactをレンダリングしたサヌバヌ䞊のアプリケヌションコヌドの頻繁な郚分を瀺したす。


 <script> window.__INITIAL_STATE__ = <%- JSON.stringify(initialState) %>; </script> 

initialState </ script>は、ナヌザヌたたは他のシステムからデヌタが送信される任意の堎所に衚瀺できたす。 JSON.stringifyは、JSONおよびJavascript圢匏ず完党に䞀貫しおいるため、シリアラむズ䞭にそのような文字列を倉曎したせん。したがっお、ペヌゞにアクセスし、攻撃者がナヌザヌのブラりザで任意のJavascriptを実行できるようにしたす。


別の䟋


 <script> analytics.identify( '<%- user.id.replace(/(\'|\\)/g, "\\$1") %>', '<%- request.HTTP_REFERER.replace(/(\'|\\)/g, "\\$1") %>', ... ); </script> 

ここで、サヌバヌに来たナヌザヌidずrefererは、適切な゚スケヌプで行に曞き蟌たれたす。 そしお、 user.idに数字以倖のほずんどない堎合、 referer攻撃者は䜕でもuser.idこずができたす。


しかし、終了タグ</ script>ゞョヌクはそこで終わりたせん。 開始<script>タグは、その前に文字[<!--]がある堎合も危険です[<!--]これは、プレヌンHTMLでは耇数行コメントの開始を瀺したす。 この堎合、ほずんどの゚ディタヌの構文匷調衚瀺は圹に立ちたせん。


 <script> var a = 'Consider this string: <!--'; var b = '<script>'; </script> <p>Any text</p> <script> var s = 'another script'; </script> 

健康な人ずほずんどの構文ハむラむトはこのコヌドで䜕を芋るのでしょうか 段萜の間にある2぀の<script>タグ。


病気のHTML5パヌサヌは䜕を芋たすか 圌は、2行目から最埌の行たでのすべおのテキストを含む1぀の閉じられおいない<script>タグを芋おいたす。


私はこれがなぜこのように機胜するのか完党には理解しおいたせん[<!--]文字[<!--]どこかでHTMLパヌサヌが開始および終了<script>タグのカりントを開始し、すべおが終了するたでスクリプトの完了を考慮しないこずを理解するだけ[<!--] <script>タグを開きたす。 ぀たり、ほずんどの堎合、このスクリプトはペヌゞの最埌に移動したす誰かが䞋に別の远加の終了</ script>タグを挿入できない限り、hehe。 あなたがこれに遭遇したこずがないなら、あなたは私が今冗談を蚀っおいるず思うかもしれたせん。 残念ながら、ありたせん。 䞊蚘のサンプルDOMツリヌのスクリヌンショットは次のずおりです。



最も䞍愉快なのは、JavaScriptで文字列リテラル内でのみ発生する終了</ script>タグずは異なり、文字シヌケンス<!--および<scriptがコヌド自䜓で発生する可胜性があるこずです そしお、それらはたったく同じ効果がありたす。


 <script> if (x<!--y) { ... } if ( player<script ) { ... } </script> 

あなたはたさに仕様ですか


HTML仕様は、<script>タグ内で有効な文字シヌケンスの䜿甚を犁止するこずに加えお、それらをHTML内で゚スケヌプする方法を提䟛しおいたせん。たた、次のこずも掚奚したす。


このセクションで説明する奇劙な制限を回避する最も簡単で安党な方法は、垞に「<-」を「<\-」、「<script」を「<\ script」、「</ script」ずしお゚スケヌプするこずです。 "as" <\ / script "これらのシヌケンスがスクリプト内のリテラルたずえば、文字列、正芏衚珟、たたはコメントに珟れるずき、および匏でそのような構造を䜿甚するコヌドの蚘述を避けるため。

「垞に゚スケヌプシヌケンス」ずしお翻蚳できるもの<!-- 「as」 <\!-- 「、」 <script "as" <\script "および" </script "as" <\/script " スクリプト内の文字列リテラルに含たれおおり、コヌド自䜓ではこれらの匏を避けたす。 この勧告は私を感動させたす。 ここでは、いく぀かの玠朎な仮定が䞀床に行われたす。


  1. 埋め蟌みスクリプトこれは必ずしもJavaScriptではありたせんでは、䞊蚘の文字シヌケンスは文字列リテラル内にあるか、蚀語構文で簡単に回避できたす。
  2. 文字列リテラルの埋め蟌みスクリプトでは、非特殊文字を゚スケヌプできたすが、これによりリテラルの倀は倉曎されたせん。
  3. スクリプトを埋め蟌む人は誰でもスクリプトの皮類を知っおおり、その構文を深く理解し、その構造を倉曎するこずができたす。

そしお、最初の2぀のポむントが少なくずもJavascriptで実行される堎合、最埌のポむントはそれでも実行されたせん。 HTMLにスクリプトを挿入するのは垞に資栌のある人ではなく、䜕らかのHTMLゞェネレヌタヌである可胜性がありたす。 ブラりザ自䜓がこれを凊理できない方法の䟋を次に瀺したす。


 var script = document.createElement('script') script.innerText = 'var s = "</script><script>alert(\'whoops!\')</script>"'; console.log(script.outerHTML); >>> <script>var s = "</script><script>alert('whoops!')</script>"</script> 

ご芧のずおり、シリアル化された芁玠を持぀行は、元の芁玠に䌌た芁玠に解析されたせん。 䞀般的な堎合の倉換DOMツリヌ→HTMLテキストは、䞀意ではなく、元に戻せたせん。 䞀郚のDOMツリヌは、単にHTML゜ヌステキストずしお衚すこずができたせん。


問題を回避する方法は


既に理解しおいるように、JavascriptをHTMLに安党に挿入する方法はありたせん。 ただし、JavascriptをHTMLに安党に埋め蟌む方法はありたす違いを感じおください。 確かに、このため、特にテンプレヌト゚ンゞンを䜿甚しおデヌタを挿入する堎合は、<script>タグ内に䜕かを蚘述しおいる間は垞に非垞に泚意する必芁がありたす。


たず、文字列リテラルではなく、゜ヌステキスト内の文字[<!-- <script>]極端に小さい可胜性瞮小埌でも。 あなた自身がこのようなこずを曞くこずはたずありたせん。攻撃者が<script>タグに䜕かを盎接曞くこずができる堎合、これらの文字の導入は最埌にあなたを悩たすでしょう。


文字列に文字を埋め蟌む問題が残っおいたす。 この堎合、仕様に曞かれおいるように、必芁なこずは、すべおの「 <!-- 」を「 <\!-- 」、「 <script 」を「 <\script 」、および「 </script 」を「 <\/script "。 しかし、問題は、 JSON.stringify()を䜿甚しお䜕らかの構造を出力する堎合、すべおの文字列リテラルを芋぀けおその䞭の䜕かをスクリヌニングするために、埌で再び解析したくないずいうこずです。 たた、状況が異なるため、この問題がすでに考慮されおいるシリアル化のために他のパッケヌゞを䜿甚するこずはお勧めしたせんが、垞に自分自身を守りたいし、解決策は普遍的でなければなりたせん。 したがっお、文字/およびを゚スケヌプするこずをお勧めしたす。 シリアル化埌にバックスラッシュを䜿甚したす。 これらの文字は、行内を陀いおJSONで芋぀けるこずができないため、単玔な眮換は絶察に安党です。 これにより、文字シヌケンス「 <script 」は倉曎されたせんが、単独で発生しおも危険ではありたせん。


 <script> window.__INITIAL_STATE__ = <%- JSON.stringify(initialState).replace(/(\/|\!)/g, "\\$1") %>; </script> 

同様に、個々の行を゚スケヌプできたす。


もう1぀のヒントは、<script>タグには䜕も埋め蟌たないこずです。 デヌタを挿入する倉換が明確で可逆的な堎所にデヌタを保存したす。 たずえば、他の芁玠の属性。 確かに、かなり汚く芋え、文字列でのみ動䜜したす。JSONは個別に解析する必芁がありたす。


 <var id="s" data="surprise!</script><script>alert(&quot;whoops!&quot;)</script>"></var> <script> var s = document.getElementById('s').getAttribute('data'); console.log(s); </script> 

しかし、良い方法で、もちろん、アプリケヌションを通垞どおりに開発し、地雷原を慎重に歩かない堎合は、HTMLにスクリプトを埋め蟌む信頌できる方法が必芁です。 したがっお、安党ではないため、<script>タグを完党に拒吊する正しい刀断を怜蚎したす。


<safescript>タグ


埋め蟌みスクリプトを䜿甚しない堎合、䜕をしたすか もちろん、すべおのスクリプトを倖郚から接続するこずはオプションではありたせん。HTMLドキュメント内にデヌタを持぀䜕らかのJavascriptがあるず䟿利な堎合がありたす。䜙分なHTTPリク゚ストはなく、サヌバヌ偎で远加のルヌトを䜜成する必芁はありたせん。


したがっお、新しいタグを導入するこずを提案したす-<safescript>、そのコンテンツは通垞のHTMLルヌルに完党に埓う-HTML゚ンティティはコンテンツを゚スケヌプするために動䜜したす-したがっお、スクリプトを埋め蟌むこずは絶察に安党です。


 <safescript> var s = "surprise!&lt;/script&gt;&lt;script&gt;alert('whoops!')&lt;/script&gt;"; </safescript> <safescript> var a = 'Consider this string: &lt;!--'; var b = '&lt;script&gt;'; </safescript> 

ブラりザでこのタグが実装されるのを埅぀必芁はありたせん。 すぐに䜿甚できる非垞にシンプルなセヌフスクリプトの芪友を䜜成したした。 これに必芁なものは次のずおりです。


 <script type="text/javascript" src="/static/safescript.js"></script> <style type="text/css">safescript {display: none !important}</style> 

<safescript>内のコヌドは、ひどくお異垞に芋えたす。 しかし、これはHTML自䜓に入るコヌドです。 䜿甚するテンプレヌト゚ンゞンで、タグを挿入し、そのすべおのコンテンツを゚スケヌプする単玔なフィルタヌを䜜成できたす。 Djangoテンプレヌト゚ンゞンのコヌドは次のようになりたす。


 {% safescript %} var s = "surprise!</script><script>alert('whoops!')</script>"; {% endsafescript %} {% safescript %} var a = 'Consider this string: <!--'; var b = '<script>'; {% endsafescript %} 

このアプロヌチにより、Javascript゚スケヌプを忘れ、倚くの脆匱性を回避できたす。 そしお、HTML仕様を開発しおいる人たちがそのようなスクリプトをベヌスセットに远加したり、HTMLでのスクリプトの安党でない埋め蟌みの問題を解決する他の方法を思い぀いたら玠晎らしいでしょう。



Source: https://habr.com/ru/post/J348558/


All Articles