Open4

Securityの勉強

nabetsunabetsu

Cross-Site Scripting(XSS)

ブラウザを標的にした(ブラウザ上で悪意のあるコードを実行する)攻撃手法。

主に以下の3つに分類される。

Stored XSS

一般的なWebアプリケーションではデータベースに保存されたデータを取得し、その結果を含めて最終的なHTMLを作成する。(例えばソーシャルメディアサイトではユーザからの投稿がデータベースに保存され、その内容をデータベースから取得した結果がブラウザに表示される)

攻撃者はこの仕組みを利用してデータベースにJavaScriptコードを保存させ、ブラウザ上でそのコードを実行することで攻撃を行う。

具体例

ユーザが自由に投稿できるWebサイトがあったとして、以下のコメントを投稿すると、その内容がデータベースに保存される。

<script>alert('Stored Cross-Site Scripting')</script>

保存された内容は別のユーザがWebサイトにアクセスした時にデータベースから取得され、ブラウザ上で実行される。(アラートがブラウザ上に表示される)

ユーザ側の被害は軽微だが、攻撃者はこうした攻撃でXSSが可能か調べ、よりセッション情報を盗んだり、有害なサイトにリダイレクトさせたり、より危険な攻撃に出る

対応策

1. HTML Characterのエスケープ

データベースから取得した値を使う動的コンテンツにエスケープ処理を行う

Character Entiti Encoding
" &quot;
& &amp;
' &apos;
< &lt;
> &gt;

Content Security Policyの設定

モダンブラウザではContent Security Policyの設定が可能になっており、適切な設定を行うことで悪意のあるJavaScriptコードの実行を防げる。

Content Security PolicyがHTTPレスポンスヘッダーに設定されている場合、ブラウザ上でインラインJavaScriptの実行が行われず、src attributeでimportされたものだけが実行を許可されるようになる。

  • 例えば以下の設定をすれば、Webサイトと同じドメイン(self)かapis.google.comドメインからのimportのみが許可され、インラインJavaScriptの実行は許可されない

Content-Security-Policy: script-src 'self' https://apis.google.com

Reflected XSS

Dom-Based XSS

参考資料

ReactにおけるXSS

Reactでは仮想DOMから実際にブラウザに表示されるDOMをレンダリングする際に不適切な文字列についてはエスケープがされる。
そのため、基本的にはフレームワーク側で前述のエスケープを実施してくれるが、いくつかのケースではエスケープ処理が行われない。

  • dangerouslySetInnerHTML
  • javascript:スキーム
  • SSRを使用しているケース

参考資料

ホスティングサービスにおけるXSS対策

Netlify, Amplify等のホスティングサービスを利用する際の対策について、基本的にどのサービスもカスタムヘッダーの設定が可能であり、利用者側で適切な設定をすることでセキュリティ対策が実施できるようになっている。

Netlify

# a path:
/templates/index.html
  # headers for that path:
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
# another path:
/templates/index2.html
  # headers for that path:
  X-Frame-Options: SAMEORIGIN

Amplify

customHeaders:
  - pattern: '**/*'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: 'default-src self'

Custom headers

nabetsunabetsu

Incomplete or No Cache-control and Pragmra HTTP Header Set

OWASP

Web Content Caching

  • セッションがクローズされた後でも、ブラウザのキャッシュを利用してセッション情報からセンシティブなデータにアクセスすることができる
  • そのため、webサーバはキャッシュの利用に関して制約を課さないといけない
    • Cache-ControlPragma HTTP headers
    • ページ自体にMETA tagをつける

キャッシュを使っている場合には、Session IDがキャッシュされないようにCache-Control: no-cache="Set-Cookie, Set-Cookie2をつける。

MDNによるとSet-Cookie2は廃止されている。

オリジンで Cookie を受信するが、CloudFront がオリジンのレスポンスで Set-Cookie ヘッダーをキャッシュしないようにする場合、フィールド名として Set-Cookie を指定する no-cache ディレクティブを含む Cache-Control ヘッダーを追加するようにオリジンを設定します。例: Cache-Control: no-cache="Set-Cookie"。詳細については、「Hypertext Transfer Protocol (HTTP/1.1): Caching」標準の「Response Cache-Control Directives」を参照してください。 https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Cookies.html

