แฮนด์บาร์: การเข้าถึงถูกปฏิเสธเพื่อแก้ไขคุณสมบัติ“ จาก” เนื่องจากไม่ใช่“ คุณสมบัติของตัวเอง” ของพาเรนต์


15

ฉันใช้แบ็กเอนด์ Nodejs กับการเรนเดอร์ฝั่งเซิร์ฟเวอร์โดยใช้แฮนด์บาร์ หลังจากอ่านdocอาเรย์ของวัตถุจากแฮนด์บาร์ซึ่งมีคีย์ "เนื้อหา" และ "จาก" อย่างไรก็ตามเมื่อฉันพยายามที่#eachจะวนลูปผ่านอาร์เรย์ของวัตถุข้อผิดพลาด "แฮนด์บาร์: การเข้าถึงถูกปฏิเสธเพื่อแก้ไขคุณสมบัติ" จาก "เพราะไม่ใช่" คุณสมบัติของตัวเอง "ของพาเรนต์" ปรากฏขึ้น

ฉันพยายาม console.log () ข้อมูลที่ฉันได้รับในอาร์เรย์ doc และทุกอย่างดูเหมือนจะดี

สำหรับบางมุมมองนี่เป็นข้อความค้นหาพังพอน
ฉันได้เพิ่มเอกสารวัตถุเป็นกุญแจในอาร์กิวเมนต์ res.render

Confession.find()
  .sort({date: -1})
  .then(function(doc){
    for(var i=0; i < doc.length; i++){
      //Check whether sender is anonymous
      if (doc[i].from === "" || doc[i].from == null){
        doc[i].from = "Anonymous";
      }

      //Add an extra JSON Field for formatted date
      doc[i].formattedDate = formatTime(doc[i].date);
    }
    res.render('index', {title: 'Confession Box', success:req.session.success, errors: req.session.errors, confession: doc});
    req.session.errors = null;
    req.session.success = null;
  });

นี่คือส่วนของไฟล์. hbs ที่ฉันพยายามวนซ้ำ:

 {{#each confession}}
    <div class="uk-card uk-card-default uk-card-body uk-margin uk-align-center uk-width-1-2@m" >
        <div class="uk-text-bold">Message: </div>
        <div>{{this.content}}</div>
        <div>From: {{this.from}}</div>
        <div>Posted: {{this.formattedDate}}</div>
    </div>
    {{/each}}

คำตอบ:


25

ฉันแก้ปัญหานี้โดยการติดตั้งการพึ่งพา dev สำหรับแฮนด์บาร์

npm i -D handlebars@4.5.0


ว้าวใช้งานได้ทำไมถึงเกิดเหตุการณ์เช่นนี้ ขณะนี้ฉันใช้ express-handlebars (3.1.0) ซึ่งฉันตั้งเป็นเอ็นจิ้นการเรนเดอร์ในแอปด่วนของฉัน
ลีบุญกง

ฉันสงสัยว่านี่เกิดขึ้นกับแฮนด์บาร์รุ่นใหม่เนื่องจากข้อ จำกัด บางอย่าง แต่ฉันไม่ทราบวิธีการทำงานกับข้อ จำกัด เหล่านี้
ลีบุญกง

ปัญหาเกิดขึ้นระหว่างปลั๊กอินด่วนที่รองรับแฮนด์บาร์ แต่เมื่อแฮนด์บาร์ 4.5.0 ถูกบันทึกเพื่อใช้เป็นเครื่องมือหลักของส่วนหน้าของคุณโปรดแจ้งให้เราทราบโดยแสดงความคิดเห็นในเรื่องนี้
เมสัน

สิ่งนี้ไม่ทำงาน ยังคงได้รับปัญหาเดียวกันหลังจากฉันเรียกใช้ npm i -D handlebars@4.5.0
Deepak Thakur

คำตอบที่ถูกต้องอยู่ที่นี่github.com/wycats/handlebars.js/issues/1642
Deepak Thakur

12

หากใช้พังพอนปัญหานี้สามารถแก้ไขได้โดยใช้ .lean () เพื่อรับวัตถุ json (แทนที่จะเป็นพังพอน):

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });

3
ขอให้พระเจ้าคุ้มครอง! ประหยัดชีวิต!
Nick Thatick

