การทำความเข้าใจความสมบูรณ์ของทรัพยากรย่อย

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ JavaScript ทุกบิตที่คุณเพิ่มลงในไซต์เป็นวิธีที่เป็นไปได้สำหรับแฮ็กเกอร์ สิ่งนี้เป็นจริงเป็นสองเท่าหาก JavaScript นั้นโฮสต์โดยบุคคลอื่น เช่น บน CDN สาธารณะ ความสมบูรณ์ของทรัพยากรย่อยเป็นคุณลักษณะของเบราว์เซอร์ที่คุณสามารถใช้เพื่อให้แน่ใจว่ารหัสที่ใช้นั้นตรงกับที่คุณต้องการ

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

ขยะทั้งหมดนั้นเป็นคุณลักษณะด้านความปลอดภัยที่มีประโยชน์จริงๆ ซึ่งเรียกว่า Subresource Integrity (SRI) ที่สามารถช่วยปกป้องไซต์ของคุณจากการแฮ็กและการประนีประนอมบางประเภท ในบทความนี้ เราจะมาดูกันว่า SRI คืออะไร สามารถช่วยปกป้องคุณได้อย่างไร และคุณจะเริ่มต้นใช้งาน SRI ในโครงการของคุณได้อย่างไร ไม่ใช่แค่สำหรับไฟล์ที่โฮสต์บน CDN

บิตของประวัติศาสตร์

ย้อนกลับไปในสมัยที่ JavaScript เป็นลูกพี่ลูกน้องที่ยากจนกว่า HTML และ CSS เราไม่ต้องคิดมากว่าสคริปต์ของเราสามารถใช้เป็นเวกเตอร์โจมตีสำหรับเว็บไซต์ของเราได้อย่างไร ไซต์ส่วนใหญ่ทั้งหมดโฮสต์อยู่บนเซิร์ฟเวอร์จริงเพียงแห่งเดียวบนโครงสร้างพื้นฐานการโฮสต์ของเราเอง และเป็นเซิร์ฟเวอร์ที่เราคิดว่าจะปกป้องเมื่อกล่าวถึงแนวทางปฏิบัติด้านความปลอดภัยที่ดีที่สุด

เมื่อเบราว์เซอร์มีความสามารถมากขึ้นและการเชื่อมต่อเน็ตก็เพิ่มมากขึ้น เราจึงเริ่มใช้ JavaScript มากขึ้นเรื่อยๆ และในที่สุด ไลบรารี JavaScript ที่นำกลับมาใช้ใหม่ได้ก็เริ่มผุดขึ้นมา ในช่วงแรกๆ นั้น ไลบรารีต่างๆ เช่น script.aculo.us, Prototype และในที่สุด jQuery เริ่มได้รับการยอมรับในหมู่นักพัฒนาที่ต้องการเพิ่มการโต้ตอบในหน้าเว็บของตน

ด้วยไลบรารีที่เพิ่มเหล่านี้และปลั๊กอินที่ตามมาทำให้น้ำหนักหน้าเพิ่มขึ้น และไม่นานเราก็เริ่มคิดอย่างจริงจังเกี่ยวกับประสิทธิภาพของส่วนหน้า แหล่งข้อมูลเช่น Content Delivery Networks (CDNs) ที่เคยสงวนไว้ของบริษัทยักษ์ใหญ่ กลายเป็นเรื่องธรรมดาสำหรับการสร้างเว็บไซต์ที่ฉับไว

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

ระหว่างทาง จุดประกายสว่างสดใสสังเกตเห็นว่าไซต์ต่าง ๆ ต่างขอสำเนาไลบรารีทั่วไปของตนเอง — เช่น jQuery ล่าสุด — และหากมีเวอร์ชัน CDN ทั่วไปของไลบรารีเหล่านั้นที่ทุกไซต์สามารถใช้ได้ ผู้ใช้ก็จะ' ไม่จำเป็นต้องดาวน์โหลดไฟล์เดิมต่อไป พวกเขาต้องการโจมตีไซต์แรกเพื่อใช้ไฟล์ แต่จากนั้นก็จะนั่งอยู่ในแคชของเบราว์เซอร์ในเครื่องและสามารถข้ามการดาวน์โหลดสำหรับแต่ละไซต์ที่ตามมาได้ อัจฉริยะ!

นี่คือเหตุผลที่คุณจะเห็นลิงก์ CDN สำหรับไลบรารีโปรดของคุณโดยใช้ URL เช่น jsdelivr.com ซึ่งใช้ CDN ทั่วไปเพื่อโฮสต์ไฟล์ เพื่อให้ผู้ใช้เห็นประโยชน์ด้านประสิทธิภาพ

อะไรจะผิดพลาดได้?

