บล็อกโพสต์นี้เกี่ยวข้องกับการใช้งานการสนับสนุนของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์เพื่อแก้ไขข้อบกพร่องเกี่ยวกับนโยบายรักษาความปลอดภัยเนื้อหา (CSP) ด้วยความช่วยเหลือจากแท็บปัญหาที่เพิ่งเปิดตัว
เราได้ดำเนินการติดตั้งใช้งานในการฝึกงาน 2 ระยะ ดังนี้ 1. ในช่วงแรก เราได้สร้างเฟรมเวิร์กการรายงานทั่วไปและออกแบบข้อความปัญหาสำหรับการละเมิด CSP 3 รายการ 2. ในครั้งที่ 2 เราได้เพิ่มปัญหาประเภท Trusted ควบคู่ไปกับฟีเจอร์พิเศษสำหรับเครื่องมือสำหรับนักพัฒนาเว็บบางส่วนสำหรับการแก้ไขข้อบกพร่อง Trusted Types
นโยบายรักษาความปลอดภัยเนื้อหาคืออะไร
นโยบายรักษาความปลอดภัยเนื้อหา (CSP) อนุญาตให้จํากัดลักษณะการทํางานบางอย่างในเว็บไซต์เพื่อเพิ่มความปลอดภัย ตัวอย่างเช่น คุณสามารถใช้ CSP เพื่อไม่อนุญาตให้ใช้สคริปต์ในบรรทัดหรือไม่อนุญาตให้ใช้ eval
ซึ่งทั้ง 2 อย่างช่วยลดพื้นที่การโจมตีสำหรับการโจมตีด้วย Cross-site Scripting (XSS) อ่านข้อมูลเบื้องต้นโดยละเอียดเกี่ยวกับ CSP ได้ที่นี่
CSP ใหม่ที่โดดเด่นเป็นพิเศษคือนโยบาย Trusted Types(TT) ซึ่งเปิดใช้การวิเคราะห์แบบไดนามิกที่ป้องกันได้แบบเป็นระบบจากการโจมตีด้วยการแทรกข้อมูลในเว็บไซต์ได้หลายประเภท ด้วยเหตุนี้ TT จึงสนับสนุนเว็บไซต์ในการควบคุมโค้ด JavaScript เพื่ออนุญาตให้มีการกำหนดสิ่งบางประเภทให้กับซิงก์ DOM เช่น teriorHTML
เว็บไซต์สามารถเปิดใช้งานนโยบายรักษาความปลอดภัยเนื้อหาได้โดยใส่ส่วนหัว HTTP ที่เฉพาะเจาะจง เช่น ส่วนหัว content-security-policy: require-trusted-types-for 'script'; trusted-types default
จะเปิดใช้งานนโยบาย TT สําหรับหน้าเว็บ
แต่ละนโยบายจะทำงานได้ในโหมดใดโหมดหนึ่งต่อไปนี้
- โหมดบังคับใช้ - การละเมิดนโยบายทุกรายการถือเป็นข้อผิดพลาด
- โหมดรายงานเท่านั้น - ซึ่งรายงานข้อความแสดงข้อผิดพลาดเป็นคําเตือน แต่ไม่ทําให้หน้าเว็บเกิดข้อผิดพลาด
การใช้นโยบายรักษาความปลอดภัยเนื้อหาในแท็บปัญหา
เป้าหมายของการทำงานนี้คือการปรับปรุงประสบการณ์การแก้ไขข้อบกพร่องสำหรับปัญหา CSP เมื่อพิจารณาปัญหาใหม่ ทีม DevTools จะดำเนินการตามกระบวนการโดยคร่าวๆ ดังนี้
- การอธิบายเรื่องราวของผู้ใช้ ระบุชุดเรื่องราวของผู้ใช้ในฟรอนท์เอนด์ของเครื่องมือสำหรับนักพัฒนาเว็บ ซึ่งครอบคลุมวิธีที่นักพัฒนาเว็บจะต้องตรวจสอบปัญหา
- การใช้งานส่วนหน้า ระบุข้อมูลที่จำเป็นในการตรวจสอบปัญหาในฝั่งไคลเอ็นต์ (เช่น คำขอที่เกี่ยวข้อง ชื่อคุกกี้ บรรทัดในสคริปต์หรือไฟล์ html ฯลฯ) โดยอิงตาม User Story
- การตรวจหาปัญหา ระบุตําแหน่งในเบราว์เซอร์ที่ตรวจพบปัญหาใน Chrome และเครื่องมือตําแหน่งเพื่อรายงานปัญหาพร้อมข้อมูลที่เกี่ยวข้องจากขั้นตอนที่ (2)
- บันทึกและแสดงปัญหา จัดเก็บปัญหาไว้ในตำแหน่งที่เหมาะสมและทำให้เครื่องมือสำหรับนักพัฒนาเว็บเข้าถึงได้เมื่อเปิดขึ้น
- การออกแบบข้อความปัญหา เขียนข้อความอธิบายที่จะช่วยให้นักพัฒนาเว็บเข้าใจ และที่สำคัญคือแก้ไขปัญหาได้
ขั้นตอนที่ 1: การระบุเรื่องราวของผู้ใช้สำหรับปัญหา CSP
ก่อนเริ่มใช้งาน เราได้สร้างเอกสารการออกแบบพร้อมสตอรี่ผู้ใช้เพื่อให้เข้าใจสิ่งที่ต้องทำมากขึ้น ตัวอย่างเช่น เราได้เขียนสตอรี่ผู้ใช้ต่อไปนี้
ในฐานะนักพัฒนาซอฟต์แวร์ เพิ่งรู้ว่าบางส่วนของเว็บไซต์ถูกบล็อก ฉันอยากจะดำเนินการดังนี้- - ...ดูว่า CSP เป็นสาเหตุที่ทำให้ iframe / รูปภาพถูกบล็อกในเว็บไซต์ของฉันหรือไม่ - ...ดูว่าคำสั่ง CSP ใดทำให้ทรัพยากรบางอย่างถูกบล็อก - ...รู้วิธีเปลี่ยน CSP ของเว็บไซต์เพื่ออนุญาตให้แสดงทรัพยากรที่ถูกบล็อกอยู่ / การเรียกใช้ JavaScript ที่ถูกบล็อกอยู่ในปัจจุบัน
ในการสำรวจเรื่องราวผู้ใช้นี้ เราสร้างหน้าเว็บตัวอย่างง่ายๆ ที่แสดงการละเมิด CSP ที่เราสนใจ และสำรวจหน้าตัวอย่างเพื่อทำความคุ้นเคยกับกระบวนการด้วยตนเอง ตัวอย่างหน้าเว็บบางส่วนมีดังนี้ (เปิดการสาธิตโดยเปิดแท็บปัญหาไว้)
จากการใช้กระบวนการนี้ เราพบว่าตำแหน่งแหล่งที่มาเป็นข้อมูลที่สำคัญที่สุดสำหรับการแก้ไขข้อบกพร่อง CSP นอกจากนี้ เราพบว่าการค้นหา iframe และคำขอที่เกี่ยวข้องอย่างรวดเร็วในกรณีที่มีการบล็อกทรัพยากรนั้นมีประโยชน์ และลิงก์โดยตรงไปยังองค์ประกอบ HTML ในแผงองค์ประกอบของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ก็มีประโยชน์เช่นกัน
ขั้นตอนที่ 2: การติดตั้งใช้งานส่วนหน้า
เรานําข้อมูลเชิงลึกนี้มาร่างเป็นข้อมูลฉบับร่างแรกที่ต้องการให้พร้อมใช้งานในเครื่องมือสําหรับนักพัฒนาเว็บผ่านโปรโตคอลเครื่องมือสําหรับนักพัฒนาเว็บใน Chrome (CDP) ดังนี้
ด้านล่างนี้เป็นข้อความที่ตัดตอนมาจาก third_party/blink/public/devtools_protocol/browser_protocol.pdl
type ContentSecurityPolicyIssueDetails extends object
properties
# The url not included in allowed sources.
optional string blockedURL
# Specific directive that is violated, causing the CSP issue.
string violatedDirective
boolean isReportOnly
ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
optional AffectedFrame frameAncestor
optional SourceCodeLocation sourceCodeLocation
optional DOM.BackendNodeId violatingNodeId
คําจํากัดความข้างต้นจะเข้ารหัสโครงสร้างข้อมูล JSON การเขียนด้วยภาษาง่ายๆ เรียกว่า PDL (ภาษาของข้อมูลโปรโตคอล) PDL มีไว้เพื่อวัตถุประสงค์ 2 อย่าง ก่อนอื่น เราใช้ PDL เพื่อสร้างคําจํากัดความ TypeScript ที่ส่วนหน้าของ DevTools ต้องใช้ ตัวอย่างเช่น คําจํากัดความ PDL ข้างต้นจะสร้างอินเทอร์เฟซ TypeScript ดังต่อไปนี้
export interface ContentSecurityPolicyIssueDetails {
/**
* The url not included in allowed sources.
*/
blockedURL?: string;
/**
* Specific directive that is violated, causing the CSP issue.
*/
violatedDirective: string;
isReportOnly: boolean;
contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
frameAncestor?: AffectedFrame;
sourceCodeLocation?: SourceCodeLocation;
violatingNodeId?: DOM.BackendNodeId;
}
ประการที่สอง และที่สำคัญกว่านั้นคือ เราสร้างไลบรารี C++ จากคำจำกัดความที่จัดการการสร้างและส่งโครงสร้างข้อมูลเหล่านี้จากแบ็กเอนด์ C++ Chromium ไปยังฟรอนท์เอนด์ของเครื่องมือสำหรับนักพัฒนาเว็บ เมื่อใช้ไลบรารีดังกล่าว คุณสามารถสร้างออบเจ็กต์ ContentSecurityPolicyIssueDetails
โดยใช้โค้ด C++ ต่อไปนี้
protocol::Audits::ContentSecurityPolicyIssueDetails::create()
.setViolatedDirective(d->violated_directive)
.setIsReportOnly(d->is_report_only)
.setContentSecurityPolicyViolationType(BuildViolationType(
d->content_security_policy_violation_type)))
.build();
เมื่อตัดสินใจได้แล้วว่าจะเปิดเผยข้อมูลใดบ้าง เราจึงต้องหาแหล่งที่มาของข้อมูลนี้จาก Chromium
ขั้นตอนที่ 3: การตรวจหาปัญหา
เราต้องค้นหาตำแหน่งที่มีข้อมูลจริงในแบ็กเอนด์เพื่อให้ Chrome DevTools Protocol (CDP) ใช้งานได้ในรูปแบบที่อธิบายไว้ในส่วนที่แล้ว โชคดีที่โค้ด CSP มีจุดคอขวดที่ใช้สำหรับโหมดรายงานเท่านั้นอยู่แล้ว ซึ่งเราใช้เพื่อเชื่อมต่อกับ ContentSecurityPolicy::ReportViolation
ที่รายงานปัญหาไปยังปลายทางการรายงาน (ไม่บังคับ) ซึ่งกำหนดค่าได้ในส่วนหัว HTTP ของ CSP ข้อมูลส่วนใหญ่ที่เราต้องการรายงานนั้นพร้อมใช้งานอยู่แล้ว ดังนั้น เราจึงไม่มีการเปลี่ยนแปลงครั้งใหญ่ในส่วนหลังเพื่อให้เครื่องมือของเราทำงานได้
ขั้นตอนที่ 4: บันทึกและแสดงปัญหา
ความซับซ้อนเล็กน้อยคือเราต้องการรายงานปัญหาที่เกิดขึ้นก่อนที่จะเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ด้วย ซึ่งคล้ายกับวิธีจัดการข้อความคอนโซล ซึ่งหมายความว่าเราจะไม่รายงานปัญหาไปยังส่วนหน้าทันที แต่จะใช้พื้นที่เก็บข้อมูลที่มีข้อมูลปัญหาไม่ว่าจะเปิดเครื่องมือสำหรับนักพัฒนาเว็บอยู่หรือไม่ก็ตาม เมื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บแล้ว (หรือในกรณีที่มีไคลเอ็นต์ CDP อื่นๆ แนบอยู่) คุณจะเล่นปัญหาที่บันทึกไว้ก่อนหน้านี้ทั้งหมดซ้ำได้จากพื้นที่เก็บข้อมูล
การดำเนินการนี้ถือเป็นการสิ้นสุดงานแบ็กเอนด์ และตอนนี้เราต้องมุ่งเน้นที่วิธีแสดงปัญหาในหน้าเว็บ
ขั้นตอนที่ 5: การออกแบบข้อความปัญหา
การออกแบบข้อความปัญหาเป็นกระบวนการที่ดึงดูดความสนใจจากหลายทีมนอกเหนือจากทีมของเราเอง เช่น เรามักใช้ข้อมูลเชิงลึกจากทีมที่ติดตั้งใช้งานฟีเจอร์ (ในกรณีนี้คือทีม CSP) และแน่นอน ทีม DevRel ซึ่งออกแบบวิธีที่นักพัฒนาเว็บควรจัดการกับปัญหาบางประเภท ข้อความปัญหามักจะได้รับการขัดเกลาจนกว่าจะเสร็จสมบูรณ์
โดยปกติแล้วทีม DevTools จะเริ่มด้วยฉบับร่างคร่าวๆ ของสิ่งที่จินตนาการไว้ ดังนี้
## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site
## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.
Usage of content from not included sources is restricted to strengthen the security of your entire site.
## Specific information
### VIOLATED DIRECTIVES
`img-src 'self'`
### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg
## Specific information
https://web.dev/strict-csp/
หลังจากทำซ้ำแล้ว เราจึงได้ข้อสรุปดังนี้
จะเห็นได้ว่าการรวมทีมฟีเจอร์และ DevRel ทำให้คำอธิบายชัดเจนและแม่นยำขึ้นมาก
นอกจากนี้ คุณยังดูปัญหา CSP ในหน้าเว็บได้ในแท็บเฉพาะสำหรับการละเมิด CSP
การแก้ไขข้อบกพร่องของ Trusted Types
การทำงานกับ TT จำนวนมากอาจเป็นเรื่องยากหากไม่มีเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ที่เหมาะสม
การพิมพ์คอนโซลที่ปรับปรุงแล้ว
เมื่อเราทำงานกับออบเจ็กต์ที่เชื่อถือ เราต้องการแสดงข้อมูลในจำนวนที่เท่ากับออบเจ็กต์ที่ไม่น่าเชื่อถือเป็นอย่างน้อย ขออภัย ปัจจุบันเมื่อแสดงออบเจ็กต์ที่เชื่อถือได้ ระบบจะไม่แสดงข้อมูลเกี่ยวกับออบเจ็กต์ที่รวมไว้
เนื่องจากค่าที่แสดงในคอนโซลนั้นมาจากการเรียกใช้ .valueOf()
บนออบเจ็กต์โดยค่าเริ่มต้น แต่ในกรณีของ Trusted Type ค่าที่ส่งคืนจะไม่มีประโยชน์มากนัก เราอยากได้สินค้าที่คล้ายกันกับสิ่งที่คุณได้รับเมื่อโทรหา .toString()
ด้วยเหตุนี้ เราจึงต้องแก้ไข V8 และ Blink เพื่อใช้การจัดการพิเศษสำหรับออบเจ็กต์ประเภทที่เชื่อถือได้
แม้ว่าการจัดการที่กําหนดเองนี้จะทำใน V8 เนื่องด้วยเหตุผลทางประวัติศาสตร์ แต่แนวทางดังกล่าวมีข้อเสียที่สำคัญ ออบเจ็กต์จํานวนมากที่จําเป็นต้องแสดงแบบกําหนดเอง แต่มีประเภทเหมือนกันที่ระดับ JS เนื่องจาก V8 เป็น JS เท่านั้น จึงไม่สามารถแยกความแตกต่างของแนวคิดที่สอดคล้องกับ Web API เช่น Trusted Type ได้ ด้วยเหตุนี้ V8 จึงต้องขอความช่วยเหลือจากผู้ฝัง (Blink) เพื่อแยกความแตกต่าง
ดังนั้น การย้ายโค้ดส่วนนั้นไปยัง Blink หรือเครื่องมือฝังใดๆ จึงดูเหมือนเป็นทางเลือกที่สมเหตุสมผล นอกจากปัญหาที่เปิดเผยแล้ว ยังมีประโยชน์อื่นๆ อีกมากมาย ดังนี้
- ผู้ฝังแต่ละรายสามารถสร้างคำอธิบายของตนเองได้
- การสร้างคำอธิบายผ่าน Blink API นั้นง่ายกว่ามาก
- Blink มีสิทธิ์เข้าถึงคําจํากัดความเดิมของออบเจ็กต์ ดังนั้นหากเราใช้
.toString()
เพื่อสร้างคำอธิบาย ก็ไม่มีความเสี่ยงที่.toString()
อาจถูกกำหนดใหม่
หยุดเมื่อตรวจพบการละเมิด (ในโหมดรายงานเท่านั้น)
ปัจจุบันวิธีเดียวในการแก้ไขข้อบกพร่องการละเมิด TT คือการตั้งจุดหยุดพักในการยกเว้น JS เนื่องจากการละเมิด TT ที่บังคับใช้จะทำให้เกิดข้อยกเว้น ฟีเจอร์นี้จึงมีประโยชน์บางประการ อย่างไรก็ตาม ในสถานการณ์จริง คุณจำเป็นต้องมีการควบคุมการละเมิด TT ที่ละเอียดยิ่งขึ้น โดยเฉพาะอย่างยิ่ง เราต้องการหยุดการเผยแพร่เฉพาะในกรณีที่มีการละเมิด TT (ไม่ใช่ข้อยกเว้นอื่นๆ) หยุดการเผยแพร่ในโหมดรายงานเท่านั้น และแยกความแตกต่างระหว่างการละเมิด TT ประเภทต่างๆ
DevTools รองรับจุดหยุดพักที่หลากหลายอยู่แล้ว สถาปัตยกรรมจึงขยายได้ค่อนข้างมาก การเพิ่มประเภทจุดหยุดพักใหม่ต้องมีการเปลี่ยนแปลงในแบ็กเอนด์ (Blink), CDP และฟีดหน้า
เราควรเปิดตัวคําสั่ง CDP ใหม่ เรียกว่า setBreakOnTTViolation
ฟรอนต์เอนด์จะใช้คำสั่งนี้เพื่อบอกแบ็กเอนด์ว่าควรหยุดการละเมิด TT ประเภทใด แบ็กเอนด์ โดยเฉพาะ InspectorDOMDebuggerAgent
จะจัดหา "โปรบ" onTTViolation()
ที่จะเรียกใช้ทุกครั้งที่มีการละเมิด TT จากนั้น InspectorDOMDebuggerAgent
จะตรวจสอบว่าควรเรียกจุดหยุดพักให้แสดงหรือไม่ และหากใช่ ก็จะส่งข้อความไปยังส่วนหน้าเพื่อหยุดการดําเนินการชั่วคราว
สิ่งที่ทําเสร็จแล้วและสิ่งที่ต้องทำต่อไป
นับตั้งแต่มีการเปิดตัวปัญหาที่อธิบายไว้ที่นี่ แท็บปัญหาก็เปลี่ยนแปลงไปมากพอสมควร ดังนี้
- เราได้ปรับปรุงการเชื่อมโยงกับแผงอื่นๆ ในเครื่องมือสำหรับนักพัฒนาเว็บ
- เราได้ย้ายรายงานปัญหาอื่นๆ ไปยังแท็บปัญหาแล้ว ซึ่งได้แก่ คอนทราสต์ต่ำ กิจกรรมบนเว็บที่เชื่อถือได้ โหมดที่ไม่มาตรฐาน API การรายงานการระบุแหล่งที่มา และปัญหาเกี่ยวกับ CORS เป็นต้น
- เพิ่มตัวเลือกในการซ่อนปัญหา
นับจากนี้ไป เราวางแผนที่จะใช้แท็บปัญหาเพื่อแสดงปัญหาเพิ่มเติม ซึ่งจะช่วยให้สามารถยกเลิกการโหลดคอนโซลจากขั้นตอนข้อความแสดงข้อผิดพลาดที่อ่านไม่ออกได้ในระยะยาว
ดาวน์โหลดแชแนลตัวอย่าง
ลองใช้ Chrome Canary, Dev หรือเบต้าเป็นเบราว์เซอร์เริ่มต้นสำหรับการพัฒนา ช่องทางเวอร์ชันตัวอย่างเหล่านี้จะช่วยให้คุณเข้าถึงฟีเจอร์ล่าสุดของ DevTools, ทดสอบ API ของแพลตฟอร์มเว็บที่ล้ำสมัย และช่วยคุณค้นหาปัญหาในเว็บไซต์ได้ก่อนที่ผู้ใช้จะพบ
ติดต่อทีมเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
ใช้ตัวเลือกต่อไปนี้เพื่อพูดคุยเกี่ยวกับฟีเจอร์ใหม่ การอัปเดต หรือสิ่งอื่นๆ ที่เกี่ยวข้องกับเครื่องมือสำหรับนักพัฒนาเว็บ
- ส่งความคิดเห็นและคำขอฟีเจอร์ถึงเราได้ที่ crbug.com
- รายงานปัญหาเกี่ยวกับเครื่องมือสำหรับนักพัฒนาเว็บโดยใช้ตัวเลือกเพิ่มเติม > ความช่วยเหลือ > รายงานปัญหาเกี่ยวกับเครื่องมือสำหรับนักพัฒนาเว็บในเครื่องมือสำหรับนักพัฒนาเว็บ
- ทวีตถึง @ChromeDevTools
- แสดงความคิดเห็นในวิดีโอ YouTube เกี่ยวกับข่าวสารใน DevTools หรือวิดีโอ YouTube เกี่ยวกับเคล็ดลับใน DevTools