見出し画像

Reactアプリをセキュアにする最良の方法

こんにちは。devsecopsのデベロッパ向けの記事として
javaのフレームワークとして人気のReactを取り上げました。日本ではまだまだReactができるプログラマは少ないようです。

DevSecOpsに関連するSnykのブログ記事からの紹介です。ブログ記事は、デベロッパの方の個性が文章にみられ、なかなか面白いです。

今回は、Ron Perris(ロン・ペリス)氏の2020年10月28日のReactアプリをセキュアにする最良の方法についてのブログ記事をご紹介します。Reactコードのセキュリティ関連のエラーを自動的にテストし、自動的に修正する方法についての記事をご紹介します。

React におけるセキュリティのベストプラクティス 10項目
1.データバインディングによるデフォルトのXSS保護
波括弧{}を使用したデフォルトのデータバインディングの使用で、ReactはXSS攻撃から保護するために値を自動的にエスケープします。この保護はtextContentレンダリング時にのみ実行され、HTML属性のレンダリング時には実行されないことに注意してください。
JSXデータバインディング構文{}を使用して、エレメントにデータを配置します。

推奨:
<div>{data}</div>
カスタムバリデーションなしの動的属性値を回避します。

危険:
<form action={data}>...

2.危険なURL
URLには、javascript:プロトコルURLを介して動的なスクリプトコンテンツを含めることができます。バリデーションによりリンクがhttp:またはhttps:であることを確認し、javascript:のURLベースのスクリプトインジェクションを回避してください。ネイティブのURLパーシング機能を使用してURLバリデーションを実行し、パースされたプロトコルプロパティが許可リストに一致していることを確認してください。

推奨:
function validateURL(url) {
const parsed = new URL(url)
return ['https:', 'http:'].includes(parsed.protocol)
}
<a href={validateURL(url) ? url : ''}>Click here!</a>

危険:
<a href={attackerControlled}>Click here!</a>

3.HTMLのレンダリング
dangerouslySetInnerHTMLを使用してレンダリングされたDOMノードにHTMLを直接挿入することができます。この方法で挿入されたコンテンツは、事前にサニタイズする必要があります。
値をdangerouslySetInnerHTMLのpropに配置するまえに、dompurifyのようなサニタイズライブラリを使用してください。
HTMLをDOMに挿入するときにdompurifyを使用します。

import purify from "dompurify";
<div dangerouslySetInnerHTML={{ __html:purify.sanitize(data) }} />

4.ダイレクトDOMアクセス
DOMにアクセスしてコンテンツをDOMノードに直接挿入することは避けてください。HTMLをインジェクトする必要がある場合にはdangerouslySetInnerHTMLを使用し、dompurifyを使いインジェクトをする前にサニタイズしてください。

推奨:
import purify from "dompurify";
<div dangerouslySetInnerHTML={{__html:purify.sanitize(data) }} />

refやfindDomNode()を使ってレンダリングされたDOMエレメントにアクセスし、innerHTMLおよび同様のプロパティまたはメソッドを介してコンテンツを直接インジェクトすることは避けてください。

危険:
this.myRef.current.innerHTML = attackerControlledValue;

5.サーバーサイド レンダリング
ReactDOMServer.renderToString()やReactDOMServer.renderToStaticMarkup()のようなサーバーサイド レンダリング関数を使用するときに、データバインディングによりコンテンツが自動的にエスケープされます。
ハイドレーションのためにストリングをクライアントに送信する前に、renderToStaticMarkup()のアウトプットにストリングを連結することは避けてください。
XSSを回避するために、サニタイズされていないデータをrenderToStaticMarkup()のアウトプットと連結させることは避けてください:

app.get("/", function (req, res) {
return res.send(
ReactDOMServer.renderToStaticMarkup(
React.createElement("h1", null, "Hello World!")
) + otherData
);
});

6.依存関係における脆弱性の検出
サードパーティコンポーネントのいくつかのバージョンには、セキュリティの問題が含まれている場合があります。依存関係を確認し、より信頼性の高いバージョンが利用可能になった時に、すぐに更新してください。

脆弱性を確認するためにSnykCLI などのツールを利用してください。

ソースコード管理システムと統合して自動修正を受け取ることにより、自動的にSnykの脆弱性を修正できます:
$ npx snyk test

7.JSON ステートのインジェクション
サーバー側でレンダリングされたReactページと一緒にJSONデータを送信するのが一般的です。インジェクション攻撃を回避するために、常に無害な値で、<などの文字をエスケープしてください。

JSONに含まれるHTMLの重要な値については無害な文字を使用して、エスケープしてください:

window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace( /</g, '\\u003c')}

8.脆弱な Reactの バージョンの検出
Reactライブラリには過去にいくつかの重大度の高い脆弱性があったため、常にバージョンを最新に保つことをお勧めします。
reactとreact-domの脆弱なバージョンを避けるため、npm outdated を使用して最新バージョンであることを確認してください。

9.セキュリティ Linter の設定
コード内のセキュリティ問題を自動的に検出し、修復のアドバイスを提供するLinterコンフィグレーションとプラグインをインストールします。
ESLint Reactセキュリティコンフィグを使用して、コードベースのセキュリティ問題を検出します。
huskyなどのライブラリを使用してセキュリティ関連のLinterの問題が検出されたときにエラーを起こすpre-commitフックを設定します。
使用しているバージョンに脆弱性が存在する場合、Snykを使用して新しいバージョンに自動的に更新しましょう。

10.危険なライブラリーコードの回避
HTMLをDOMに直接挿入するなどの危険な操作を実行するようなライブラリコードが使用されることがあります。ライブラリコードを手動またはLinterでレビューすることにより、Reactのセキュリティメカニズムの危険な使用法を検出します。
dangerouslySetInnerHTML、innerHTML、未検証のURLまたはその他の危険なパターンを使用しているライブラリーを避けましょう。node_modulesフォルダでSecurity Linterを使用して、ライブラリコード内の危険なパターンを検出します。

長い翻訳記事を、最後まで読んでいただいてありがとうございます!
reference:
10 React security best practices | Snyk
https://snyk.io


Contents provided by:
Jesse Casman, Fumiko Doi, Content Strategists for Snyk, Japan, and Randell Degges, Community Manager for Snyk Global

前回の記事はこちらです:


この記事が気に入ったらサポートをしてみませんか?