サイト内の現在位置

PortSwigger Web Security Academy: Business Logic Lab – Write-up

NECセキュリティブログ

2020年11月20日

NECサイバーセキュリティ戦略本部セキュリティ技術センターの中島です。
本記事では、Webセキュリティのオンライントレーニングサイトである “PortSwigger Web Security Academy” new window[1] のBusiness Logicの脆弱性に関するLabから1問、Write-upを紹介します。

Web Security Academyとは

“Web Security Academy”はPortSwigger社が公開しているオンラインのWeb Security トレーニングサイトです。脆弱性に関する説明や教科書的位置づけの「Learning Material」と、脆弱性を含んだ演習環境である「Lab」が用意されており、すべて無料で学ぶことができます。また、Labを通して、PortSwigger社が提供しているローカルプロキシツールであるBurpSuitenew window[2]の使い方も実践的に学ぶことができます。

2020年11月9日現在では、20のトピックと191のラボが提供されています。
新しいコンテンツが公開された際には、公式のTwitter(@WebSecAcademy)new window[3]で紹介されるのでフォローしておくと良いかと思います。

Business Logic の脆弱性

Labの解説の前に、Business Logic の脆弱性について少し触れておきます。
Business Logic の脆弱性とは、アプリケーションの設計と実装における欠陥のことです。Business Logicの不備を突いて意図したワークフローをバイパスされたり、ユーザから渡されるパラメータに任意の値や本来無効にされるべき値が挿入され、不正な操作を引き起こされる可能性があります。

例えば、オンラインで1つ1000円のおかしを購入するWebアプリを構築する、ということを考えます。
想定しているフローに則って購入する場合、カートに入るお菓子の数は1以上の整数が渡されるはずです。
しかし、システム上でのデータの検証に不備があり、負の数も受け入れるように設計されている場合、攻撃者は-1個を指定することができ、-1000円の支払い、つまり、1000円とお菓子を手に入れることができる可能性があります。
このように、ユーザがワークフロー通りに操作を行うだろう、といった想定に基づいてアプリケーションを設計することは避けなくてはなりません。

Authentication bypass via encryption oracle

本記事では、今年の9月に新たに公開されたトピックである「Business Logic Vulnerabilities」より 「Authentication bypass via encryption oracle」new window[4]というLabを紹介いたします。公式からも簡単な解法が提供されていますが、観点や手順を少し掘り下げて解説していきます。
また、本トピックには11のLabがあります。
上から順番に解いていくと後半もスムーズに解きやすいですが、それぞれ独立したLabとなっているので今回ご紹介するLabからでも好きなLabから解いても問題ありません。

本Labは、管理パネルにアクセスしてCarlosというユーザのアカウントを削除することでクリアとなります。
まず、Labへのアクセスボタンを押すと、LabのURLとあらかじめ登録してあるWienerというユーザのアカウント情報が提供されます。なお、Labは15分間でリセットされるので、問題に取り組むうえで誤ってWienerアカウントを削除してしまった場合、15分待ってから再度lab環境を立ち上げ直してください。(URLも変わるのでBurpSuiteのscopeを設定した場合、併せて変更するようご注意ください。)

まず、与えられたURLにアクセスすると、ブログの投稿記事を見て、コメントをする機能が存在するWebアプリケーションであることがわかりました。

トップページではblogの概要を確認できます
ブログの詳細画面下部でコメント投稿機能を確認できます

早速、Wienerアカウントを用いてログインページからログインを行います。
ログインページにアクセスすると、Stay in login というオプションがあることがわかります。このオプションをチェックしてログインすると、stay-logged-in というCookieが付与されます。

/login ページ

次に、管理パネルを見つけるためにディレクトリスキャンをかけたところ、/adminというページを見つけました。/admin にアクセスすると、以下のように admin権限が必要であると示されます。

/admin ページにアクセスすると、admin権限を求められる

ここで、administratorのstay in login 状態を詐称して、/admin ページにアクセスすることができればCarlosというユーザを削除することができると考え、administrator の stay-logged-in のCookieを特定するという方針を立てます。

まずは、stay in login オプションを有効にした状態でwienerとしてログインし、ブログにコメントを投稿しながら、リクエストとレスポンスを見比べます。

すると、無効なメールアドレスの形式を使用してコメントを送信した場合には、notificationというCookieが付与されてからブログの記事ページにリダイレクトされることが確認できました。

BurpSuiteを眺めるとリダイレクトされていることが確認できる

