ส่วนขยายมีการเข้าถึงสิทธิพิเศษภายในเบราว์เซอร์ ทำให้เป็นเป้าหมายที่น่าสนใจสำหรับ ผู้โจมตีได้ หากส่วนขยายถูกบุกรุก ผู้ใช้ทุกคนของส่วนขยายนั้นจะมีช่องโหว่ การบุกรุกที่เป็นอันตรายและไม่พึงประสงค์ รักษาส่วนขยายให้ปลอดภัยและปกป้องผู้ใช้ด้วยการรวม แนวทางปฏิบัติเหล่านี้
ปกป้องบัญชีนักพัฒนาซอฟต์แวร์
ระบบจะอัปโหลดและอัปเดตโค้ดส่วนขยายผ่านบัญชี Google หากนักพัฒนาแอป บัญชี มีช่องโหว่ ผู้โจมตีอาจพุชโค้ดที่เป็นอันตรายไปยังผู้ใช้ทุกคนโดยตรง ปกป้องบัญชีเหล่านี้โดย สร้างบัญชีนักพัฒนาซอฟต์แวร์โดยเฉพาะ และเปิดใช้การตรวจสอบสิทธิ์แบบ 2 ปัจจัย ด้วยคีย์ความปลอดภัย
เลือกกลุ่มให้เหมาะสม
หากใช้การเผยแพร่เป็นกลุ่ม ให้จำกัดกลุ่มไว้เฉพาะนักพัฒนาซอฟต์แวร์ที่เชื่อถือได้ ไม่ยอมรับ คำขอเป็นสมาชิกจากบุคคลที่ไม่รู้จัก
ไม่ใช้ HTTP เลย
เมื่อขอหรือส่งข้อมูล ให้หลีกเลี่ยงการเชื่อมต่อ HTTP สมมติว่าการเชื่อมต่อ HTTP จะ ผู้สอดแนมหรือมีการปรับเปลี่ยน ควรเลือกใช้ HTTPS เสมอเนื่องจากมีในตัว ความปลอดภัยที่หลบเลี่ยงการโจมตีแบบแทรกกลางการสื่อสารส่วนใหญ่
ขอสิทธิ์ขั้นต่ำสุด
เบราว์เซอร์ Chrome จำกัดการเข้าถึงของส่วนขยายสำหรับสิทธิ์ของส่วนขยายที่มีการร้องขออย่างชัดแจ้งใน ไฟล์ Manifest ส่วนขยายควรย่อสิทธิ์ให้น้อยที่สุดโดยการลงทะเบียนเฉพาะ API และ เว็บไซต์ที่ตนใช้อยู่ ควรเก็บโค้ดที่กำหนดเองให้น้อยที่สุด
การจำกัดสิทธิ์สำหรับส่วนขยายจะจำกัดสิ่งที่ผู้ที่อาจเป็นผู้โจมตีจะแสวงหาประโยชน์ได้
XMLHttpRequest แบบข้ามต้นทาง
ส่วนขยายจะใช้ได้เฉพาะ XMLHttpRequest เพื่อรับทรัพยากรจากตัวเองและจากโดเมนเท่านั้น ที่ระบุไว้ในสิทธิ์
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"permissions": [
"/*",
"https://*.google.com/"
],
"manifest_version": 2
}
ส่วนขยายนี้ขอเข้าถึงทุกอย่างบน developer.chrome.com และโดเมนย่อยของ Google โดย
แสดง "/*"
และ "https://*google.com/"
ในสิทธิ์ หาก
ส่วนขยายถูกบุกรุก ส่วนขยายนั้นจะยังคงมีสิทธิ์โต้ตอบกับเว็บไซต์ที่เป็นไปตาม
รูปแบบการจับคู่ ผู้โจมตีจะไม่สามารถเข้าถึง "https://user_bank_info.com"
หรือ
โต้ตอบกับ "https://malicious_website.com"
จำกัดช่องไฟล์ Manifest
การใส่การลงทะเบียนที่ไม่จำเป็นในไฟล์ Manifest ทำให้เกิดช่องโหว่และสร้างส่วนขยาย มองเห็นได้มากขึ้น จำกัดช่องไฟล์ Manifest ให้เฉพาะที่ส่วนขยายใช้และให้ฟิลด์ที่เฉพาะเจาะจง การลงทะเบียน
เชื่อมต่อกับภายนอกได้
ใช้ช่อง externally_connectable
เพื่อประกาศส่วนขยายและหน้าเว็บภายนอกที่
จะแลกเปลี่ยนข้อมูลกับ จำกัดคนที่ส่วนขยายสามารถเชื่อมต่อด้วยภายนอก
แหล่งที่มาที่เชื่อถือได้
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"/*",
"https://*google.com/"
],
"accepts_tls_channel_id": false
},
...
}
แหล่งข้อมูลที่เข้าถึงได้ทางเว็บ
การทำให้ทรัพยากรเข้าถึงโดยอินเทอร์เน็ตได้ภายใต้web_accessible_resources
จะทำให้
ที่ตรวจจับได้โดยเว็บไซต์และผู้โจมตี
{
...
"web_accessible_resources": [
"images/*.png",
"style/secure_extension.css",
"script/secure_extension.js"
],
...
}
ยิ่งมีแหล่งข้อมูลที่เข้าถึงได้บนเว็บมากเท่าใด โอกาสที่ผู้โจมตีอาจใช้ประโยชน์จากได้มากขึ้นเท่านั้น เก็บ ไฟล์เหล่านี้น้อยที่สุด
ใส่นโยบายความปลอดภัยของเนื้อหาที่อาจไม่เหมาะสม
ระบุนโยบายรักษาความปลอดภัยเนื้อหาของส่วนขยายในไฟล์ Manifest เพื่อป้องกันการข้ามเว็บไซต์ การโจมตีด้วยสคริปต์ หากส่วนขยายโหลดเฉพาะทรัพยากรจากตัวมันเอง ให้ลงทะเบียนสิ่งต่อไปนี้
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self'"
"manifest_version": 2
}
หากส่วนขยายจำเป็นต้องรวมสคริปต์จากโฮสต์ที่เฉพาะเจาะจง ก็เพิ่มสคริปต์ดังกล่าวได้โดยทำดังนี้
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self' https://extension.resource.com"
"manifest_version": 2
}
หลีกเลี่ยง API ที่ดำเนินการได้
คุณควรแทนที่ API ที่ใช้โค้ดด้วยทางเลือกที่ปลอดภัยกว่า
document.write() และ teriorHTML
แม้ว่าการสร้างองค์ประกอบ HTML แบบไดนามิกด้วย document.write()
และ innerHTML
อาจง่ายกว่า
ส่วนขยายจะทิ้งส่วนขยายไว้ และหน้าเว็บที่ส่วนขยายเกี่ยวข้องจะพึ่งพิง โดยอนุญาตให้ผู้โจมตีแทรก
สคริปต์ที่เป็นอันตราย แต่ให้สร้างโหนด DOM ด้วยตนเองและใช้ innerText
เพื่อแทรกเนื้อหาแบบไดนามิก
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
eval()
หลีกเลี่ยงการใช้ eval()
ทุกครั้งที่ทำได้เพื่อป้องกันการโจมตี เนื่องจาก eval()
จะเรียกใช้โค้ดทั้งหมดที่ผ่าน
ลงไป ซึ่งอาจเป็นอันตรายได้
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + xhr.responseText + ")");
...
}
}
xhr.send();
แต่เลือกใช้วิธีการที่ปลอดภัยและรวดเร็วยิ่งขึ้น เช่น JSON.parse()
แทน
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(xhr.responseText);
}
}
xhr.send();
ใช้สคริปต์เนื้อหาอย่างระมัดระวัง
แม้ว่าสคริปต์เนื้อหาจะอยู่ในโลกที่โดดเดี่ยว แต่ก็จะไม่ได้รับภูมิคุ้มกันจากการโจมตี
- สคริปต์เนื้อหาเป็นเพียงส่วนเดียวของส่วนขยายที่โต้ตอบกับหน้าเว็บโดยตรง ด้วยเหตุนี้ หน้าเว็บที่ไม่เป็นมิตรอาจบิดเบือน DOM บางส่วนที่สคริปต์เนื้อหาที่อ้างอิงอยู่ หรือการแสวงหาประโยชน์จากพฤติกรรมมาตรฐานของเว็บที่ไม่คาดคิด เช่น รายการที่มีชื่อ
- ในการโต้ตอบกับ DOM หน้าเว็บ สคริปต์เนื้อหาจะต้องทำงานในกระบวนการแสดงผลแบบเดียวกับ หน้าเว็บนั้น ซึ่งทำให้สคริปต์เนื้อหาเสี่ยงต่อการรั่วไหลของข้อมูลเนื่องจากการโจมตีแบบ Side Channel (เช่น Spectre) และถูกผู้โจมตีบุกยึดหากหน้าเว็บที่เป็นอันตรายบุกรุก ของโหมดแสดงภาพ
งานที่มีความละเอียดอ่อนควรทำในกระบวนการเฉพาะ เช่น พื้นหลังของส่วนขยาย สคริปต์ หลีกเลี่ยงการแสดงสิทธิ์ของส่วนขยายแก่สคริปต์เนื้อหาโดยไม่ได้ตั้งใจ
- สมมติว่าข้อความจากสคริปต์เนื้อหาอาจสร้างขึ้นโดยผู้โจมตี (เช่น ตรวจสอบความถูกต้องและทำความสะอาดข้อมูลที่ป้อนทั้งหมดและปกป้องสคริปต์ของคุณจากการเขียนสคริปต์ข้ามเว็บไซต์)
- สมมติว่าข้อมูลที่ส่งไปยังสคริปต์เนื้อหาอาจรั่วไหลไปยังหน้าเว็บ อย่าส่งข้อมูลที่ละเอียดอ่อน (เช่น ข้อมูลลับจากส่วนขยาย ข้อมูลจากแหล่งที่มาเว็บอื่นๆ ประวัติการท่องเว็บ) ไปจนถึงเนื้อหา สคริปต์
- จำกัดขอบเขตของการดำเนินการที่มีสิทธิ์ซึ่งสามารถทริกเกอร์โดยสคริปต์เนื้อหา ไม่อนุญาต
สคริปต์เนื้อหาเพื่อทริกเกอร์คำขอไปยัง URL ที่กำหนดเองหรือส่งอาร์กิวเมนต์ที่กำหนดเองไปยัง
API ส่วนขยาย (เช่น ไม่อนุญาตให้ส่ง URL ที่กำหนดเองไปยัง
fetch
หรือchrome.tabs.create
API)
ลงทะเบียนและแก้ไขอินพุต
ป้องกันส่วนขยายจากสคริปต์ที่เป็นอันตรายโดยจำกัด Listener ไว้เฉพาะสิ่งที่ส่วนขยายเป็น คาดหวัง ตรวจสอบผู้ส่งข้อมูลที่เข้ามา และตรวจสอบอินพุตทั้งหมด
ส่วนขยายควรลงทะเบียนสำหรับ runtime.onRequestExternal
เท่านั้นในกรณีที่คาดว่าจะได้รับ
การสื่อสารจากเว็บไซต์หรือส่วนขยายภายนอก ตรวจสอบให้แน่ใจเสมอว่าผู้ส่งตรงกับ
เป็นแหล่งข้อมูลที่เชื่อถือได้
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
แม้กระทั่งข้อความผ่านเหตุการณ์ runtime.onMessage จากส่วนขยายก็ต้องได้รับการตรวจสอบ ตรวจสอบว่า MessageSender ไม่ได้มาจากสคริปต์เนื้อหาที่ถูกบุกรุก
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});
ป้องกันไม่ให้ส่วนขยายเรียกใช้สคริปต์ของผู้โจมตีด้วยการตรวจสอบความถูกต้องของอินพุตของผู้ใช้และขาเข้า แม้แต่จากส่วนขยายเองและแหล่งที่มาที่ได้รับอนุมัติ หลีกเลี่ยงการใช้ API ที่ดำเนินการได้
function sanitizeInput(input) {
return input.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"');
}