
تحليل قائم على CodeQL لثغرة تلوث النموذج الأولي CVE-2025-55182 في مكونات خادم React، مع POC للاستغلال واستعلامات كشف ثابتة لاجتياز الخصائص غير الآمن.
البناء والتشغيل:
docker compose build
docker compose run --rm --entrypoint 'npm install' node
docker compose run --rm --entrypoint 'npm run build' node
docker compose up
POC (من https://github.com/msanft/CVE-2025-55182):
node poc.js
التجريب مع unbundled:
yarn --immutable
node --conditions react-server app.js
استنسخ facebook/react وأنشئ نسخة unbundled:
yarn --immutable
yarn cross-env RELEASE_CHANNEL=experimental node ./scripts/rollup/build.js react-server-dom-webpack/ --type=NODE_DEV
cp ./build/node_modules/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js \
codeql/${version}/
تجهيز CodeQL:
codeql database create db -l javascript -s codeql
cd queries && codeql pack install
codeql query run ./queries/PrototypeTraversal.ql -d db
Promise.resolve(userData)
await non-native-promise
await للدوال التي لا تُرجع وعداً أصلياً (native promise)await بشكل خاطئ على دالة تعيد (أحياناً) بيانات خامالتقط الاستعلام الاستخدامَ المُصحَّح في getOutlinedModel (حيث أُضيف hasOwnProperty.call) والاستخدام المُزال في createModelResolver (الذي أصبح الآن fulfillReference).
| اسم الملف | المصدر | المصب | |
|---|---|---|---|
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | parentObject[reference[key]] | parentObject[reference[key]] | عبور غير آمن للنموذج الأولي: المتغير 'parentObject' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | parentObject[reference[key]] | parentObject[reference[key]] | عبور غير آمن للنموذج الأولي: المتغير 'parentObject' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | value[path[i]] | value[path[i]] | عبور غير آمن للنموذج الأولي: المتغير 'value' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./tests.js | value[path[i]] | c | عبور غير آمن للنموذج الأولي: المتغير 'value' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./tests.js | value[path[i]] | c | عبور غير آمن للنموذج الأولي: المتغير 'value' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./tests.js | value[path[i]] | value[path[i]] | عبور غير آمن للنموذج الأولي: المتغير 'value' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./vuln.js | parentObject[reference[key]] | parentObject[reference[key]] | عبور غير آمن للنموذج الأولي: المتغير 'parentObject' يُحدَّث بخاصية خاصة به داخل حلقة. |
| ./vuln.js | value[path[i]] | value[path[i]] | عبور غير آمن للنموذج الأولي: المتغير 'value' يُحدَّث بخاصية خاصة به داخل حلقة. |
لا أعرف لماذا يشير الأول والثاني إلى نفس الموقع، بينما المستخرج في vuln.js لا يشير.
في codeql/tests.js توجد هذه الأشكال الثلاثة:
var value = {};
for (let i = 0; i < path.length; i++) {
value = value[path[i]] // VarAccess
}
var value = {};
for (let i = 0; i < path.length; i++) {
let c = value[path[i]] // VarDecl
value = c
}
var value = {};
for (let i = 0; i < path.length; i++) {
let c
c = value[path[i]] // use VarRef
value = c
}