カプセル化とは、強い境界線を引くことです。Web ブラウザの場合は、自分のモバイル コードが他のモバイル コードに悪用されないようにすることを意味します。サーバー上では、検証されたデータと検証されていないデータ、あるユーザーのデータと別のユーザーのデータ、またはユーザーが見ることを許可されたデータと許可されていないデータの区別などを意味する場合があります。
X-Frame-Options
ヘッダーを介してフレーミング ポリシーを指定できない場合。X-Frame-Options
ヘッダーを介してフレーミング ポリシーを指定できない場合。localStorage
と sessionStorage
間で値を転送すると、意図せずに重要な情報が公開される可能性があります。localStorage
および sessionStorage
マップを提供して、開発者がプログラムの値を保持できるようにしています。sessionStorage
マップは、ページを起動するためのストレージを提供し、該当するページ インスタンスおよび直近のブラウザ セッションの期間だけ持続します。しかし、localStorage
マップは、複数のページ インスタンスおよび複数のブラウザ インスタンスにわたってアクセス可能なストレージを提供します。この機能により、アプリケーションは、複数のブラウザタブやウィンドウで同じ情報を保持して利用できるようになります。sessionStorage
スコープと localStorage
間で移動しないように注意するよう必要があります。sessionStorage
オブジェクトに保存されます。しかし、開発者は、localStorage
オブジェクト内にも情報を保存します。
...
try {
sessionStorage.setItem("userCCV", currentCCV);
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert('Quota exceeded.');
}
}
...
...
var retrieveObject = sessionStorage.getItem("userCCV");
try {
localStorage.setItem("userCCV",retrieveObject);
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert('Quota exceeded.');
}
...
var userCCV = localStorage.getItem("userCCV");
...
}
...
localStorage
オブジェクトに情報を戻すことで、CCV 情報は他のブラウザ タブでも利用できるようになります。また、ブラウザを新たに呼び出した場合でも利用できるようになります。これは、アプリケーション論理の本来のワークフローを回避しています。MyAccountActions
とページ アクション メソッド pageAction()
を宣言しています。ページの URL にアクセスすると、pageAction()
メソッドが実行され、サーバーは CSRF 防止トークンをチェックしません。
<apex:page controller="MyAccountActions" action="{!pageAction}">
...
</apex:page>
public class MyAccountActions {
...
public void pageAction() {
Map<String,String> reqParams = ApexPages.currentPage().getParameters();
if (params.containsKey('id')) {
Id id = reqParams.get('id');
Account acct = [SELECT Id,Name FROM Account WHERE Id = :id];
delete acct;
}
}
...
}
<img src="http://my-org.my.salesforce.com/apex/mypage?id=YellowSubmarine" height=1 width=1/>
RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, "/new_user");
body = addToPost(body, new_username);
body = addToPost(body, new_passwd);
rb.sendRequest(body, new NewAccountCallback(callback));
RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, "http://www.example.com/new_user");
body = addToPost(body, "attacker";
body = addToPost(body, "haha");
rb.sendRequest(body, new NewAccountCallback(callback));
example.com
の管理者が、サイトでセッションを行っているときに、悪意あるページにアクセスすると、攻撃者にアカウントを作成してしまいますが、本人はそのことに気づきません。これが CSRF 攻撃です。アプリケーションには、リクエストの生成元を検証する方法がないために、この攻撃が可能となっています。リクエストはユーザーによって選択された正当なアクションにも、攻撃者が準備した不正なアクションにもなりえます。攻撃者は偽のリクエストを生成する Web ページを見ることができません。そのため、この攻撃方法は、アプリケーションの状態を変更するリクエストにのみ有効です。
<http auto-config="true">
...
<csrf disabled="true"/>
</http>
var req = new XMLHttpRequest();
req.open("POST", "/new_user", true);
body = addToPost(body, new_username);
body = addToPost(body, new_passwd);
req.send(body);
var req = new XMLHttpRequest();
req.open("POST", "http://www.example.com/new_user", true);
body = addToPost(body, "attacker");
body = addToPost(body, "haha");
req.send(body);
example.com
の管理者が、サイトでセッションを行っているときに、悪意あるページにアクセスすると、攻撃者にアカウントを作成してしまいますが、本人はそのことに気づきません。これが CSRF 攻撃です。アプリケーションには、リクエストの生成元を検証する方法がないために、この攻撃が可能となっています。リクエストはユーザによって選択された正当なアクションにも、攻撃者が準備した不正なアクションにもなりえます。攻撃者は偽のリクエストを生成する Web ページを見ることができません。そのため、この攻撃方法は、アプリケーションの状態を変更するリクエストにのみ有効です。
<form method="POST" action="/new_user" >
Name of new user: <input type="text" name="username">
Password for new user: <input type="password" name="user_passwd">
<input type="submit" name="action" value="Create User">
</form>
<form method="POST" action="http://www.example.com/new_user">
<input type="hidden" name="username" value="hacker">
<input type="hidden" name="user_passwd" value="hacked">
</form>
<script>
document.usr_form.submit();
</script>
example.com
の管理者が、サイトでセッションを行っているときに、悪意あるページにアクセスすると、攻撃者にアカウントを作成してしまいますが、本人はそのことに気づきません。これが CSRF 攻撃です。アプリケーションには、リクエストの生成元を検証する方法がないために、この攻撃が可能となっています。リクエストはユーザによって選択された正当なアクションにも、攻撃者が準備した不正なアクションにもなりえます。攻撃者は偽のリクエストを生成する Web ページを見ることができません。そのため、この攻撃方法は、アプリケーションの状態を変更するリクエストにのみ有効です。buyItem
コントローラー メソッドの CSRF 保護を無効にします。
+ nocsrf
POST /buyItem controllers.ShopController.buyItem
shop.com
のアクティブ セッション実行時に、ユーザーは意図せずに悪意あるページに誘導され、気づかないうちに攻撃者にアイテムを購入してしまいます。 これが CSRF 攻撃です。 アプリケーションには、リクエストの生成元を検証する方法がないために、この攻撃が可能となっています。 リクエストはユーザーによって選択された正当なアクションにも、攻撃者が準備した不正なアクションにもなりえます。 攻撃者は偽のリクエストを生成する Web ページを見ることができません。そのため、この攻撃方法は、アプリケーションの状態を変更するリクエストにのみ有効です。
<form method="POST" action="/new_user" >
Name of new user: <input type="text" name="username">
Password for new user: <input type="password" name="user_passwd">
<input type="submit" name="action" value="Create User">
</form>
<form method="POST" action="http://www.example.com/new_user">
<input type="hidden" name="username" value="hacker">
<input type="hidden" name="user_passwd" value="hacked">
</form>
<script>
document.usr_form.submit();
</script>
example.com
の管理者が、サイトでセッションを行っているときに、悪意あるページにアクセスすると、攻撃者にアカウントを作成してしまいますが、本人はそのことに気づきません。これが CSRF 攻撃です。アプリケーションには、リクエストの生成元を検証する方法がないために、この攻撃が可能となっています。リクエストはユーザによって選択された正当なアクションにも、攻撃者が準備した不正なアクションにもなりえます。攻撃者は偽のリクエストを生成する Web ページを見ることができません。そのため、この攻撃方法は、アプリケーションの状態を変更するリクエストにのみ有効です。noopen
に設定されている X-Download-Options
ヘッダーを無効化し、ダウンロードされた HTML ページがそれらを提供するサイトのセキュリティ コンテキストで実行されるのを許可します。
var express = require('express');
var app = express();
var helmet = require('helmet');
app.use(helmet({
ieNoOpen: false
}));
...
Origin
ヘッダーの検証に失敗した場合、サーバーは、悪意あるサイトがユーザーに気づかれずにユーザーを偽装し、双方向 WebSocket 接続を確立することを許可します。Origin
ヘッダーの検証に失敗した場合、サーバーは、悪意あるサイトがユーザーに気づかれずにユーザーを偽装し、双方向 WebSocket 接続を確立することを許可します。exclude
拒否リストを使用します。これでは保守管理が難しく、間違いが発生しやすくなります。開発者がフォームまたはフォームをバックアップする Model
に新しいフィールドを追加するとき、exclude
フィルターの更新を忘れると、機密フィールドを攻撃者にさらすことになります。攻撃者は悪意のあるデータを送信し、除外されていないフィールドにバインドできます。User
属性を開示しますが、ユーザー id
について拒否リストをチェックします。
from myapp.models import User
...
class UserForm(ModelForm):
class Meta:
model = User
exclude = ['id']
...
User
モデルが新しい role
属性で更新され、関連付けられている UserForm
が更新されない場合、role
属性はフォームに表示されます。
...
myWebView.loadUrl("file:///android_asset/www/index.html");
...
Example 1
の Android WebView レンダラーは、「file://」で開始する URL を使用する loadUrl()
でロードされたものはすべて同じ発生元として扱います。
<script src="http://www.example.com/js/fancyWidget.js"></script>
Example 2
では、セキュアではないプロトコルが使用されているため、悪意のある行為者による決定したスクリプトの改ざんが許可される可能性があります。または、他の攻撃が実行されてマシンが攻撃者のサイトに誘導される可能性があります。file://
)。UIWebView.loadRequest(_:)
メソッドを使用してローカル ファイルをロードしています。
...
NSURL *url = [[NSBundle mainBundle] URLForResource: filename withExtension:extension];
[webView loadRequest:[[NSURLRequest alloc] initWithURL:url]];
...
Example 1
の WebView エンジンは、file://
で開始する URL を使用する UIWebView.loadRequest(_:)
でロードされたものはすべて、権限のあるローカル ファイルで発生したとして扱います。file://
URL によってローカルにロードされると、同一生成元ポリシーによって、このファイル内のスクリプトは同じ生成元から生成された他のファイルにアクセスできるようになるため、攻撃者は機密情報を含むすべてのローカル ファイルにアクセスできるようになる可能性があります。file://
)。UIWebView.loadRequest(_:)
メソッドを使用してローカル ファイルをロードしています。
...
let url = Bundle.main.url(forResource: filename, withExtension: extension)
self.webView!.load(URLRequest(url:url!))
...
Example 1
の WebView エンジンは、file://
で開始する URL を使用する UIWebView.loadRequest(_:)
でロードされたものはすべて、権限のあるローカル ファイルで発生したとして扱います。file://
URL によってローカルにロードされると、同一生成元ポリシーによって、このファイル内のスクリプトは同じ生成元から生成された他のファイルにアクセスできるようになるため、攻撃者は機密情報を含むすべてのローカル ファイルにアクセスできるようになる可能性があります。crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。しかし、この設定を変更する場合には、注意が必要です。クロスドメインポリシーが過度に許容的であると、悪意のあるアプリケーションが不正な方法で攻撃対象のアプリケーションとやりとりし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
flash.system.Security.allowDomain("*");
*
を allowDomain()
への引数として使用すると、アプリケーションのデータが、任意のドメインにある他の SWF アプリケーションにアクセスできることになります。crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。Flash Player 9,0,124,0 以降、Adobe は Flash Player がドメイン間で送信できるカスタム ヘッダーを定義する機能も導入しました。ただし、これらの設定を定義するときには注意が必要です。過度に許容的なカスタム ヘッダー ポリシーを、過度に許容的なクロスドメイン ポリシーと一緒に適用すると、悪意のあるアプリケーションが任意のヘッダーをターゲット アプリケーションに送信できるようになります。その結果、さまざまな攻撃の対象となったり、受信したヘッダーの処理方法がわからない、アプリケーションの実行エラーが発生したりする可能性があります。
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
*
を headers
属性の値として使用すると、任意のヘッダーがドメイン間で送信できてしまいます。crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。しかし、この設定に影響を与えるユーザーを決定する場合には、注意が必要です。クロスドメインポリシーが過度に許容的であると、悪意のあるアプリケーションが不正な方法で攻撃対象のアプリケーションとやりとりし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。ポリシー制約の回避の脆弱性は次のように発生します。例 2: 次のコードは、ロードされた SWF ファイルへのパラメーターの 1 つの値を使用して、信頼されるドメインのリストを定義しています。
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var url:String = String(params["url"]);
flash.system.Security.loadPolicyFile(url);
...
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var domain:String = String(params["domain"]);
flash.system.Security.allowDomain(domain);
...
crossdomain.xml
設定ファイルの該当する設定によりこの制約を変更することを開発者に許可しています。しかし、HTTP を介してロードされたアプリケーションは、中間者攻撃を受ける可能性があり、信頼するべきではないため、これらの設定を定義するときには、注意が必要です。allowInsecureDomain()
をコールしています。これは、HTTP でロードされた SWF アプリケーションが HTTPS でロードされた SWF アプリケーションのデータにアクセスすることを禁止する制約を解除するものです。
flash.system.Security.allowInsecureDomain("*");
app.use('/graphql', graphqlHTTP({
schema
}));
app.add_url_rule('/graphql', view_func=GraphQLView.as_view(
'graphql',
schema = schema,
graphiql = True
))
services
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>();
app.use('/graphql', graphqlHTTP({
schema
}));
app.add_url_rule('/graphql', view_func=GraphQLView.as_view(
'graphql',
schema = schema
))
script
タグを考えてみます。
<script src="http://www.example.com/js/fancyWidget.js"></script>
www.example.com
以外の Web サイトでこのタグが表示される場合、このサイトは www.example.com
に依存し、正しい悪意のないコードが提供されます。攻撃者が www.example.com
を乗っ取っている場合、fancyWidget.js
の内容を改変して、サイトのセキュリティが侵害される場合があります。たとえば、fancyWidget.js
にユーザーの機密情報を盗むコードが追加される可能性があります。
HtmlInputHidden hidden = new HtmlInputHidden();
Hidden hidden = new Hidden(element);
hidden
タイプの <input>
タグは、非表示フィールドが使用されていることを示します。
<input type="hidden">
...
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
...
'mydb'
と推測できればだれでもアクセスできます。script-src
、img-src
、object-src
、style_src
、font-src
、media-src
、frame-src
、connect-src
はリソース アクセスを制御します。*
を使用し、全部または一部のソースを指示できます。いずれのディレクティブも必須ではありません。ブラウザは一覧にないディレクティブにすべてのソースを許可するか、任意の default-src
ディレクティブからその値を導出します。また、このヘッダーの仕様は時間の経過とともに発展しています。Firefox の場合はバージョン 23 まで、IE の場合はバージョン 10 まで X-Content-Security-Policy
として実装されていました。Chrome の場合はバージョン 25 まで X-Webkit-CSP
として実装されていました。いずれの名前も廃止となり、新しい標準名の Content Security Policy
に取って代わられました。ディレクティブの数、2 つの廃止となった代替名、1 つのヘッダーで複数回発生する同じヘッダーと繰り返しディレクティブの処理方法が指示される場合、開発者がこのヘッダーを間違って構成する可能性が高くなります。unsafe-inline
または unsafe-eval
のディレクティブは CSP の目的を無効にします。script-src
ディレクティブは設定されていますが、スクリプト nonce
は設定されていません。frame-src
は設定されていますが、sandbox
は設定されていません。django-csp
設定では、安全でないディレクティブ、unsafe-inline
と unsafe-eval
が使用され、インライン スクリプトとコード評価が許可されます。
...
MIDDLEWARE = (
...
'csp.middleware.CSPMiddleware',
...
)
...
CSP_DEFAULT_SRC = ("'self'", "'unsafe-inline'", "'unsafe-eval'", 'cdn.example.net')
...
X-Frame-Options
ヘッダーが含まれます。このヘッダーが無効化されているか設定されていないと、クロスフレーム関連の脆弱性につながります。X-Frame-Options
ヘッダーを無効化するよう設定します。
<http auto-config="true">
...
<headers>
...
<frame-options disabled="true"/>
</headers>
</http>