วิธีนี้ยังคงเป็นวิธีที่ดีและใช้งานได้จริง แต่จะแนะนำเวกเตอร์ที่มีศักยภาพสำหรับการโจมตี ลองนึกภาพว่าเป็นปี 2012 และทุกคนกำลังใช้ jQuery 1.8 ใหม่ล่าสุด กลับมาพร้อมกับวิธีการทำสิ่งต่างๆ แบบเดิมๆ ทุกคนจะมีไฟล์ jQuery 1.8 ของตัวเองที่โฮสต์โดยเป็นส่วนหนึ่งของเว็บไซต์ของตนเองบนเซิร์ฟเวอร์ของตนเอง

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

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

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

ป้อนความสมบูรณ์ของทรัพยากรย่อย

แทนที่จะย้อนเวลากลับไปและละทิ้งวิธีที่เป็นประโยชน์ในการใช้โค้ด SRI เป็นโซลูชันที่เพิ่มระดับการรักษาความปลอดภัยที่เรียบง่าย สิ่งที่ SRI และแอตทริบิวต์ integrity ทำคือต้องแน่ใจว่าไฟล์ที่คุณเชื่อมโยงไปยังเพจจะไม่เปลี่ยนแปลง และถ้ามันเปลี่ยนแปลง เบราว์เซอร์ก็จะปฏิเสธมัน

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

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

เมื่อใช้ SRI หน้าเว็บของคุณจะเก็บแฮชและเซิร์ฟเวอร์ (CDN หรือที่ใดก็ได้) จะเก็บไฟล์ไว้ เบราว์เซอร์ดาวน์โหลดไฟล์ จากนั้นจึงคำนวณอย่างรวดเร็วเพื่อให้แน่ใจว่าตรงกับแฮชในแอตทริบิวต์ integrity หากตรงกับไฟล์ที่ใช้และหากไม่ถูกบล็อก

ลองเลย

ถ้าฉันไปที่ getbootstrap.com วันนี้เพื่อรับลิงก์ CDN ไปยังเวอร์ชันของ Bootstrap ฉันได้รับแท็กที่มีลักษณะดังนี้:

 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

คุณจะเห็นว่าแอตทริบิวต์ src เป็นแบบที่เราคุ้นเคย และแอตทริบิวต์ integrity ถือสิ่งที่เรารู้ในขณะนี้ว่าเป็นแฮช

แฮชจริงๆ แล้วแบ่งเป็นสองส่วน อย่างแรกคือคำนำหน้าเพื่อประกาศว่าจะใช้อัลกอริทึมการแฮชใด ในกรณีนี้คือ sha384 ตามด้วยเส้นประแล้วแฮชเองซึ่งเข้ารหัสด้วย base64

คุณอาจคุ้นเคยกับ base64 ในการเข้ารหัสไฟล์แบบอินไลน์ เช่น รูปภาพลงในเพจ ไม่ใช่กระบวนการเข้ารหัส แต่เป็นวิธีที่ง่ายและรวดเร็วในการเข้ารหัสข้อมูลที่อาจยุ่งเหยิงในลักษณะที่แปลเป็น ASCII ได้อย่างเรียบร้อย ด้วยเหตุนี้จึงมีการใช้เว็บเป็นจำนวนมาก

เมื่อเห็นสิ่งนี้ เบราว์เซอร์จะดาวน์โหลด bootstrap.min.js ก่อนดำเนินการ มันจะถอดรหัส base64 แฮช แล้วใช้อัลกอริธึมการแฮช sha384 เพื่อยืนยันว่าแฮชตรงกับไฟล์ที่เพิ่งดาวน์โหลด หากตรงกัน ไฟล์จะถูกดำเนินการ

ฉันสามารถทดสอบได้โดยใส่แท็กนั้นในหน้า จากนั้นพลิกไปที่แท็บเครือข่ายในเครื่องมือเบราว์เซอร์เพื่อดูว่าไฟล์ถูกโหลดแล้ว

แท็บเครือข่าย
(ตัวอย่างขนาดใหญ่)

ฉันเห็นว่า bootstrap.min.js (และไฟล์ jQuery ที่ต้องการด้วย) โหลดสำเร็จแล้ว

มาดูกันว่าจะเกิดอะไรขึ้นหากฉันอัปเดตแฮชเป็นสิ่งที่ฉันรู้ว่าไม่ถูกต้อง

 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-SmashingMagazineIsCoolForCats" crossorigin="anonymous"></script> 
กัญชา
(ตัวอย่างขนาดใหญ่)

อย่างที่คุณเห็น แฮชที่ระบุในหน้าของฉันไม่ตรงกับไฟล์อีกต่อไป ไฟล์จึงถูกบล็อก

