ปลอดภัยหรือไม่ที่จะเปิดเผย Firebase apiKey สู่สาธารณะ?


438

คู่มือ Firebase เว็บแอปฯ ที่ฉันควรใส่ให้apiKeyใน HTML ของฉันที่จะเริ่มต้น Firebase:

// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: '<your-api-key>',
    authDomain: '<your-auth-domain>',
    databaseURL: '<your-database-url>',
    storageBucket: '<your-storage-bucket>'
  };
  firebase.initializeApp(config);
</script>

โดยการทำเช่นนั้นapiKeyจะได้สัมผัสกับผู้เข้าชมทุกคน จุดประสงค์ของกุญแจนั้นคืออะไรและมีความหมายต่อสาธารณะหรือไม่


1
ฉันคิดว่าตราบใดที่คุณตั้งค่ากฎฐานข้อมูลFirebase AuthและFirebaseคุณสามารถให้ข้อมูลแก่สาธารณะได้
abbaf33f

ผู้ใช้ Christophe Quintard ได้เพิ่มลิงก์ไปยังบทความที่มีประโยชน์มากพร้อมข้อมูลเพิ่มเติมเกี่ยวกับความปลอดภัยของ Firebase APIs ดังนั้นฉันจึงโพสต์ไว้ที่นี่: javebratt.com/hide-firebase-api (ความคิดเห็นจะหายไปเพราะมันแนบมากับผู้ใช้รายอื่น คำตอบที่ถูกตั้งค่าสถานะสำหรับการลบเนื่องจากมีคุณภาพไม่ดี)
โอลิเวอร์ Schafeld

ฉันแค่ต้องการชี้ให้เห็นว่าเพียงเพราะเฟรมเวิร์กเฉพาะนี้เกิดขึ้นได้ดีกับการเปิดเผยว่าเป็น API นั่นไม่ได้หมายความว่าเฟรมเวิร์กอื่นจะใช้ได้กับมัน ไม่ต้องการให้ใครเดินออกไปจากโพสต์นี้ด้วยแนวคิดที่ว่า "โดยทั่วไปแล้วการเปิดเผยคีย์ API" ไม่เป็นไร
YungGun

คุณเปิดเผยคีย์โดยไม่มีปัญหา เพื่อให้ปลอดภัยคุณสามารถ จำกัด ด้วยโดเมนเฉพาะในการผลิตเพื่อให้ไม่มีใครสามารถเรียกการเรียก API จากชื่อโดเมนแบบสุ่มใด ๆ เพื่อให้ปลอดภัยลบ localhost ออกจากแอปการผลิต
BL Λ CK

1
ฉันไม่คิดว่าการลบ localhost ออกจากรายการที่อนุญาตของผู้อ้างอิงของคุณกำลังจะทำอะไรนอกจากการทดสอบให้หนักขึ้น การกำหนดค่านั้นไม่เหมือนกับรายการที่อนุญาตของ IP คิดว่ามันเหมือน config CORS วิธีการทำงานของ Firebase ก็คือเส้นทาง API เหล่านั้นจะถูกเรียกโดยตรงจากลูกค้าไม่ใช่พร็อกซี นั่นเป็นสาเหตุที่หน้าเว็บของคุณต้องการคีย์ API หากนักแสดงที่ไม่ดีต้องการโทรหาเส้นทาง API ของคุณจากบุรุษไปรษณีย์รายการที่อนุญาตพิเศษของคุณจะไม่หยุดพวกเขา มีประโยชน์สำหรับการป้องกันไซต์สาธารณะอื่น ๆ จากการปิดเซิร์ฟเวอร์ของคุณ
forresthopkinsa

คำตอบ:


451

apiKey ในตัวอย่างการกำหนดค่านี้เพียงระบุโครงการ Firebase ของคุณบนเซิร์ฟเวอร์ Google ไม่ใช่ความเสี่ยงด้านความปลอดภัยสำหรับคนที่จะรู้ ในความเป็นจริงมันเป็นสิ่งจำเป็นสำหรับพวกเขาที่จะรู้ว่าเพื่อให้พวกเขามีปฏิสัมพันธ์กับโครงการ Firebase ของคุณ ข้อมูลการกำหนดค่าเดียวกันนี้ยังรวมอยู่ในแอป iOS และ Android ทุกเครื่องที่ใช้ Firebase เป็นแบ็กเอนด์