1
ไม่มีปัญหาดีใจที่ได้ช่วย !!
Billeh

2
หวังว่าฉันจะเอาชนะคำตอบนี้ได้มากกว่าหนึ่งครั้ง .. ฮ่าฮ่าขอบคุณมาก!
Abdus

7

วันนี้ฉันมีคำเตือนเดียวกันจากแฮนด์บาร์และมุมมองว่างเปล่า ด้านล่างนี้เป็นวิธีที่ฉันแก้ไข:

//  * USERS PAGE
// @description        users route
// @returns           ../views/users.hbs
router.get('/users', async (req, res) => {
  // get all items from db collection
  const collection = 'User'
  await dbFindAllDocs(collection) // <=> wrapper for Model.find() ...
    .then(documents => {
      // create context Object with 'usersDocuments' key
      const context = {
        usersDocuments: documents.map(document => {
          return {
            name: document.name,
            location: document.location
          }
        })
      }
      // rendering usersDocuments from context Object
      res.render('users', {
        usersDocuments: context.usersDocuments
      })
    })
    .catch(error => res.status(500).send(error))
})

ไฟล์ users.hbs

<ul>
{{#each usersDocuments}}
<li>name: {{this.name}} location: {{this.location}}</li>
{{/each}}    
</ul>

การสร้างออบเจ็กต์ใหม่ทั้งหมดที่contextมีชื่อด้วยคุณสมบัติของตัวเองจากนั้นส่งเข้าไปในฟังก์ชั่นการเรนเดอร์เพื่อแก้ไขปัญหา ...

บันทึก:

เมื่อเราไม่ได้สร้างวัตถุใหม่มันเป็นเรื่องง่ายที่จะเปิดเผยข้อมูลที่เป็นความลับหรือข้อมูลที่อาจส่งผลต่อความปลอดภัยของ projet การทำแผนที่ข้อมูลที่ส่งคืนจากฐานข้อมูลและส่งผ่านเฉพาะสิ่งที่จำเป็นในมุมมองเท่านั้น ...


ขอบคุณมากสำหรับคำตอบของคุณ! ดูเหมือนว่าจะเป็นการดีกว่าที่จะสร้างวัตถุใหม่เพื่อป้องกันการเปิดเผยข้อมูลที่ไม่พึงประสงค์
ลีบุญกง

ขอบคุณสำหรับงานนี้
GNETO DOMINIQUE

การเรนเดอร์รายการใหม่จากรายการที่เตรียมไว้ใช้เวลา 2x หรือไม่
mustafiz012

6

"ว้าวใช้งานได้แล้วทำไมมันถึงเกิดขึ้นตอนนี้ฉันกำลังใช้งานแฮนดายบาร์ (3.1.0) ซึ่งฉันตั้งเป็นเอ็นจิ้นการเรนเดอร์ในแอพด่วนของฉัน" - ลีบุญกง 12 ม.ค. เวลา 14:13 น

"ในอดีตมือจับจะอนุญาตให้คุณเข้าถึงวิธีการต้นแบบและคุณสมบัติของวัตถุอินพุตจากแม่แบบ ... ปัญหาด้านความปลอดภัยหลายอย่างมาจากพฤติกรรมนี้ ... ใน handlebars@^4.6.0 การเข้าถึงวัตถุต้นแบบมี ถูกปิดใช้งานอย่างสมบูรณ์. ตอนนี้ถ้าคุณใช้คลาสที่กำหนดเองเป็น input เพื่อแฮนด์รหัสของคุณจะไม่ทำงานอีกต่อไป ... แพคเกจนี้จะเพิ่มตัวเลือกให้กับแต่ละรันไทม์แม่แบบสายปิดการใช้งานข้อ จำกัด การรักษาความปลอดภัย ... หากผู้ใช้ของคุณเขียน แม่แบบและคุณรันมันบนเซิร์ฟเวอร์ของคุณคุณไม่ควรใช้แพ็คเกจนี้ แต่หาวิธีอื่นในการแก้ปัญหา ...ฉันขอแนะนำให้คุณแปลงคลาสอินสแตนซ์ของคุณเป็นวัตถุ JavaScript ธรรมดาก่อนส่งต่อไปยังฟังก์ชันเทมเพลต ทุกคุณสมบัติหรือฟังก์ชั่นที่คุณเข้าถึงจะต้องเป็น "คุณสมบัติของตัวเอง" ของแม่ของมัน "- README

รายละเอียดเพิ่มเติมได้ที่นี่: https://www.npmjs.com/package/@handlebars/allow-prototype-access

วิธีที่ไม่ปลอดภัยอย่างรวดเร็วและสกปรก

การใช้งาน ( express-handlebarsและmongoose):

express-handlebarsไม่อนุญาตให้คุณระบุตัวเลือกรันไทม์เพื่อส่งผ่านไปยังฟังก์ชันเทมเพลต แพคเกจนี้สามารถช่วยคุณปิดการตรวจสอบต้นแบบสำหรับรุ่นของคุณ

"ทำสิ่งนี้หากคุณสามารถควบคุมเทมเพลตที่ดำเนินการในเซิร์ฟเวอร์ได้อย่างสมบูรณ์"

ขั้นตอน:

1 - ติดตั้งการพึ่งพา

npm i @handlebars/allow-prototype-access

2 - ใช้ตัวอย่างนี้เป็นตัวอย่างเพื่อเขียนเซิร์ฟเวอร์ด่วนของคุณ

const express = require('express');
const mongoose = require('mongoose');
const Handlebars = require('handlebars');
const exphbs = require('express-handlebars');

// Import function exported by newly installed node modules.
const { allowInsecurePrototypeAccess } = require('@handlebars/allow-prototype->access');

const PORT = process.env.PORT || 3000;

const app = express();

const routes = require('./routes');

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static('public'));

// When connecting Handlebars to the Express app...
app.engine('handlebars', exphbs({
    defaultLayout: 'main',
    // ...implement newly added insecure prototype access
    handlebars: allowInsecurePrototypeAccess(Handlebars)
    })
);
app.set('view engine', 'handlebars');

app.use(routes);

const MONGODB_URI = process.env.MONGODB_URI || >'mongodb://localhost/dbName';

mongoose.connect(MONGODB_URI);

app.listen(PORT, function () {
  console.log('Listening on port: ' + PORT);
});

3 - เรียกใช้เซิร์ฟเวอร์และเต้นอย่างมีความสุข


อีกต่อไปวิธีที่ปลอดภัย

ก่อนส่งผ่านวัตถุที่ส่งคืนโดยการเรียก AJAX ของคุณไปยังเทมเพลต Handlebars ให้แมปวัตถุใหม่กับคุณสมบัติหรือฟังก์ชันที่คุณต้องการเข้าถึงใน.hbsไฟล์ของคุณ ด้านล่างคุณสามารถเห็นวัตถุใหม่ที่สร้างขึ้นก่อนส่งผ่านไปยังเทมเพลตแฮนด์บาร์

const router = require("express").Router();
const db = require("../../models");

router.get("/", function (req, res) {
    db.Article.find({ saved: false })
        .sort({ date: -1 })
        .then(oldArticleObject => {
            const newArticleObject = {
                articles: oldArticleObject.map(data => {
                    return {
                        headline: data.headline,
                        summary: data.summary,
                        url: data.url,
                        date: data.date,
                        saved: data.saved
                    }
                })
            }
            res.render("home", {
                articles: newArticleObject.articles
            })
        })
        .catch(error => res.status(500).send(error));
});

แบบสอบถามพังพอนของคุณ

แก้ไขฉันถ้าฉันผิด แต่ฉันคิดว่านี่อาจจะเป็นไปได้สำหรับการค้นหาของคุณ ...

Confession.find()
    .sort({ date: -1 })
    .then(function (oldDoc) {

        for (var i = 0; i < oldDoc.length; i++) {
            //Check whether sender is anonymous
            if (oldDoc[i].from === "" || oldDoc[i].from == null) {
                oldDoc[i].from = "Anonymous";
            }

            //Add an extra JSON Field for formatted date
            oldDoc[i].formattedDate = formatTime(oldDoc[i].date);
        }

        const newDoc = {
            doc: oldDoc.map(function (data) {
                return {
                    from: data.from,
                    formattedDate: data.formattedDate
                }
            })
        }

        res.render('index', { title: 'Confession Box', success: req.session.success, errors: req.session.errors, confession: newDoc.doc });
        req.session.errors = null;
        req.session.success = null;
    });

5

ลอง npm ติดตั้งแฮนด์บาร์เวอร์ชัน 4.5.3

npm ติดตั้ง handlebars@4.5.3

มันใช้งานได้สำหรับฉัน


นี่ควรเป็นความเห็น
อรุณ Vinoth

ขณะนี้ฉันใช้มือจับด่วนรุ่น 3.1.0
Lee Boon Kong

ขอบคุณฉันได้ลองทั้งคุณแล้วและ @ anonser ทำงานได้ แต่ฉันไม่แน่ใจว่าทำไมสิ่งนี้ถึงเกิดขึ้น
ลีบุญกง

3

เริ่มจากเวอร์ชัน 4.6.0 เป็นต้นไป Handlebars ห้ามมิให้เข้าถึงคุณสมบัติต้นแบบและวิธีการของวัตถุบริบทโดยค่าเริ่มต้น สิ่งนี้เกี่ยวข้องกับปัญหาด้านความปลอดภัยที่อธิบายไว้ที่นี่: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

อ้างถึงhttps://github.com/wycats/handlebars.js/issues/1642

หากคุณมั่นใจว่ามีเพียงผู้พัฒนาเท่านั้นที่สามารถเข้าถึงเทมเพลตเป็นไปได้ที่จะอนุญาตการเข้าถึงต้นแบบโดยการติดตั้งแพ็คเกจต่อไปนี้:

npm i @handlebars/allow-prototype-access

หากคุณกำลังใช้แฮนด์ด่วนคุณควรดำเนินการดังนี้:

const 
    express = require('express'),
    _handlebars = require('handlebars'),
    expressHandlebars = require('express-handlebars'),
    {allowInsecurePrototypeAccess} = require('@handlebars/allow-prototype-access')

const app = express()

app.engine('handlebars', expressHandlebars({
    handlebars: allowInsecurePrototypeAccess(_handlebars)
}))
app.set('view engine', 'handlebars')

ขอบคุณสิ่งนี้ได้ผล ดังนั้นเราต้องทำสิ่งนี้ทุกครั้งเมื่อเราต้องใช้มือจับด่วน?
Yash Boura

2

มีการเปลี่ยนแปลงเล็กน้อยในรุ่นล่าสุดของแฮนด์บาร์ซึ่งทำให้เกิดข้อผิดพลาดนี้

คุณสามารถเพิ่มการกำหนดค่าที่พวกเขาแนะนำในเอกสารประกอบของพวกเขาได้ แต่ระวังให้ดีขึ้นอยู่กับการติดตั้งของคุณซึ่งอาจนำไปสู่การโจมตีแบบ XXS และ RCE

https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access

Confession.find()
  .sort({date: -1})
  .then(function(doc){
    for(var i=0; i < doc.length; i++){
      //Check whether sender is anonymous
      if (doc[i].from === "" || doc[i].from == null){
        doc[i].from = "Anonymous";
      }

      //Add an extra JSON Field for formatted date
      doc[i].formattedDate = formatTime(doc[i].date);
    }
    res.render('index', {title: 'Confession Box', success:req.session.success, errors: req.session.errors, confession: doc}, {

      // Options to allow access to the properties and methods which as causing the error.

      allowProtoMethodsByDefault: true,
      allowProtoPropertiesByDefault: true

    });

    req.session.errors = null;
    req.session.success = null;
  });

Ahhh นั่นคือที่ฉันเพิ่มตัวเลือกขอบคุณมาก!
Lee Boon Kong

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน คาดว่าจะเรียกกลับไม่ใช่วัตถุตัวเลือก
mrg95

0

การสร้างวัตถุใหม่หรืออาร์เรย์จากข้อมูลที่ส่งคืนมาfind() จะช่วยแก้ปัญหา ดูภาพประกอบง่ายๆด้านล่าง

app.get("/",(req,res)=>{

 let com = require('./MODELCOM')    // loading model
 let source=fs.readFileSync(__dirname+"/views/template.hbs","utf-8");

 com.find((err,data)=>{
    // creation new array  using map
   let wanted = data.map(doc=>{
       return {
           name:doc.name,
           _id:doc._id
        }
   })

    let html= handlebar.compile(source);
  fs.writeFileSync(__dirname+"/views/reciever.html",html({communities:wanted}))
    res.sendFile(__dirname+"/views/reciever.html")
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.