
A OSINT project that explores how to dump data from React
这个工具是一个为 Tampermonkey 编写的快速而粗糙的用户脚本,它会深入任何 React 页面若干层,并搜索用户提供的一个或多个短语。
该工具可以让你轻松地在 DOM 中找到 React 附加大量 JSON 数据的位置。
手动查找这些位置可能非常耗时,因为数据的存储和传递方式在很大程度上取决于开发者、React 的版本以及特定网站的复杂性。
这个用户脚本旨在让这一过程变得容易得多。
下面是该脚本实际使用时的视频。

关于这项工作如何以及为何进行的更多背景信息,请参阅本仓库中其他位置的同名教程。
从本仓库复制用户脚本,并按照 Tampermonkey 文档 中的说明安装该脚本。
大体流程是:选择 Create a new userscript,删除 Tampermonkey 提供的任何样板内容,粘贴用户脚本并保存。然后就可以使用了。
安装后,该用户脚本会提供一个带有两个按钮的右键上下文菜单,这些按钮应在所有使用 React 的网站上启用(如果你发现有网站未启用,请告诉我):
reactPropsreactFiber如下所示。

这两个按钮以 React 附加到常规 DOM 中 HTML 节点上的两个内部属性命名。React 使用它们来内部传递数据、构建页面、保持页面状态与其虚拟 DOM(VDOM)同步、响应 用户操作等等。
也正因如此,我们可以通过这两个属性批量访问和转储原始数据——包括大量在 DOM 中原本不暴露的数据。
要使用该工具,只需打开开发者工具中的 JavaScript 控制台,然后选择两个选项之一。如果其中一个没有给你任何数据,就试试另一个。如前所述,哪个有效似乎在很大程度上取决于具体网站。
在这个例子中,我在查找 SANS 研究所 TikTok 视频的数据。我输入的短语之一是 four days,它出现在第一个视频下方:

你提供给用户脚本的输入会先被转为小写并去除空格,然后再与附加在 HTML 节点上的属性内容进行比较,所以基本上,直接输入你想要的内容即可。
如果你愿意,也可以使用多个短语,只需用逗号分隔。如果你想在 TikTok 示例中定位多个视频,可以输入 four days,congratulations,thank you。
该脚本使用 OR 而不是 AND 作为搜索运算符。
你还可以使用通配符 *,它会转储所有内容。
不过对此有一个小警告:
执行 * 搜索可能会导致你的开发者工具崩溃,因为它很容易转储数万行数据。所以,请只把那个 功能 作为最后手段使用。尤其是在 Facebook 上,如果这样做,你会被数据淹没。
一般来说,值得搜索的内容是某些你确信应该存在的用户名 / 用户 ID——或者,如果你知道某处有一个名为 videoData 的属性,直接使用它即可。
在 TikTok 上触发脚本(reactProps)时,大量数据会被记录到 JavaScript 控制台中——同时也会复制到你的剪贴板。在底部,你会看到搜索模式命中的次数(本例中为 5 次)。

如果你想浏览 JSON 数据,只需将其粘贴到编辑器中——最好是支持 JSON 和语法高亮的编辑器。这样浏览起来会容易得多。
然而,如果你打算为特定网站构建基于 React 的工具,真正好用的功能并不是剪贴板转储。除了转储数据外,该脚本还会记录命中的 HTML 节点,以及匹配数据所在的确切属性路径。

这个功能解决了在尝试将 React 的 VDOM 映射到常规 DOM 时遇到的一个真正的麻烦——与 VDOM 不同,我们可以使用原生 JavaScript 与常规 DOM 交互。
在本例中,输出告诉我们,我们想要的数据被附加为属性,其中之一是在 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 节点提取所需键的有效示例。
该脚本实际做的是深入所选类别(__reactFiber 或 __reactProps)的每个属性若干层,并尝试将内部所有内容转换为 JSON(JSON.stringify())。如果内部的对象包含循环引用(很多对象都会有),则无法解析为 JSON。尝试转换会引发错误,该错误会被捕获,循环会忽略它并继续执行。
目前,该脚本也只查看 <div> 和 <article> 标签的属性。如果你发现它因此遗漏了某些内容,请告诉我。这还是一项正在进行中的工作。
此外,该脚本不会对属性进行非常深层的递归。首先,我不擅长递归。其次,我对深层嵌套在属性中的内容不太感兴趣,因为在此基础上构建的东西更有可能因为目标平台上即使是微小的变化而出现问题。根据我的经验,应该可以在靠近 HTML 节点的地方找到数据。
此脚本仅用于教育目的。不要滥用它。请守规矩。与人为善。并且不要触犯任何法律。