ในแง่ที่ว่ามันจะคล้ายกับ URL ของฐานข้อมูลที่ระบุฐานข้อมูล back-end https://<app-id>.firebaseio.comที่เกี่ยวข้องกับโครงการของคุณในตัวอย่างเดียวกัน: ดูคำถามนี้ว่าทำไมจึงไม่มีความเสี่ยงด้านความปลอดภัย: จะ จำกัด การปรับเปลี่ยนข้อมูล Firebase ได้อย่างไร? รวมถึงการใช้กฎความปลอดภัยฝั่งเซิร์ฟเวอร์ของ Firebase เพื่อให้มั่นใจว่าผู้ใช้ที่ได้รับอนุญาตเท่านั้นที่สามารถเข้าถึงบริการแบ็คเอนด์

หากคุณต้องการที่จะเรียนรู้วิธีการรักษาความปลอดภัยในการเข้าถึงข้อมูลทั้งหมดของการบริการที่แบ็กเอนด์ Firebase ของคุณจะได้รับอนุญาตอ่านข้อมูลเกี่ยวกับเอกสารในกฎความปลอดภัย Firebase


หากคุณต้องการที่จะลดความเสี่ยงของการกระทำข้อมูลการกำหนดค่านี้เพื่อควบคุมรุ่นให้พิจารณาใช้SDK อัตโนมัติการกำหนดค่าของ Firebase โฮสติ้ง ในขณะที่ปุ่มจะยังคงอยู่ในเบราว์เซอร์ในรูปแบบเดียวกันพวกเขาจะไม่ได้รับการกำหนดค่าตายตัวในรหัสของคุณอีกต่อไป


7
ดังนั้นหมายความว่าคนอื่นจะสามารถเข้าถึงข้อมูลทั้งหมดในฐานข้อมูล firebase ของฉันได้หรือไม่
Emmanuel Campos

31
@EmmanuelCampos คำตอบคือใช่และไม่ใช่ใช่ถ้าคุณอนุญาตหรือต้องการให้ผู้อื่นเข้าถึงข้อมูลทั้งหมดในฐานข้อมูล และไม่ถ้าคุณไม่ต้องการให้พวกเขา ฐานข้อมูล Firebase มีกฎระเบียบที่คุณควบคุม
KhoPhi

5
พบคำตอบของฉันที่นี่สำหรับคำถามสุดท้ายของฉันsupport.google.com/firebase/answer/6400741ขอบคุณสำหรับความช่วยเหลือ ลิงค์นี้อาจช่วยใครซักคนในอนาคต
Emmanuel Campos

7
@ m.rufca ข้อมูลของคุณควรพร้อมใช้งานสำหรับผู้ใช้ที่ได้รับการรับรองความถูกต้อง และนี่คือเคล็ดลับ ตามค่าเริ่มต้นในการตั้งค่าฐานข้อมูลของคุณเฉพาะโฮสต์ในพื้นที่และโดเมนโครงการของคุณเท่านั้นที่ได้รับอนุญาตให้ดำเนินการตรวจสอบสิทธิ์จากพวกเขา ดังนั้นไม่มีใครสามารถสร้างแอปที่ปกติจะทำงานกับฐานข้อมูลของคุณ
Artem Arkhipov

15
จะเกิดอะไรขึ้นถ้าบอตกำลังสร้างผู้ใช้ไม่ จำกัด ที่แอปของฉัน ฉันจะขอแคปต์ชาได้อย่างไร
มูฮัมหมัดอูเมอ

79

จากคำตอบของ prufrofro และ Frank van Puffelen ที่นี่ฉันรวบรวมการตั้งค่านี้ที่ไม่ป้องกันการคัดลอกแต่สามารถทำให้ยากขึ้นเล็กน้อยในการใช้คีย์ API ของคุณ

คำเตือน:หากต้องการรับข้อมูลของคุณแม้จะใช้วิธีนี้ก็สามารถเปิดคอนโซล JS ใน Chrome แล้วพิมพ์:

firebase.database().ref("/get/all/the/data").once("value", function (data) {
    console.log(data.val());
});

กฎความปลอดภัยฐานข้อมูลเท่านั้นที่สามารถปกป้องข้อมูลของคุณได้

