この記事は ServiceNow アドベントカレンダー 2024 の12月17日分の記事として執筆しています。
はじめに
この記事の目的
- ServiceNowの中で、クロスサイトスクリプティング(以下、XSS)対策に利用されている、いくつかのプロパティの意味を備忘も兼ねてまとめます
対象読者
- ServiceNow開発に携わる人
- ServiceNow開発に興味がある人
XSSのざっくりとした説明
前段として、XSSを画像付きでざっくりと説明します。
XSSの被害例として例えば「不特定多数のユーザーが利用する掲示板やブログのコメント欄でのXSSの埋め込み」が挙げられます。
以下のコメント欄は私がcodepen.ioというサイトで適当に作ったものなのですが、ここではHTMLタグのエスケープ処理は全くしていないためHTMLインジェクション
攻撃が可能です。
したがって、このコメント入力欄に第三者が悪意のあるスクリプトを投稿することで、ページ内の過去コメント欄に悪意のあるスクリプトが残り続け、次にこのページを訪問した人に悪意のあるスクリプトを実行させることが可能となります。
▼何もセキュリティ対策がされていない、XSSに対して脆弱性のあるコメント欄
▼第三者が悪意のあるスクリプトをコメント欄に入力した結果、スクリプトが読み込まれる
▼さらに、挿入されたonload
イベントハンドラが起動して別の危険なURLに飛ばされる
上図の例だと、コメント欄でiframe
タグを利用して、悪意のあるスクリプトの実行と危険なURLへの自動遷移の処理をさせられているのがわかります。XSSには種類があり、こうしたタイプのXSSを 格納型XSS(Stored-XSS) と呼びます。他にも色々種類があるので、興味のある方は調べてみてください。
これで、XSSに馴染みのない方もこの記事がどういうトピックなのかが大体わかったかなと思います。
ServiceNowでもあらゆるXSS対策が行われているのですが、システムプロパティ化されXSS対策の強度や対象範囲をユーザー側で定義できるものもあります。
この記事では、そのシステムプロパティの一部をできるだけわかりやすく紹介したいと思います。
本編
この記事は2024年12月(Xanaduバージョン)時点のものです。
# | プロパティ名 | 説明 |
---|---|---|
1 | glide.ui.security.allow_codetag | 埋め込み HTML コードを許可する |
2 | glide.ui.security.codetag.allow_script | 埋め込み HTML で JavaScript タグを許可する |
3 | com.glide.security.check_unsanitized_html | サニタイズされていない HTML の確認 |
4 | glide.ui.escape_html_list_field | リストビューでの HTML をエスケープ |
5 | glide.html.escape_script | JavaScript のエスケープ |
6 | glide.html.sanitize_all_fields | HTML サニタイザー |
1. glide.ui.security.allow_codetag
- デフォルト値:
true
- 推奨値:
false
(デフォルト値と異なります) - 公式ドキュメント:埋め込み HTML コードの許可 (インスタンスセキュリティ強化)
プロパティの説明
このプロパティをtrue
にすると、作業メモや追加コメントで[code]
タグを利用してHTMLを埋め込むことができます。試しに、プロパティ値true
で以下のテストケースを入力してみます。
- ケース1:
[code]
タグなしで<b>
タグを打ち込み - ケース2:
[code]
タグありで<b>
タグを打ち込み - ケース3:
[code]
タグありで<a>
タグを打ち込み - ケース4:
[code]
タグありで<script>
タグを打ち込み
すると、以下のような挙動となります。
一方で、プロパティ値false
に変更すると以下のような挙動となります。
このように、glide.ui.security.allow_codetag
のプロパティ値をtrue
に設定することで [code]タグで囲われたHTMLタグはエスケープされなくなり、b
タグでテキストを太字にしたり、a
タグでリンクを貼り付けたりすることが可能となります。
ただしケース4を見ての通り、 script
タグはXSSに悪用されるリスクが非常に高いため、本プロパティと併せてglide.ui.security.codetag.allow_script
もtrue
に設定しないと利用できません。 (後者のプロパティはtrue
設定できないように制限がかかってるんですけどね。)
他にも、このプロパティによって影響を受けるケースがいくつか存在します。
例えば、問題管理のOOTB$^※$ UIアクション「Communicate Workaround」が一例として挙げられます。
$^※$OOTB(Out-of-the-Box):インスタンス購入時のベースライン機能のこと
▼問題管理フォームの「Workaround」フィールドにHTMLテキストを記載して、関連リンクの「Communicate Workaround」を押下
▼プロパティ値true
の場合での表示(インシデント管理に連携された画面)
▼プロパティ値false
の場合での表示(インシデント管理に連携された画面)
この挙動は、HTMLテキストを作業メモに転記する他のUIアクションにも共通します。
HTMLタグをそのまま表示させることは、利用者のUI/UXを大きく損なう可能性があります。前述の通り、危険性の高いscript
タグは本プロパティをtrue
にするだけではレンダリングされないので、それほどセキュリティを厳密にする必要がない限りはUI/UXを優先して本プロパティをtrue
に設定しておくのがよいかもしれません。
2. glide.ui.security.codetag.allow_script
- デフォルト値:
false
- 推奨値:
false
- 公式ドキュメント:埋め込み HTML で JavaScript タグを許可する
プロパティの説明
このプロパティをtrue
にすると、作業メモや追加コメントで[code]
タグを利用してscript
タグを埋め込むことができます。
とはいえ、Xanaduバージョンのインスタンスでこのプロパティ値をtrue
にしようとしても、以下のようにアラートが表示され変更できないようになっています。また、プロパティレコードの削除もできないようになっています。
▼システムプロパティ定義にて、プロパティ値をtrue
に変更しようとした画面
推奨値もfalse
となっています。
業務で作業メモや追加コメントに<script>
タグを埋め込む必要性は普通ないですし、あくまで「こういうプロパティがあるんだ」とご理解いただくだけでよいかと思われます。
3. com.glide.security.check_unsanitized_html
- デフォルト値:
enforce
- 推奨値:
enforce
- 公式ドキュメント:サニタイズされていない HTML の確認 (インスタンスセキュリティ強化)
プロパティの説明
このプロパティをenforce
にすると、「翻訳されたHTML」タイプのフィールドにおいて、特定のHTMLタグにサニタイズが適用され使用できなくなります。
▼「翻訳されたHTML」タイプのフィールドの一例(「cmdb_ci_service」テーブルの「Service level requirement」フィールド)
こちらもglide.ui.security.codetag.allow_script
同様に、Xanaduバージョンのインスタンスでこのプロパティ値をtrue
にしようとしても、以下のようにアラートが表示され画面から変更できないようになっています。また、プロパティレコードの削除もできないようになっています。
▼システムプロパティ定義にて、プロパティ値をdisable
に変更しようとした画面
公式ドキュメントを読む限り、利用の少ない「翻訳されたHTML」フィールドでのみ適用されるプロパティであり、インスタンスユーザーがプロパティ値を変更することもできないのであまり気にしなくてもよいものと思われます。
よりわかりやすい説明がコミュニティサイトにありましたので、気になった方はご参照ください。
4. glide.ui.escape_html_list_field
- デフォルト値:
true
- 推奨値:
true
- 公式ドキュメント:リストビューでの HTML をエスケープ
プロパティの説明
このプロパティをtrue
にすると、リストビュー画面で強制的にHTMLがエスケープされます。
▼問題のリストビュー画面にて、ワークアラウンド(HTMLフィールド)の内容を表示
なお、こちらも画面から変更・削除できないようになっていました。
▼システムプロパティ定義にて、プロパティ値をfalse
に変更しようとした画面
5. glide.html.escape_script
- デフォルト値:
true
- 推奨値:
true
- 公式ドキュメント:JavaScript のエスケープ
プロパティの説明
このプロパティをtrue
にすると、リストビュー画面でHTMLフィールドの<script>
タグがエスケープされます。
glide.ui.escape_html_list_field
の効果をscript
タグに絞ったものというイメージです。
なお、こちらも画面から変更・削除できないようになっていました。
▼システムプロパティ定義にて、プロパティ値をfalse
に変更しようとした画面
6. glide.html.sanitize_all_fields
- デフォルト値:
true
- 推奨値:
true
- 公式ドキュメント:HTML サニタイザー
プロパティの説明
このプロパティをtrue
にすると、すべてのHTMLフィールドでHTMLタグのサニタイズ評価がされます。サニタイズ評価の基準は、HTMLSanitizerConfig
スクリプトインクルードにて ホワイトリスト と ブラックリスト の形式でユーザー側で定義することが可能です。当該スクリプトインクルードにて、ホワイトリストはHTML_WHITELIST
クラス、ブラックリストはHTML_BLACKLIST
クラスで定義します。
▼HTMLSanitizerConfig
スクリプトインクルード画面
具体例を見てみましょう。
まずはOOTBの設定で問題管理の「Workaround」(HTMLフィールド)にiframe
タグを埋め込んでみます。
▼OOTBの設定でHTMLフィールドにiframe
タグを埋め込んでみる(保存前)
どうやらServiceNowのHTML Sanitizeスクリプトインクルードはレコードの保存・更新時に実行されているらしく(ソース)、保存前はiframe
で外部のページが参照できるようなのですが、保存後は以下の通りsrc
属性がサニタイズされ、iframe
の枠だけ残っている状態となります。
▼OOTBの設定でHTMLフィールドにiframe
タグを埋め込んでみる(保存後)
次に、iframe
をタグをブラックリストに入れるとどうなるのか 検証をしましょう。
下図のようにHTML Sanitize スクリプトインクルードのブラックリスト設定を変更します。
▼HTMLSanitizerConfig
スクリプトインクルード画面
そうすると、iframe
タグを打ち込んで保存した時の挙動が先ほどとは異なり、src
属性だけではなくiframe
タグが丸ごとサニタイズされます。
▼iframe
タグをブラックリストに登録した上でHTMLフィールドに埋め込んでみる(保存後)
以上の検証で、確かに本プロパティおよびHTMLSanitizerConfig
スクリプトインクルードが期待通りに動くことが確認できました。strong
タグなどの無害なタグはブラックリストに入れてもそのまま利用できたり、src
属性はブラックリストに入れてなくてもサニタイズされたりと気になる点はあるのですが、それらは別で管理するプロパティがあるか、内部でよしなに設定されているのでしょう。これ以上の深掘りは一旦やめておきます。(奥が深すぎて時間がいくらあっても足らない)
なお、サニタイズの履歴はhttps://[インスタンス名].service-now.com/syslog_list.do?sysparm_query=source%3DHTMLSanitizer
にレコードとして残っておりいつでも内容を確認できます。
変更・削除についてはこちらも画面からはできないようになっていました。
▼システムプロパティ定義にて、プロパティ値をfalse
に変更しようとした画面
完全に余談ですが、個別のHTMLフィールドにサニタイズする/しないを設定したい場合、本プロパティをfalse
に設定した上で、サニタイズしたい特定のフィールドにのみhtml_sanitize
属性をtrue
に設定する必要があります。公式ドキュメント
おわりに
ServiceNowアドベントカレンダー大会は初参加なので、もし分かりにくいところあれば申し訳ありません。SNUGユーザー会にてオンサイトでお会いした方々はありがとうございました^-^
もし間違い等あれば、ぜひコメントで教えてください。
参考文献(公式Docsやコミュニティサイト以外)
・XSS(クロスサイトスクリプティング)とは?攻撃手法と5つの対策を紹介
・XSSと、XSSの種類について