この場合、コメントは適切に投稿できず、<header class=”notification-header”>タグの配下に「Invalid email address: xxx」というエラーメッセージが表示されます。

「Invalid email address: xxx」というエラーメッセージが確認できる

上記より、無効なメールアドレスの形式を使用したときのみnotification Cookieが付与され、メールアドレスがエラーメッセージに含まれていることがわかります。
そこから、notificationにはこのメールアドレスが暗号化されたものが入っていると推測し、以下の2つのリクエストをBurpSuiteのRepeater機能 に送信します。

  • POST /post/comment(以後、encryptリクエスト)
  • GET /post?postId=x(以後、decryptリクエスト)

ここで、stay-logged-in cookie も同様のアルゴリズムで暗号化されていると推測し、notification cookie の値に stay-logged-in cookie の値を入れて decryptリクエストを送信します。
すると、`wiener:1604913155084`という値を得ることができ、このcookieは「username:timestamp」という形式であることがわかりました。

復号されたstay-logged-in cookie が確認できる

今度は、emailパラメータに `wiener:1604465151121` をセットして encryptリクエストを送信し、得られたnotificationを用いて decryptリクエストを送信します。
すると、「Invalid email address: wiener:1604465151121」と表示されます。
このことから、先頭23byteに 「Invalid email address: 」 が付与されて暗号化されているということがわかります。

ここで、使用されている暗号アルゴリズムは単純に1ブロックずつ処理する、平文ブロックと暗号文ブロックが一対一の関係になるアルゴリズムであると仮定します。

mailパラメータ に `administrator:1604465151121` をセットして encryptリクエストを送信し、得られたnotification Cookieを BurpSuiteのdecoder機能に渡します。(cookieの末尾の「;」については、decoderには渡しません。)

decoder に渡した notification Cookie を URL decode > base64 decode し、先頭の23byteを削除します。次に、再度、base64 encode > URL encode を行います。

得た結果を decrypt リクエストに付与して送信すると、入力値を16byte毎にブロックにして暗号化するアルゴリズムを使用していることを示すエラーメッセージが表示されます。

そのため、「Invalid email address: 」の23byte から16byteを引いた9byte 分を先頭に追加した`xxxxxxxxxadministrator:1604465151121`をemailの値としてencryptリクエストに渡し、 notification Cookieを得ます。

再度decoder機能を用いて、 notification cookieを URL decode > base64 decode し、先頭の23+9 = 32byte分を削除し、base64 encode > URL encode を行います。

上記で得られた値を notificationの値として decrypt リクエストに付与して送信すると、 「Invalid email address: 」が付与されずに `administrator:1604465151121`が表示されていることが確認することができます。
これで、administratorを装って管理者パネルにアクセスする準備ができました。

最後に、session Cookie を削除した状態で、stay-logged-in cookie に上記で得た値をセットし、管理者パネルにアクセスします。(session cookie は勝手に付与されます。)

/admin 管理者パネルにアクセス

管理者パネルからCarlosアカウントを削除します。
本Labはこれでクリアです。
筆者は本Labを解くにあたって、ユーザにより入力されたパラメータがnotification Cookieに暗号化して渡されると気づくまでに少し悩みました。悩んだ時には、コメント投稿が成功したときと失敗したときでの挙動やパラメータの差異を意識して一つ一つBurp Suiteで確認しながら、ヒントとなる情報がないかを探しました。実際の検査でもエラー情報やパラメータの差異を意識して確認しています。

おわりに

本記事では、 PortSwigger Web Security Academy より Business Logic に関するLab1問を紹介いたしました。
必ずしもWebアプリケーションの設計・開発において想定していた通りのワークフローに従ってリクエストが投げられるとは限りません。今回ご紹介したLabのように、改ざん・詐称したリクエストが投げられる可能性を考慮した設計や開発、そしてセキュリティ対策を実施することが大切です。
Web Security Academyは、基礎的なLabから少し複雑なLabまで様々なレベルかつ幅広いトピックを学ぶことができるのでとても勉強になります。ぜひ挑戦してみてください。

参考情報

執筆者プロフィール

中島 春香(なかしま はるか)
セキュリティ技術センター リスクハンティングチーム

ペネトレーションテストを通じて安全なシステムの構築支援の業務に従事。
CTF for GIRLS副代表として主にWeb分野の問題作成やワークショップ企画設計を担当。
CISSP Associate 保持
SANS SEC504 メダル保持
「Hardening II SU」にてMVV(Most Valuable vendor)賞受賞
趣味は美味しいものやワクワクすることを探し歩くこと。