
A OSINT project that explores how to dump data from React
このツールは、Tampermonkey用の即席ユーザースクリプトで、あらゆるReactページの中を数レベル掘り下げ、ユーザーが指定した1つ以上のフレーズを検索します。
このツールを使うと、Reactが大きなJSONデータの塊をアタッチしているDOM内の正しい場所を簡単に見つけられます。
こうした場所を手動で見つけるのは非常に時間がかかります。なぜなら、データの保存方法や受け渡し方法は、開発者やReactのバージョン、サイトの複雑さに大きく依存するからです。
このユーザースクリプトは、そのプロセスを大幅に簡単にすることを目的としています。
以下は、このスクリプトを使用している動画です。

この仕組みの背景や理由については、このリポジトリ内の別場所にある同じテーマのチュートリアルを参照してください。
このリポジトリからユーザースクリプトをコピーし、スクリプトのインストール方法についてTampermonkeyドキュメントの指示に従ってください。
要点は、Create a new userscriptを選択し、Tampermonkeyが提案するボイラープレートを削除して、ユーザースクリプトを貼り付けて保存を押すだけです。これで準備完了です。
インストールすると、このユーザースクリプトは右クリックコンテキストメニューに2つのボタンを提供します。これらはReactを使用するすべてのサイトで有効になるはずです(もし有効にならないサイトを見つけたら、お知らせください)。
reactPropsreactFiberこれは以下で確認できます。

ボタンの名前は、Reactが通常のDOM内のHTMLノードに付与する2つの内部プロパティに由来しています。Reactはこれらを使って、内部でのデータ受け渡し、ページの構築、ページの状態を自身の仮想DOM(VDOM)と同期させること、ユーザーの操作に反応することなどを実現しています。
また、これらのプロパティを通じて、生データにアクセスして一括ダンプすることもできます。通常はDOMに公開されない大量のデータも含まれます。
このツールを使うには、開発者ツールでJavaScriptコンソールを開き、2つのオプションのいずれかを選ぶだけです。データが得られない場合は、もう一方を試してください。前述のとおり、どちらが機能するかは特定のWebサイトに大きく依存するようです。
この例では、SANS InstituteのTikTok動画に関するデータを探しています。入力として、最初の動画の下にあるフレーズの1つ、four daysを指定しました。

ユーザースクリプトに入力する文字列は、HTMLノードにプロパティとして付与されたコンテンツと比較される前に、小文字化され、空白がトリミングされます。なので、本当に好きなものを入力するだけで大丈夫です。
必要であれば、複数のフレーズを使うこともできます。カンマで区切るだけです。TikTokの例で複数の動画を対象にしたい場合は、four days,congratulations,thank youのように指定できます。
スクリプトは検索演算子としてANDではなくORを使用します。
ワイルドカード*を使用すると、すべてをダンプすることもできます。
ただし、これに対する小さな警告があります:
*検索を実行すると、簡単に数万行のデータをダンプする可能性があるため、開発者ツールがクラッシュするかもしれません。そのため、その機能は最後の手段としてのみ使用してください。特にFacebookで使用すると、データに埋もれてしまいます。
一般的に、検索すると便利なのは、存在するはずの特定のユーザー名やユーザーIDです。あるいは、どこかにvideoDataという名前のプロパティがあることが分かっているなら、単にそれを使うのも手です。
TikTokでスクリプト(reactProps)を実行すると、大量のデータがJavaScriptコンソールにログ出力され、同時にクリップボードにもコピーされます。一番下には、検索パターンがいくつヒットしたかの数が表示されます(この場合は5件)。

JSONデータを調査したい場合は、エディタに貼り付けるだけです。できればJSONとシンタックスハイライトに対応したエディタが良いでしょう。そうすれば、はるかに簡単に確認できます。
ただし、特定のWebサイト向けのReactベースのツールを構築する予定があるなら、本当に素晴らしい機能はクリップボードへのダンプではありません。スクリプトはデータのダンプに加えて、マッチしたHTMLノードと、マッチが見つかった正確なプロパティパスの両方もログ出力します。

この機能は、ReactのVDOMを通常のDOMに対応付ける際の実際の面倒の1つを解決します。私たちはVDOMとは異なり、通常のDOMとはバニラJavaScriptでやり取りできます。
この場合、出力から、必要なデータが、HTMLノード<div class="css-x6y88p-DivItemContainerV2 e19c29qe8">などにプロパティとして付与されており、パス__reactProps$xunlb5k9rwt | children | 1 | propsのプロパティであることが分かります。
この情報が分かれば、どのノードのどのパスからデータを取得できるかを正確に把握できます。
|は私が選んだ単なる区切り文字です。これをスクリプトに変換するときは、ドット記法(例: __reactProps$xunlb5k9rwt.children[1].props)やブラケット記法(例: ["__reactProps$xunlb5k9rwt"]["children"][1]["props"])に置き換えてください。

このリポジトリ内のReactチュートリアルで述べられているように、__reactProps部分には、ページが読み込まれるたびにランダムに生成される10文字の文字列が含まれています。
HTMLノードの1つから必要なキーを取得する方法の実用的な例については、チュートリアルを参照してください。
このスクリプトが実際に行うのは、選択したカテゴリ(__reactFiberまたは__reactProps)の各プロパティを数レベル深く掘り下げ、内部のすべてをJSON(JSON.stringify())に変換しようとすることです。内部のオブジェクトに循環参照が含まれている場合(多くが含まれます)、JSONとして解析できません。変換しようとするとエラーが発生しますが、それはキャッチされ、ループはこれを無視して続行します。
現時点では、スクリプトは<div>タグと<article>タグのプロパティのみを対象としています。この理由で何か見落としていることに気付いた場合は、お知らせください。これはまさに進行中の作業です。
また、スクリプトはプロパティをそれほど深く再帰しません。まず第一に、私は再帰が苦手です。第二に、プロパティ内に深く入れ子になったものにはあまり興味がありません。なぜなら、その上に何かを構築すると、対象とするプラットフォームのわずかな変更でも壊れやすくなるからです。私の経験では、HTMLノードの近くでデータを見つけることができるはずです。
このスクリプトは教育目的のみで提供されています。悪用しないでください。行儀よく振る舞い、親切にしましょう。そして、法律を犯さないでください。