การใช้ SRI ในโครงการของคุณเอง

การมีความสามารถนี้สำหรับไลบรารีบน CDN นั้นยอดเยี่ยม และหากคุณเห็นตัวเลือกในการใช้ไฟล์ที่ฝังตัวที่มีแอตทริบิวต์ integrity คุณควรเลือกใช้ตัวเลือกนั้นแทน แต่ไม่จำกัดเฉพาะโปรเจ็กต์ขนาดใหญ่บน CDN คุณสามารถใช้สิ่งนี้กับไซต์ของคุณเองได้

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

SRI สามารถปกป้องคุณจากสิ่งนี้ได้เช่นกัน หากคุณสร้างแฮชความสมบูรณ์สำหรับไฟล์ของคุณเอง คุณสามารถให้ไซต์ของคุณปฏิเสธการเปลี่ยนแปลงใดๆ ได้เช่นเดียวกับที่ทำกับไฟล์ที่โฮสต์จากระยะไกล

กำลังสร้างแฮช

อย่างที่คาดไว้ คุณสามารถรันคำสั่งบางอย่างที่เทอร์มินัลของคอมพิวเตอร์ของคุณเพื่อสร้างแฮชสำหรับไฟล์ ตัวอย่างวิธีการดำเนินการดังกล่าวมาจากหน้า MDN Subresource Integrity:

 cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A

นั่นคือการรับเนื้อหาของ FILENAME.js และส่งผ่านเป็นอินพุตไปยัง openssl เพื่อสร้างไดเจสต์โดยใช้ sha384 ซึ่งจะถูกส่งต่อเป็นอินพุตไปยังคำสั่ง openssl อื่นเพื่อเข้ารหัส base64 ผลลัพธ์ ไม่เพียงแต่จะซับซ้อนและคลุมเครือเท่านั้น แต่ยังไม่ใช่สิ่งที่คุณต้องการทำด้วยมือทุกครั้งที่ไฟล์ JavaScript ของคุณเปลี่ยนแปลง

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

หากคุณใช้ Gulp เพื่อสร้างไซต์ของคุณ จะมี gulp-sri ซึ่งจะส่งออกไฟล์ JSON พร้อมรายการไฟล์ของคุณและแฮชของไฟล์เหล่านั้น จากนั้นคุณสามารถใช้สิ่งนี้ในเว็บไซต์ของคุณ ตัวอย่างเช่น สำหรับไซต์ที่แสดงผลแบบไดนามิก คุณอาจสร้างปลั๊กอินเทมเพลตเพื่ออ่านไฟล์นั้นและเพิ่มแฮชลงในเทมเพลตของคุณเมื่อจำเป็น

หากคุณยังคงใช้ Gulp แต่มีไซต์แบบสแตติก (หรือไซต์ที่สร้างแบบสแตติก) คุณอาจใช้ gulp-sri-hash ซึ่งจะทำงานผ่านหน้า HTML ของคุณจริงๆ และแก้ไขหน้าเว็บเพื่อเพิ่มแฮชได้ตามต้องการ ซึ่งสะดวกมาก

หากคุณกำลังใช้ Webpack มี webpack-subresource-integrity ซึ่งในสไตล์ Webpack ที่แท้จริงนั้นซับซ้อนกว่าที่มนุษย์ทุกคนคาดหวัง แต่ดูเหมือนว่าจะใช้งานได้

สำหรับผู้ที่ใช้เครื่องมือสร้างเทมเพลตของ Handlebars ดูเหมือนจะมีตัวเลือกให้คุณใช้ได้ และหากกระบวนการสร้างของคุณเป็นเพียง JavaScript พื้นฐาน ก็มีวิธีแก้ไขปัญหาง่ายๆ ด้วยเช่นกัน

หากคุณกำลังใช้ CMS เช่น WordPress ฉันพบปลั๊กอินที่ดูเหมือนจะทำให้ง่าย แม้ว่าฉันจะยังไม่ได้ลองใช้เองก็ตาม Googling สำหรับแพลตฟอร์มที่คุณเลือกด้วย SRI หรือ Sub Resource Integrity มักจะชี้ให้คุณไปในทิศทางที่ถูกต้อง

โดยพื้นฐานแล้วคุณต้องการแฮชแฮชของคุณ หลังจากที่ ไฟล์ JavaScript ของคุณถูกย่อให้เล็กสุดแล้วทำให้แฮชนั้นพร้อมใช้งานในส่วนใดส่วนหนึ่งของระบบของคุณที่ส่งออกแท็ก <script> สิ่งมหัศจรรย์อย่างหนึ่งของแพลตฟอร์มเว็บคือมันมีความหลากหลายทางเทคนิคมาก แต่น่าเสียดายที่ฉันไม่สามารถให้คำแนะนำในการใช้งานที่ดีแก่คุณได้!

