文章总结: 本文从React框架的next-action头部机制切入,分析了actionId的识别与转发流程。关键发现包括:通过serverActionsManifest映射action与worker关系,当本地无对应worker时由selectWorkerForForwarding选择转发目标,最终通过createForwardedActionResponse构造跨worker请求。可操作建议涉及审计时重点关注action绑定逻辑与转发路径的归一化处理。 综合评分: 85 文章分类: WEB安全,代码审计,漏洞分析,安全开发,应用安全
跟我零基础跟完RSC反序列(1)
原创
YMsora YMsora
YMs0ra的安全漫路
2026年4月7日 00:41 浙江
(1)
1.React框架的next-action初步
业务逻辑的跟进
关于next-action这个头,是一种函数身份的定位,也就是一串hax值,react框架构建以来,每个函数会绑定一串hax,作为标识符.
当然我的审计是从next-action的识别及后续开始的,所以我暂时不会在初步构建以及hax加密这块去做工作。
另外,为了加强文档可读性,我会较多换行。那就 START
if (actionId) {
const forwardedWorker = (0, _actionutils.selectWorkerForForwarding)(actionId, page, serverActionsManifest);
// If forwardedWorker is truthy, it means there isn't a worker for the action
// in the current handler, so we forward the request to a worker that has the action.
if (forwardedWorker) {
return {
type: 'done',
result: await createForwardedActionResponse(req, res, host, forwardedWorker, ctx.renderOpts.basePath)
};
}
}
其中selectWorkerForForwarding这个函数,溯源之后是.d.ts的声明文档,在同目录下的js文件处找到了源function。
function selectWorkerForForwarding(actionId, pageName, serverActionsManifest) {
var _serverActionsManifest__actionId;
const workers = (_serverActionsManifest__actionId = serverActionsManifest[process.env.NEXT_RUNTIME === 'edge' ? 'edge' : 'node'][actionId]) == null ? void 0 : _serverActionsManifest__actionId.workers;
const workerName = normalizeWorkerPageName(pageName);
// no workers, nothing to forward to
if (!workers) return;
// if there is a worker for this page, no need to forward it.
if (workers[workerName]) {
return;
}
// otherwise, grab the first worker that has a handler for this action id
return denormalizeWorkerPageName(Object.keys(workers)[0]);
}
这里的serverActionManifest参数类似一张actionid和worker进程的对应表单,下面就是return,其中denormalizeWorkerPagename是返回转发路径的。
也就是说,serverActionsManifest的action匹配的workers值被赋值给workers,然后denormalizeWorkerPageName将所有对应的workers的路径返回。
*/ function denormalizeWorkerPageName(bundlePath) {
return (0, _apppaths.normalizeAppPath)((0, _removepathprefix.removePathPrefix)(bundlePath, 'app'));
}
接下来就是1返回的createForwardedActionResponse,简化的最终请求就是
const response = await fetch(fetchUrl, {
method: 'POST',
body,
duplex: 'half',
headers: forwardedHeaders,
redirect: 'manual',
next: {
// @ts-ignore
internal: 1
}
});
body经过strearm之后可以分块读取数据,body是我们的req,headers是扒res的cookie之类的字段送过去
const forwardedHeaders = getForwardedHeaders(req, res);
以上,next-action的前置分析完成,再者就到了action的server接收以及解析。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:YMs0ra的安全漫路 YMsora YMsora《跟我零基础跟完RSC反序列(1)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论