(著者:サイボウズ kintone開発チーム 天野 祐介)
kintoneはJavaScriptを使って自由にカスタマイズすることができます。
カスタマイズにより独自のリッチなUIを構築したり、新しい機能を追加したりできるようになりますが、セキュアなコーディングをしないとクロスサイトスクリプティング脆弱性を作り込んでしまう危険性があります。
この記事では、JavaScriptでセキュアなコーディングをするための基本的な点を解説します。
主な原因
脆弱性を作り込む主な原因になるコードは、要素の動的な生成です。特に、レコード情報などのユーザーが入力した値を使って要素を生成するときに脆弱性が発生しやすくなります。
対策
document.write()
やelement.innerHTML
を使って要素を生成するときは、コンテンツとなる文字列をかならずHTMLエスケープするようにしましょう。
以下は、HTMLエスケープの実装のサンプルです。
使用例は以下になります。
適切なHTMLエスケープをおこなうというのは大原則ですが、それに加えて気をつけるべき点を以下にまとめます。
気をつけるべき点
信頼できない外部サイトからデータを取得しない
JSONPやkintone.proxy()
を利用して外部サイトからデータを取得するときは、データの提供元が信頼できることを確認します。
また、以下のような場合も、かならず提供元を確認します。
- imgタグやscriptタグのsrc属性を設定するとき
- 外部サイトが提供するJavaScriptやCSSを利用するとき
JavaScriptコードを動的に生成しない
eval("...")
や<span onclick="...">
のように、文字列としてJavaScriptコードを記述するのは避けるようにします。可読性が著しく下がり、スコープの破壊や適切なエスケープが難しくなるなどのリスクがあります。
JSONのパースにはJSON.parse()を使う
kintone.api()
などで取得したJSONオブジェクトのパースには、JSON.parse()
を使います。JSONはJavaScriptのオブジェクトとしても評価可能なためeval()
やnew Function()
を使うことも可能ですが、エスケープの不備やXSSの恐れがあるため利用しないようにします。
URLのエンコードにはencodeURIComponent()を使う
aタグのhref属性(リンク先)をセットする場合や、location.href
を書き換える場合は、かならずencodeURIComponent()
でエンコードします。
ユーザーに関係する情報をcookieやlocalStorageに保存しない
意図せずブラウザ上にデータが残り続け、第三者に漏洩するのを防ぐため、ユーザーの個人情報や入力したデータは、クライアントサイドストレージに保存するのは避けます。
たとえば、次のようなデータが該当します。
- ログインID, プロフィール
- レコード情報
- アクセス権
サードパーティライブラリは常に最新版を利用する
ライブラリによっては特定のバージョンに脆弱性があり、読み込んでいるだけで攻撃可能になることがあります。ライブラリのバージョンに起因する脆弱性を防ぐため、常に最新版を利用するようにしましょう。
危険なデータソース
基本的にどんな要素を生成するときもエスケープ処理は必須ですが、以下のデータは特に脆弱性の原因になりやすく、注意が必要なものです。
- レコード情報(ユーザーの入力値)
- 外部から取得したデータ(第三者からのデータ)
- URLパラメータ(ユーザーの入力値)
location.href
やlocation.hash
で取得できるURL情報から特定のパラメータを抽出するといった処理はよくあるものですが、URLにはユーザーが任意の値を入力可能なので、レコード情報などのユーザー入力値と同じように扱う必要があります。
危険な操作
脆弱性を特に引き起こしやすいJavaScriptのコード例を挙げます。これらを使うときは適切なエスケープが必須になります。
また、URL操作時はエンコードに加えて遷移先が信頼できるサイトであることを保証する必要があります。
その他気をつける点
同期XMLHttpRequestはなるべく使わない
通信中にブラウザが固まってしまうパフォーマンスの問題や、Firefoxでは廃止予定になっていることから、同期XMLHttpRequestはなるべく使わないようにします。
サードパーティライブラリ使用時の注意点
jQueryに代表されるDOM操作をおこなうライブラリは、内部で操作しているDOM APIがユーザーから見えないため、知らないうちに前述の危険な操作を呼び出していることがあります。
たとえば、jQueryのhtml()
メソッドは内部的にはinnerHTML
と同じなので、渡された文字列をそのままHTMLとして展開してしまいます。そのため、コンテンツ部分はtext()
を使ってエスケープするなどの対策が必要です。
ライブラリを利用する際も、普段と同じようにエスケープに気を配ることが大事です。
おわりに
JavaScriptでセキュアなコーディングをするために気をつけることを解説しました。安心して利用できるJavaScriptカスタマイズを作成する参考になれば幸いです。
こちらとあわせて、セキュアコーディングガイドラインもご確認ください。
コメント
ログインしてコメントを残してください。