0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティー】Prototype Pollution × XSS:Lodash _.set が生む“静かなる致命傷”を実例で解説する

Posted at

はじめに

Webアプリケーションの世界では、Prototype Pollution(プロトタイプ汚染)はもはや珍しい脆弱性ではない。しかし、実際に攻撃チェーンとして成立するパターンは多くない。
本記事では、Lodash の _set 関数を悪用した Prototype Pollution と Stored XSS が組み合わさると何が起きるのかを、TryHackMe のサンプルアプリを題材にわかりやすく解説する。


Prototype Pollution とは何か

JavaScript ではオブジェクトが prototype を共有しており、その prototype を改ざんできてしまうと…

  • すべてのオブジェクトに新しいプロパティが共有される
  • すべての class/object の挙動を一度に変えられる

という、“根本からの書き換え”が発生する。

攻撃者が狙うキーはほぼ決まっている:

  • __proto__
  • constructor
  • prototype

これらを利用することで、意図しない共有プロパティ(例:isAdmin)をアプリ全体にばら撒くことが可能だ。


ゴールデンルール:Path-based Property Definition が穴になる

典型的な攻撃例は次のようなコードに潜む。

_.set(obj, input.path, input.value);

もし攻撃者が input.path を自由に設定できる場合、

input.path = "__proto__.isAdmin"
input.value = true

と送られれば、Object.prototype に isAdmin が生える

これが後続の認証・権限チェックに利用されていれば、一瞬で管理者権限が奪われる。


実例:Review 機能を悪用した XSS + Prototype Pollution

TryHackMe のサンプルアプリに、友人にレビューを投稿する機能がある。

提供されているクライアント側のフォーム

<form action="/submit-friend-review" method="post">
    <input type="hidden" name="friendId" value="1">
    <textarea name="reviewContent"></textarea>
</form>

どこにでもある、ごく普通のレビュー投稿機能だ。


サーバー側の処理が危険

問題はバックエンドにある。

const input = JSON.parse(reviewContent);
_.set(friend, input.path, input.value);

ユーザーの入力を JSON としてパースし、Lodash の _set で friend オブジェクトに保存している。
この 1 行が、Prototype Pollution を誘発する“起爆剤”だ。


攻撃ステップ:Stored XSS の注入

まずは攻撃者が XSS を仕込む場合の例。

{
  "path": "reviews[0].content",
  "value": "<script>alert('Hacked')</script>"
}

レビュー欄は HTML エスケープされていないため、
ユーザーのプロフィールを閲覧するたびに XSS が発火する。

XSS image

XSS 単体でも十分危険だが、本当の問題はここからだ。


本命:Prototype Pollution による権限の乗っ取り

同じ仕組みで攻撃者が次の payload を送るとどうなるか:

{
  "path": "__proto__.isAdmin",
  "value": true
}

するとアプリ全体の prototype に isAdmin = true が追加される。

もしどこかに下記のような権限チェックが存在すれば…

if (req.user.isAdmin) {
    // 管理者機能
}

ログイン済みの全ユーザーが admin に昇格する。

もはや「レビュー投稿機能」どころか、
アプリケーションの基盤そのものが破壊される


重要ポイント

1. Path-based 操作をユーザー入力に使ってはいけない

_.set, _.get, _.merge は Prototype Pollution の常連犯。
これらを そのままユーザー入力に適用するのは絶対に避けるべき


2. JSON.parse(reviewContent) の設計がそもそも誤っている

レビュー内容を JSON として受ける必要はない。

  • 文字列として受け取る
  • server-side で最低限の sanitization を行う
  • 保存と画面表示は分離する

という設計にすべき。


3. XSS が Prototype Pollution を加速させる

Prototype Pollution は単体だと exploit しづらいが、
XSS・CSRF・認証周りの欠陥と組み合わされると一気に実用化する。

この組み合わせは、攻撃者から見ると非常に“扱いやすい”


防御策まとめ

攻撃手法 防御策
Path-based pollution __proto__, constructor, prototype を入力拒否
Lodash 使用 _set / _merge をユーザー入力に使用しない
XSS すべてのユーザー入力を HTML エスケープ
データモデル ReviewContent を JSON 形式で受けない
Prototype Pollution 対策 Object.hasOwnProperty をチェックしながら処理する

まとめ:Prototype Pollution は“静かにアプリを乗っ取る”

Prototype Pollution は単体だと目立たないが、
XSS や権限チェックと組み合わさると爆発的な被害を生む脆弱性である。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?