この記事は 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の種類について