Pragma

Webサーバとブラウザの通信経路上に存在するプロキシサーバやキャッシュサーバをすべてWebサーバ側で把握することは困難である。場合によっては、古い設備が存在し、HTTP/1.1 の Cache-Control ヘッダを解さないプロキシが存在するかもしれない。

このような心配のある場合は次のヘッダをHTTPレスポンスに含めると、相手のプロキシが対応してくれる場合もある。
IPA - プロキシキャッシュ対策

Pragma: no-cache

Cache-Controlで許容される値

  • Cache-Control: private
  • Cache-Control: no-store
  • Cache-Control: no-cache
    • このヘッダの意味は、いちどキャッシュに記録されたコンテンツは、現在でも有効か否かを本来のWebサーバに問い合わせて確認がとれない限り再利用してはならない、という意味である。 IPA - プロキシキャッシュ対策

  • Cache-Control: must-revalidate

参考資料

ブラウザのキャッシュコントロールを正しく理解する

キャッシュについて整理

nabetsunabetsu

X-Content-Type-Options Header Missing

この属性を付与するとファイルの内容をContent-Type属性から判断してねとお願いできる。
ファイルダウンロード時にファイル形式をブラウザに誤認させてJavascriptを実行させてしまうような攻撃(XSS攻撃)を防ぐことができる。
Content-TypeとX-Content-Type-Options: nosniff

Strict-Transport-Security Header Not Set

HTTPで接続した際に、強制的にHTTPSへリダイレクトし、以降のそのドメインへの接続はすべてHTTPSとする機能がHSTS (HTTP Strict Transport Security) である。RFC6797で標準化されている。
HSTS (HTTP Strict Transport Security) の導入

Cross-Domain Misconfiguration

nabetsunabetsu

セキュアコーディング

eslint-plugin-security

detect-object-injection

  • Bracket Object Notationでユーザからのインプットの値にアクセスすると、対象のオブジェクトの全てのプロパティへのアクセスが可能になってしまう
  • Bracket Object Notationでユーザからのインプットの値にアクセスすると、対象のオブジェクトのプロパティだけでなく、プロトタイプにもアクセスが可能になる

The Dangers of Square Bracket Notation

eslint-plugin-secuirity - The Dangers of Square Bracket Notation

The most direct fix here is going to be to avoid the use of user input in property name fields. This isn't reasonable in all circumstances, however, and there should be a way to safely use core language features.

Another option is to create a whitelist of allowed property names, and filter each user input through a helper function to check before allowing it to be used. This is a great option in situations where you know specifically what property names to allow.
In cases where you don't have a strictly defined data model ( which isn't ideal, but there are cases where it has to be so ) then using the same method as above, but with a blacklist of disallowed properties instead is a valid choice.

const obj = { 
    eventName: 'Music event', 
    landingPic: 'landing.jpg',
    eventPic0: 'pic0.jpg',
    eventPic1: 'pic1.jpg',
    eventPic2: 'pic2.jpg',
    eventPic3: 'pic3.jpg',
    artist: 'Elie'
};

// array of keys which need to  be read
const arrayOfKey = ['landingPic', 'eventPic0', 'eventPic1',  'eventPic2',  'eventPic3'];

// let's read the value by a key in array
arrayOfKey.forEach( key => {
    const value = obj[`${key}`];
    console.log(value);
});

How to resolve eslint “Generic Object Injection Sink” error?より転載

If you are using the --harmony flag or io.js, you also have the option of using ECMAScript 6 direct proxies, which can stand in front of your real object ( private API ) and expose a limited subset of the object ( public API ). This is probably the best approach if you are using this pattern, as it is most consistent with typical object oriented programming paradigms.

Generic Object Injection Sink

Why is it bad pratice calling an array index with a variable?

how to fix codacy alert “Generic Object Injection Sink”

How to resolve eslint “Generic Object Injection Sink” error?