序文 Web セキュリティの台頭
Web 攻撃技術の開発もいくつかの段階に分けることができます。Web 1.0
この時代では、実行可能スクリプト (一般に として知られている) をサーバーにアップロードしてアクセス許可を取得する
など、サーバー側の動的スクリプトのセキュリティ問題にさらに注意が払われています。インジェクションはその後に登場し、インジェクションの出現はセキュリティの歴史における画期的な出来事であり、インジェクションの脆弱性は依然としてセキュリティ分野の重要な部分を占めています。続いて、別のマイルストーンとなるセキュリティ問題(クロスサイト スクリプティング攻撃) が発生しました。の台頭により、 、、 などの攻撃がより強力になりました。攻撃の概念もサーバー側からクライアント側、ブラウザーとユーザーに移りました。webshell
SQL
SQL
Web
SQL
Web
XSS
Web 2.0
XSS
CSRF
Web
Web
今日のテクノロジーの発展により、豊かでカラフルなインターネットが構築されています。インターネット ビジネスの精力的な発展により、 、、など
の多くのスクリプト言語も誕生しました。アジャイル開発はインターネットの主要テーマとなっています。携帯電話技術とモバイル インターネットの台頭も、新たな機会と課題をもたらしました。同時に、セキュリティ技術もインターネットの発展と歩調を合わせ、常に新たな変化を進化させていきます。Python
Ruby
NodeJS
HTML 5
Web
クロスサイト スクリプティング攻撃 ( XSS
) は、クライアント側のスクリプティング セキュリティにおける最大の敵です。脅威は繰り返しリストの上位にOWASP TOP 10
挙げられており、この記事では攻撃面と防御面の問題に焦点を当てます。XSS
XSS
予備探査XSS
クロスサイトスクリプティング攻撃、英語の正式名称はCross Site Script
、本来の略称は ですが、CSS
カスケードスタイルシート(Cascading Style Sheet
、 )とCSS
区別するため、XSS
セキュリティ分野では「 」と呼ばれています。
XSS
攻撃とは通常、ハッカーがHTML
改ざんされた Web ページを挿入し、ユーザーが Web を閲覧するときにユーザーのブラウザを制御する悪意のあるスクリプトを挿入する攻撃行為を指します。この動作が最初に登場したとき、デモンストレーションのケースはすべてクロスドメイン動作であったため、「クロスサイト スクリプティング」と呼ばれていました。現在、Web
端末の機能とアプリケーションが複雑になっているため、クロスサイトであるかどうかは重要ではありませんが、XSS
その名前はそのまま残されています。
Web
開発の急速な発展に伴い、Web
開発は以前のシングルPC
エンドから現在のモバイルエンド(APP
、H5
)に至るまで、デスクトップツールや機器の大画面なども含めて広く使用されるようになり、生成されるアプリケーションシナリオはますます増えています。多くの、ますます複雑な状況が存在すると同時に、ほとんどのインターネット (特に伝統的な業界) 製品開発バージョンの反復リリース時間は非常に短く、1 週間に 1 つのバージョンと 2 週間に 1 つの大きなバージョンの場合、セキュリティという重要な属性が無視され、一度攻撃されると悲惨な結果になります。
XSS
攻撃タイプの分類
XSS
攻撃は、反射型 (非永続的)、ストレージ型 (永続的)、およびベースの 3 つのカテゴリに分類できますDOM XSS
。
反射性の
反射型は、XSS
ユーザーが入力したデータを単にブラウザに「反映」するだけです。言い換えれば、ハッカーが攻撃を成功させるには、多くの場合、ユーザーに悪意のあるリンクを「クリック」させる必要があります。反射型は「非持続型XSS
」とも呼ばれます( )。**XSS**
**Non-persistent XSS**
通常、Web サイト検索、ジャンプなどのパラメータを渡す機能を介して、反射型XSS
の悪意のあるコードが存在します。悪意のある Web サイトを有効にするには、ユーザーが積極的にその Web サイトを開く必要があるため、攻撃者はさまざまな方法を組み合わせてユーザーにクリックを誘導することがよくあります。URL
URL
URL
最も基本的なリフレクション攻撃の 1 つは、Web ページ データを取得することです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XSS攻防演练</title>
</head>
<body>
<div id="t"></div>
<input id="s" type="button" value="这是一个按钮" onclick="test()">
</body>
<script>
function test() {
const arr = ['自定义的数据1', '自定义的数据2', '自定义的数据3', '<img src="11" οnerrοr="console.log(window.localStorage)" />']
const t = document.querySelector('#t')
arr.forEach(item => {
const p = document.createElement('p')
p.innerHTML = item
t.append(p)
})
}
</script>
</html>
ハッカーが をクリックすると这是一个按钮
、ローカルlocalStorage
データが簡単に取得でき、重要な情報を入手できます。
ストレージタイプ
ストレージ タイプは、XSS
ユーザーが入力したデータをサーバー側に「保存」します。これはXSS
非常に安定しています。
比較的一般的なシナリオは、ハッカーが悪意のあるコードを含むブログ投稿を作成し、記事が公開されると、そのブログ投稿にアクセスしたすべてのユーザーがブラウザでJavaScript
この悪意のあるコードを実行することです。JavaScript
ハッカーは悪意のあるスクリプトをサーバーに保存するため、この種の攻撃は「ストレージ型」XSS
と呼ばれます。**XSS**
<!-- 例如我们分别在网站中的输入框中输入以下信息,并保存到远程数据库 -->
<img src="11" onerror="console.log(window.localStorage)" />
<img src="11" onerror="alert(111)" />
ページ入力
alert
ユーザーがページを参照すると、ポップアップ ボックスがトリガーされ、ローカル データが連続して取得されますlocalStorage
。
上記は典型的なストレージ攻撃です。
に基づくDOM XSS
実はこのタイプはXSS
「サーバー側にデータが保存されているかどうか」によって分けられているわけではなく、DOM Based XSS
実質的にはそれも反映されていますXSS
。DOM Based XSS
このタイプは、その形成理由が非常に特殊であり、これを発見したセキュリティ専門家が特にこのタイプを提案したため、別個に分けられますXSS
。DOM 型 XSS
前の 2 つとの違いは、攻撃中に悪意のあるコードの抽出と実行がブラウザによって行われることです。これはXSS
フロントエンド自体のセキュリティ脆弱性ですが、他の 2 つはサーバーのセキュリティ脆弱性です。DOM 型 XSS
JavaScript
XSS
簡単な例を見てみましょう。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XSS攻防演练</title>
</head>
<body>
<h3>基于DOM的XSS</h3>
<input type="text" id="input">
<button id="btn">提交内容</button>
<div id="div"></div>
</body>
<script>
const input = document.getElementById('input');
const btn = document.getElementById('btn');
const div = document.getElementById('div');
let inputValue;
input.addEventListener('change', (e) => {
inputValue = e.target.value;
}, false);
btn.addEventListener('click', () => {
div.innerHTML = `<a href=${
inputValue}>链接地址</a>`
}, false);
</script>
</html>
ページ上の入力ボックスに次のテキストを入力します'' onclick=alert(/xss/)
。ここでの引用符は属性を閉じて null 値を与える''
ために使用されます。href
次に提交内容
ボタンをクリックすると、ページ内のラベルに<div id="div"></div>
次のhtml
コンテンツが含まれます
<a href onlick="alert(/xss/)">链接地址</a>
XSS
攻撃防御
防御はXSS
非常に複雑ですが、幸いなことに、最新のブラウザーとフロントエンド フレームワーク/ライブラリは、すでに作業のかなりの部分を行ってくれています。
HttpOnly
HttpOnly
これは最初に Microsoft によって提案され、IE 6
中国で実装され、徐々に標準になりました。ブラウザは、属性をJavaScript
持つページへのアクセスを禁止します。したがって、他の方法ではコンテンツを取得できないことをブラウザに知らせるために、応答ヘッダーに設定する必要があります。HttpOnly
Cookie
http
set-cookie
httpOnly
document.cookie
cookie
厳密に言えば、事後解決ハイジャック攻撃HttpOnly
に対抗するためのものではありません。したがって、これを使用すると攻撃を軽減できますが、依然として脆弱性を解決できる他のソリューションが必要です。XSS——HttpOnly
XSS
Cookie
HttpOnly
XSS
XSS
入力チェック
ユーザー入力については懐疑的になる必要があります。ユーザーは、入力に対してフィルタリング チェックを行わずに、任意の文字列を入力できます。たとえば、入力すると予想されるコンテンツは次のとおりです。hello word
おそらく受信したコンテンツは ですonclick=alert(/xss/)
。
防御の観点からXSS
、入力チェックでは通常、ユーザーが入力したデータに特殊文字が含まれているかどうかがチェックされます<、>、’、”
。特殊文字が見つかった場合、これらの文字はフィルタリングまたはエンコードされます。この入力チェックの方法を と呼ぶことができます“XSS Filter”
。“XSS Filter”
インターネット上にはオープンソースの実装が数多くあります。たとえば、単純なhtmlencode
エスケープ:
const htmlEncode = function (handleString){
return handleString
.replace(/&/g,"&")
.replace(/</g,"<")
.replace(/>/g,">")
.replace(/ /g," ")
.replace(/\'/g,"'")
.replace(/\"/g,""");
}
しかし、入力チェックには次のような欠点もあります。
- 攻撃者はフロントエンド ページをバイパスし、インターフェイスを直接使用して悪意のあるコードをリモート ライブラリに送信します。
- 入力データが複数の場所に表示され、それぞれの場所のコンテキストが異なる場合もあり、単一の置換操作を使用すると問題が発生する可能性があります。入力チェックも対象にする必要があり、ある数値が他の数値より小さいことを表現したい場合(
3 < 4
)、フロントエンドのエスケープ後の文字は となり3 < 4
、この値をリモートエンドに格納すると取得されますAJAX
。数値計算などを行うと余計なトラブルの原因となります。
出力チェック
一般に、リッチ テキストの出力に加えて、変数をHTML
ページに出力する場合、エンコードまたはエスケープを使用してXSS
攻撃を防御できます。
XSS の本質は依然として一種の「HTML インジェクション」であり、ユーザー データが HTML コードの一部として実行されるため、元のセマンティクスが混乱し、新しいセマンティクスが生成されます。
入力チェックと同様に、出力をエンコードおよびエスケープできます。
1.HTML
出力先
たとえば、HTML コードには次のようなコードがあります。
<div>$htmlVar</div>
<a href="">$htmlVar</a>
出力変数が安全に処理されない場合、出力変数が直接使用され、ページ上にレンダリングされる可能性があり、直接生成につながる可能性がありますXSS
。最終結果として、次のコードが生成される場合があります。
<div><script>alert('我是一个XSS攻击者')</script></div>
<a href="#"><img href="" onclick="alert('我是另外一个XSS攻击者')"></a>
これを防ぐ方法は、HTML でエスケープ チェックを実行することです。
2.HTML
プロパティへの出力
html 属性が動的な値の場合、exploit 属性も攻撃される可能性があります。
<div id="testXSS" data-name=""></div>
次に、data-name
エスケープされていないコードを属性に挿入すると"><script>alert('我是一个XSS攻击者')</script><"
、結果は次のようになります。
<div id="testXSS" data-name=""><script>alert('我是一个XSS攻击者')</script><""></div>
3.<script>
ラベルに出力
タグで出力する場合は<script>
、まず出力変数が引用符で囲まれていることを確認する必要があります。
<script>
// 假设userData是攻击者注入的数据
let xssVar = userData;
</script>
XSS 攻撃を実装するには、攻撃者はまず引用符を閉じる必要があります。
<script>
// 假设userData是攻击者注入的数据
let xssVar = "";alert('我是一个script XSS攻击者');
</script>
4.CSS
出力先
CSS
、、の作り方は非常に多様でstyle
あるため、「ラベル」、「ラベル属性」、「ファイル」には、ユーザーが制御できる変数の出力は原則として可能な限り禁止されています。このような要件が必要な場合は、CSS エスケープ ライブラリを使用することをお勧めします。style attribute
XSS
<style>
HTML
style
CSS
防衛DOM Based XSS
DOM Based XSS
これは特殊な種類のXSS
脆弱性であり、上記のいくつかの防御方法は適用できないため、特別な対応が必要です。要するに、Web サイトのフロントエンド JavaScript コードが十分に厳密ではなく、信頼できないデータがコードとして実行されるのが実際です。
/関数を使用Vue/React
せずにテクノロジー スタックを使用する場合は、フロントエンド段階で、の隠れた危険性を回避する必要があります。それについては後ほど専門的な弁護の段落が設けられます。v-html
dangerouslySetInnerHTML
render
innerHTML
outerHTML
XSS
Vue
XSS
トリガーとなる箇所は多数ありますが、ページに出力できるのはDOM Based XSS
以下の箇所のみです。JavaScript
HTML
document.write()
;document.writeln()
;xxx.innerHTML()
;xxx.outerHTML()
;xxx.innerHTML.replace()
;document.attachEvent()
;window.attachEvent()
;window.location()
;window.name
;
したがって、開発者は、これらの場所のパラメータをユーザーが制御できるかどうかに焦点を当てる必要があります。これらをプロジェクトで使用する場合は、文字列内で信頼できないデータを結合しないようにしてください。
Vue
でのXSS
守備
これをプロジェクトのVue
フロントエンド開発フレームワークとして使用すると、おめでとうございます。攻撃の問題Vue
のほとんどは解決されますが、攻撃を防ぐためのフレームワークではなく、開発中および使用中に攻撃される脆弱性がまだ残っています。 ;XSS
Vue
XSS
Vue
における防御策
テンプレートまたはレンダリング関数の使用に関係なく、Vue
補間されたコンテンツは、次のテンプレート コードのように自動的にエスケープされます。
<template>
<p>{
{userData}}</p>
</template>
<script>
// 从远程获取的数据
userData = "<script>alert('xss')</script>"
</script>
最終コンパイル後にページに表示されるソース コードの内容はhtml
次のとおりです。
<p>
<script>alert('xss')</script>
</p>
その理由は、Vue
データをエスケープし、スクリプト インジェクションを回避できるようにするためです。このエスケープは textContent などのブラウザネイティブ API を通じて行われるため、ブラウザ自体にセキュリティ ホールがない限り、セキュリティ ホールは発生しません。エスケープされた内容は次のとおりです。
<script>alert("xss")</script>
注射HTML
リモート コンテンツを動的に挿入する場合はHTML
、まずコンテンツが安全で有効であることを確認する必要があります。そうでない場合は、いくつかの危険なタグ シンボルをフィルタリングまたはエスケープするための防御措置を講じる必要があります。たとえば、次のようにレンダリングを表示できますHTML
。
<!-- 当使用模版时 -->
<div v-html="userProvidedHtml"></div>
<!-- 当使用渲染函数时 -->
<script>
h('div', {
domProps: {
innerHTML: this.userProvidedHtml
}
})
</script>
<!-- 当使用JSX 的渲染函数时 -->
<div domPropsInnerHTML={this.userProvidedHtml}></div>
たとえば、単純な方法を使用することもできます (または、より堅牢なライブラリ/プラグインXSSを参照して、リモートuserProvidedHtml
データ コンテンツをフィルタリングしてセキュリティを確保することもできます)。
// 一个简单的函数,通过转义<为<以及>为>来实现防御HTML节点内容
const escape = function(str){
return str.replace(/</g, '<').replace(/>/g, '>')
}
スタイルインジェクション
Vue
テンプレート内でレンダリングを回避するにはタグを使用しますstyle
。
<style>{
{
userProvidedStyles }}</style>
これは、一度渡されてもuserProvidedStyles
、悪意のあるユーザーがCSS
「ログイン」ボタンを覆う透明なボックスとしてリンクをスタイル設定するなど、「クリック詐欺」を提供する可能性があるためです。次に、https://user-XSS-website.com/
それをアプリケーションのログイン ページのように見せます。ユーザーの実際のログイン情報を取得する可能性があるため、Vue では、安全に制御できる对象语法
特定の値を使用し、ユーザーにのみ提供を許可することをお勧めします。property
<!-- sanitizedUrl应为受控的地址 -->
<a
v-bind:href="sanitizedUrl"
v-bind:style="{
color: userProvidedColor,
background: userProvidedBackground
}"
>
click me
</a>
セキュリティ問題に対する「特効薬」はない
セキュリティ問題を解決する過程では、一度解決することは不可能、つまり「特効薬はない」のです。
一般に、人は面倒なことを嫌い、その面倒をできるだけ遠ざけたいと無意識に願っています。そしてセキュリティというのはやっかいなものであり、避けられない悩みでもあります。セキュリティ問題をきっぱり解決したいと思う人は希望的観測にすぎず、「自分を欺く」のは非現実的です。
ベストプラクティス
一般的なルールとして、フィルタされていないユーザー提供のコンテンツの実行を許可している限り (または)、攻撃される立場に身を置くことになる可能性がありますHTML
。これらの提案は、実際には、 を使用する場合でも、別のフレームワークを使用する場合でも、フレームワークを使用しない場合でも当てはまります。JavaScript
CSS
Vue
React