สิ่งอื่น ๆ ที่ควรทราบ

ในบทความนี้ ฉันได้พูดถึงไฟล์ JavaScript มามากแล้ว เพราะนั่นคือจุดที่เหมาะสมที่สุดในการป้องกันการโจมตีจากการแฮ็ก SRI ยังใช้งานได้กับ CSS ดังนั้นคุณจึงสามารถใช้งานได้ในลักษณะเดียวกันทุกประการ ความเสี่ยงสำหรับ CSS ที่เป็นอันตรายนั้นต่ำกว่ามาก แต่โอกาสในการทำลายไซต์ยังคงมีอยู่ และใครจะรู้ว่าบั๊กของเบราว์เซอร์ใดที่อาจนำไปสู่ ​​CSS ที่เปิดเผยไซต์ของคุณต่อแฮ็กเกอร์โดยไม่ได้ตั้งใจ ดังนั้นจึงใช้งานได้โดยใช้ SRI ที่นั่นเช่นกัน

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

 Content-Security-Policy: require-sri-for script;

นี่เป็นวิธีเพื่อให้แน่ใจว่ามีการใช้ SRI เสมอ ซึ่งอาจเป็นประโยชน์ในไซต์ที่ทำงานโดยสมาชิกในทีมหลายคนที่อาจหรืออาจไม่สามารถดำเนินการได้อย่างรวดเร็วอย่างเต็มที่ อีกครั้ง ที่ที่ดีในการอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้คือเอกสาร MDN ที่ยอดเยี่ยมเสมอสำหรับ Subresource Integrity

สิ่งสุดท้ายที่ควรพูดถึงคือการสนับสนุนเบราว์เซอร์สำหรับ SRI การสนับสนุนในเบราว์เซอร์สมัยใหม่นั้นกว้าง ยกเว้น Internet Explorer เป็นหลัก เนื่องจากวิธีการที่เข้ากันได้แบบย้อนกลับ ข้อมูลจำเพาะจึงถูกนำไปใช้ อย่างไรก็ตาม สามารถใช้งานได้อย่างปลอดภัยในทันที เบราว์เซอร์ที่เข้าใจแอตทริบิวต์ integrity จะใช้แฮชและตรวจสอบความสมบูรณ์ และเบราว์เซอร์รุ่นเก่าจะทำงานต่อไปตามปกติและทำงานต่อไป แน่นอน คุณจะไม่ได้รับการป้องกันเพิ่มเติมในเบราว์เซอร์รุ่นเก่าเหล่านั้น แต่คุณจะอยู่ในเบราว์เซอร์ที่ให้การสนับสนุน

บทสรุป

เราได้เห็นไม่เพียงแค่สิ่งที่แฮชแปลกๆ เหล่านั้นในแอตทริบิวต์ integrity เท่านั้น แต่เรายังสามารถใช้แฮชเหล่านี้เพื่อป้องกันการโจมตีบางประเภทบนเว็บไซต์ของเราได้อย่างไร แน่นอนว่าไม่มีสัญลักษณ์แสดงหัวข้อย่อยสีเงินที่จะปกป้องไซต์ของเราจากการถูกโจมตีทุกประเภท แต่ Subresource Integrity เป็นเครื่องมือที่มีประโยชน์อย่างยิ่งในห่วงโซ่

การใช้ประโยชน์จากจุดบกพร่องด้านความปลอดภัยมักจะเกี่ยวกับการจัดเรียงชิ้นส่วนเล็กๆ หลายๆ ชิ้นเข้าแถว หาก A อยู่ในสถานที่ และคุณสามารถทำให้ B เกิดขึ้นได้ ข้อบกพร่องใน C จะทำให้ D เป็นไปได้ คุณสมบัติของเบราว์เซอร์เช่น SRI ทำให้เรามีวิธีที่ดีในการผูกสิ่งต่าง ๆ อีกเล็กน้อยและอาจทำลายห่วงโซ่นั้นและป้องกันไม่ให้แฮ็กเกอร์ได้รับสิ่งที่พวกเขาต้องการ ยิ่งไปกว่านั้น ถ้าคุณสามารถรวมเข้ากับกระบวนการสร้างหรือ CMS ของคุณได้ เป็นสิ่งที่คุณควรจะตั้งค่าได้ครั้งเดียวแล้วลืมไปเลย และจะไม่ทำให้คุณไม่สะดวกในแต่ละวัน

ดังนั้น เราขอแนะนำให้คุณพิจารณา Subresource Integrity อย่างจริงจัง และนำไปใช้ในเว็บไซต์ของคุณหากทำได้