อย่างไรก็ตามฉัน จำกัด การใช้คีย์ API การผลิตของฉันในชื่อโดเมนของฉันเช่นนี้:

  1. https://console.developers.google.com/apis
  2. เลือกโครงการ Firebase ของคุณ
  3. หนังสือรับรอง
  4. ภายใต้คีย์ API ให้เลือกรหัสเบราว์เซอร์ของคุณ ซึ่งควรมีลักษณะดังนี้: " คีย์เบราว์เซอร์ (สร้างโดยอัตโนมัติโดย Google Service) "
  5. ใน " ยอมรับการร้องขอจากผู้อ้างอิง HTTP เหล่านี้ (เว็บไซต์) " เพิ่ม URL ของแอปของคุณ (กันตัวอย่าง: projectname.firebaseapp.com/*)

ตอนนี้แอปจะทำงานกับชื่อโดเมนเฉพาะนี้เท่านั้น ดังนั้นฉันจึงสร้างรหัส API ใหม่ที่จะเป็นส่วนตัวสำหรับการพัฒนา localhost

  1. คลิกสร้างข้อมูลรับรอง> รหัส API

โดยค่าเริ่มต้นดังกล่าวโดยมานูเอลโปสFirebase ขาวเท่านั้นlocalhostและโฮสติ้งโดเมน Firebase ของคุณ


เพื่อให้แน่ใจว่าฉันจะไม่เผยแพร่คีย์ API ผิดโดยไม่ได้ตั้งใจฉันใช้วิธีการใดวิธีการหนึ่งต่อไปนี้เพื่อใช้รหัสที่ถูก จำกัด มากขึ้นในการผลิตโดยอัตโนมัติ

การตั้งค่าสำหรับแอป Create-React

ใน/env.development:

REACT_APP_API_KEY=###dev-key###

ใน/env.production:

REACT_APP_API_KEY=###public-key###

ใน /src/index.js

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  // ... 
};

การตั้งค่าก่อนหน้าของฉันสำหรับ Webpack:

ฉันใช้ Webpack เพื่อสร้างแอปพลิเคชันการผลิตของฉันและฉันใส่คีย์ dev API ของฉันไว้ในที่index.htmlเดียวกับที่คุณทำตามปกติ จากนั้นในwebpack.production.config.jsไฟล์ของฉันฉันจะแทนที่กุญแจทุกครั้งที่index.htmlคัดลอกไปยังบิลด์การผลิต:

plugins: [
    new CopyWebpackPlugin([
      {
        transform: function(content, path) {
          return content.toString().replace("###dev-key###", "###public-key###");
        },
        from: './index.html'
      }
    ])
  ]

1
นั่นทำงานได้ดีสำหรับคุณ กำลังคิดที่จะทำสิ่งเดียวกันสำหรับแอป Android ฉันสงสัยว่าทำไม Firebase ไม่ครอบคลุมในส่วนความปลอดภัย
steliosf

2
ฉันไม่เคยมีปัญหามาก่อน แต่อาจไม่มีการโจมตีเลย
ตอนนี้

3
นี่ไม่ได้กล่าวถึงในคู่มือเนื่องจากจะไม่ป้องกันคุณจากการขูด ทั้งหมดนี้ทำให้มั่นใจได้ว่ามีคนอื่นไม่สามารถสร้างเว็บแอปที่ใช้ firebase ของคุณเพื่ออ่าน (หรือเขียน) ข้อมูลหากมันทำงานในเบราว์เซอร์ที่มีพฤติกรรมปกติ
thoutbeckers

@thebeckers คุณพูดถูกขอบคุณ ฉันแก้ไขคำตอบ แต่ออกจากวิธีการเพราะอาจยังมีประโยชน์
ตอนนี้

1
@ FrankankPuffelen จากสิ่งที่ฉันเข้าใจมันไม่ได้สร้างความแตกต่างใหญ่ แต่สามารถสร้างความรำคาญให้กับโควต้าของคุณได้มากขึ้นเล็กน้อยเนื่องจากในเบราว์เซอร์ที่ทำงานได้ดีคีย์ API ที่ให้บริการกับ HTML / JS จะทำงานตามที่ตั้งใจไว้ โดเมนและไม่ใช่โลคัลโฮสต์หรืออย่างอื่น แต่ฉันยอมรับว่าการป้องกันที่เพิ่มนั้นเป็นเพียงเล็กน้อยเมื่อเทียบกับสิ่งที่ Firebase มีอยู่แล้ว ฉันจะเดาคำตอบสำหรับสิ่งที่น่าทึ่งน้อยกว่า
ตอนนี้

22

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

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

ฉันอยากให้ไคลเอนต์ก่อนจะเข้าชมเว็บเซิร์ฟเวอร์ของคุณมากกว่านั้นคุณใส่อะไรไฟร์วอลล์มือแรก, captcha, cloudflare, ความปลอดภัยที่กำหนดเองในระหว่างไคลเอนต์และเซิร์ฟเวอร์หรือระหว่างเซิร์ฟเวอร์และ firebase และคุณดีไป อย่างน้อยคุณก็สามารถหยุดกิจกรรมที่ต้องสงสัยก่อนที่มันจะถึงกองเพลิง คุณจะมีความยืดหยุ่นมากขึ้น

ฉันเห็นสถานการณ์การใช้งานที่ดีเพียงข้อเดียวสำหรับการใช้การกำหนดค่าตามไคลเอ็นต์สำหรับการใช้งานภายใน ตัวอย่างเช่นคุณมีโดเมนภายในและคุณค่อนข้างมั่นใจว่าบุคคลภายนอกไม่สามารถเข้าถึงได้ดังนั้นคุณจึงสามารถตั้งค่าสภาพแวดล้อมเช่นเบราว์เซอร์ -> ประเภท firebase


10
แต่มันไม่เหมือนกับ "การเปิดเผย" REST API อื่น ๆ ใช่หรือไม่ ฉันหมายความว่า URL ของ REST API จะพร้อมใช้งานสำหรับผู้ใช้ พวกเขาสามารถใช้ URL เพื่อทำการร้องขอใด ๆ ที่พวกเขาต้องการและระบายโควต้าของคุณ สิ่งที่ firebase ทำคือการใช้การตั้งค่าด้วยคีย์ api เพื่อระบุส่วนของแบ็กเอนด์ของคุณและเป็นและจะต้องมีให้ผู้ใช้ทำการร้องขอ
mbochynski

3
@mbochynski แต่คุณสามารถทำการร้องขอโดยตรงไปยังแหล่งข้อมูลที่ทำให้คุณจ่ายบิล และที่ด้าน Firebase นั้นมีกลไกควบคุมไม่มากนักในการป้องกันการโจมตี DDoS เป็นต้นข้อเสนอแนะของฉันคือให้ลูกค้าของคุณโทรหา REST API ของคุณ แต่ REST API ควรเก็บคีย์ API ไว้เป็นส่วนตัวและก่อนที่คุณจะโจมตีทรัพยากร Firebase หากพวกเขาเป็นคำขอที่ถูกต้อง (ผ่าน Cloudflare ฯลฯ ) หรือดึงผลลัพธ์จากแคช จากนั้นคุณจะเข้าถึงทรัพยากร Firebase ของคุณเฉพาะในกรณีที่คุณต้องการ นี่คือสิ่งที่ฉันจะใช้firebase.google.com/docs/admin/setup
โทิโอแมน shipahi

3
การเปิดเผยคีย์ที่เบราว์เซอร์เป็นความคิดที่เลว ผู้ที่จะเขียนคู่มือ / บทความเหล่านี้พวกเขาคิดอะไรอยู่? http ผู้อ้างอิงเพื่อความปลอดภัย? ที่ปลอมแปลงได้ง่าย
Nick Chan Abdullah

1
พวกคุณไม่ได้คิดเรื่องนี้ อย่าคิดว่าคีย์ API เป็นความลับ ไม่ใช่รหัสส่วนตัวเป็นเพียง ID ดังนั้น Firebase API จึงรู้ว่าใครกำลังเข้าถึงโครงการใดบ้าง หากคุณต้องการความยืดหยุ่นอย่างมากและคุณต้องควบคุมทุกขั้นตอนของการโต้ตอบระหว่างเซิร์ฟเวอร์ / ไคลเอ็นต์จากนั้นคุณไม่ควรใช้ Firebase คุณควรใช้ GCP
forresthopkinsa

@forresthopkinsa ฉันมีลิงค์ด้านบนแสดงความคิดเห็นวิธีการใช้ ไม่มีใครในที่นี่ที่ไร้เดียงสามากพอที่จะแนะนำว่าเป็นกุญแจความลับเลย
Teoman shipahi

4

ฉันเชื่อว่าเมื่อกฎฐานข้อมูลถูกเขียนอย่างถูกต้องจะเพียงพอที่จะปกป้องข้อมูลของคุณ นอกจากนี้ยังมีแนวทางที่สามารถปฏิบัติตามโครงสร้างฐานข้อมูลของคุณได้ ตัวอย่างเช่นการสร้างโหนด UID ภายใต้ผู้ใช้และวางข้อมูลภายใต้ไว้ทั้งหมด หลังจากนั้นคุณจะต้องใช้กฎฐานข้อมูลอย่างง่ายดังต่อไปนี้

  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

ผู้ใช้รายอื่นจะไม่สามารถอ่านข้อมูลของผู้ใช้คนอื่นได้นอกจากนี้นโยบายโดเมนจะ จำกัด การร้องขอที่มาจากโดเมนอื่น หนึ่งสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ใน กฎความปลอดภัย Firebase


3

การเปิดเผยคีย์ API จะสร้างช่องโหว่เมื่อเปิดใช้งานการลงทะเบียนผู้ใช้ / รหัสผ่าน มีจุดปลายเปิด API ที่ใช้คีย์ API และอนุญาตให้ทุกคนสร้างบัญชีผู้ใช้ใหม่ได้ จากนั้นพวกเขาสามารถใช้บัญชีใหม่นี้เพื่อเข้าสู่แอปที่ได้รับการป้องกัน Firebase Auth ของคุณหรือใช้ SDK เพื่อรับรองความถูกต้องกับ user / pass และ run query

ฉันได้รายงานสิ่งนี้กับ Google แล้ว แต่พวกเขาบอกว่ามันทำงานได้ตามที่ตั้งใจ

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

ตัวอย่าง: MyUsers / {userId} / การเข้าถึง: 0

exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);

อัปเดตกฎของคุณเพื่ออนุญาตการอ่านสำหรับผู้ใช้ที่มีการเข้าถึง> 1 เท่านั้น

เมื่อมีโอกาสฟังก์ชั่นฟังไม่ปิดการใช้งานบัญชีเร็วพอจากนั้นกฎการอ่านจะป้องกันพวกเขาจากการอ่านข้อมูลใด ๆ


3

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

ฉันบันทึกผู้ใช้ของฉันใน DB ของฉันด้วย (และบันทึกข้อมูลโปรไฟล์ในนั้น) ดังนั้นฉันเพิ่งตั้งกฎ db เช่นนี้

".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"

วิธีนี้มีเพียงผู้ใช้ที่บันทึกไว้ก่อนหน้าเท่านั้นที่สามารถเพิ่มผู้ใช้ใหม่ในฐานข้อมูลดังนั้นจึงไม่มีวิธีที่ทุกคนที่ไม่มีบัญชีสามารถดำเนินการกับฐานข้อมูลได้ การเพิ่มผู้ใช้ใหม่จะทำได้ก็ต่อเมื่อผู้ใช้มีบทบาทพิเศษและแก้ไขโดยผู้ดูแลระบบหรือผู้ใช้นั้นเท่านั้น (เช่นนี้):

"userdata": {
  "$userId": {
    ".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
   ...

-2

คุณไม่ควรเปิดเผยข้อมูลนี้ ในที่สาธารณะคีย์พิเศษของ API มันอาจนำไปสู่การรั่วไหลของความเป็นส่วนตัว

ก่อนที่จะเผยแพร่เว็บไซต์คุณควรซ่อนมัน คุณสามารถทำได้ 2 วิธีขึ้นไป

  1. การเข้ารหัส / การซ่อนความซับซ้อน
  2. เพียงใส่รหัส SDK ของ firebase ที่ด้านล่างของเว็บไซต์หรือแอปของคุณดังนั้น firebase จะทำงานโดยอัตโนมัติ คุณไม่จำเป็นต้องใส่คีย์ API ทุกที่

1
ฉันอ้างอิงจาก Firebase "คัดลอกและวางสคริปต์เหล่านี้ลงที่ด้านล่างของแท็ก <body> ของคุณ แต่ก่อนที่คุณจะใช้บริการ Firebase" ซึ่งรวมถึงคีย์ API
Luke-zhang-04
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.