Antipattern: ใช้ตัวระบุความโลภในนโยบาย Regular ExpressionProtection

คุณกำลังดูเอกสารประกอบ Apigee Edge
ไปที่ เอกสารประกอบเกี่ยวกับ Apigee X.
ข้อมูล

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

คุณจะกำหนดนิพจน์ทั่วไปสำหรับเส้นทางคำขอ พารามิเตอร์การค้นหา พารามิเตอร์แบบฟอร์ม ส่วนหัว, องค์ประกอบ XML (ในเพย์โหลด XML ที่กำหนดโดยใช้ XPath), แอตทริบิวต์ออบเจ็กต์ JSON (ใน JSON เพย์โหลดที่กำหนดโดยใช้ JSONPath)

ตัวอย่างต่อไปนี้นโยบาย regularExpressionProtection ปกป้องแบ็กเอนด์จาก SQL การโจมตีแบบแทรกโค้ด:

<!-- /antipatterns/examples/greedy-1.xml -->
<RegularExpressionProtection async="false" continueOnError="false" enabled="true"
  name="RegexProtection">
    <DisplayName>RegexProtection</DisplayName>
    <Properties/>
    <Source>request</Source>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <QueryParam name="query">
      <Pattern>[\s]*(?i)((delete)|(exec)|(drop\s*table)|
        (insert)|(shutdown)|(update)|(\bor\b))</Pattern>
    </QueryParam>
</RegularExpressionProtection>

ลาย Antipattern

ตัวขยายเริ่มต้น (*, + และ ?) มีค่าที่ใช้ได้ ธรรมชาติ: จะเริ่มจับคู่กับลำดับที่ยาวที่สุด เมื่อไม่พบรายการที่ตรงกัน Backtrack ค่อยๆ พยายามให้ตรงกันกับรูปแบบ หากสตริงผลลัพธ์ที่ตรงกับรูปแบบคือ สั้นมาก การใช้ตัวระบุที่ละเลยอาจใช้เวลานานกว่าที่จำเป็น โดยเฉพาะอย่างยิ่ง เป็นจริงหากเพย์โหลดมีขนาดใหญ่ (ในหน่วย 10 หรือหลายร้อย KB)

นิพจน์ตัวอย่างต่อไปนี้ใช้ .* หลายอินสแตนซ์ ซึ่งมีความโลภ โอเปอเรเตอร์:

<Pattern>.*Exception in thread.*</Pattern>

ในตัวอย่างนี้ นโยบาย regularExpressionProtection จะพยายามจับคู่ให้นานที่สุดก่อน ลำดับ — สตริงทั้งหมด หากไม่พบรายการที่ตรงกัน ระบบจะใช้นโยบายย้อนหลัง ค่อยๆ เปลี่ยน หากสตริงที่ตรงกันอยู่ใกล้กับจุดเริ่มต้นหรือตรงกลางของเพย์โหลด ให้ใช้ ตัวขยายที่ละลายอย่าง .* อาจใช้เวลาและพลังในการประมวลผลมากกว่าเต็มใจ คำขยาย เช่น .*? หรือ "ตัวขยายเชิงแสดงแทน" (ไม่ค่อยเป็นที่นิยม) เช่น .*+

ตัวขยายที่ลังเล (เช่น X*?, X+?, X??) เริ่มต้นด้วยการลอง เพื่อจับคู่อักขระเดียวจากจุดเริ่มต้นของเพย์โหลด แล้วค่อยๆ เพิ่มอักขระ ตัวขยายแบบแสดงแทน (เช่น X?+, X*+, X++) พยายามจับคู่ เพย์โหลดทั้งหมดเพียงครั้งเดียว

โดยใช้ข้อความตัวอย่างต่อไปนี้สำหรับรูปแบบข้างต้น

Hello this is a sample text with Exception in thread
with lot of text after the Exception text.

การใช้ .* ที่ละโมบไม่มีประสิทธิภาพในกรณีนี้ ลาย .*Exception in thread.* ดำเนินการจับคู่ 141 ขั้นตอน หากคุณใช้รูปแบบ .*?Exception in thread.* (ซึ่งใช้ตัวระบุที่ไม่เต็มใจ) แทน ผลลัพธ์จะ 55 ก้าวเท่านั้น

ผลกระทบ

การใช้ตัวขยายแบบไม่ต้องกำหนด เช่น ไวลด์การ์ด (*) ร่วมกับฟังก์ชัน นโยบาย regularExpressionProtection อาจนำไปสู่ปัญหาต่อไปนี้

  • เวลาในการตอบสนองโดยรวมที่เพิ่มขึ้นสำหรับคำขอ API ที่มีขนาดเพย์โหลดปานกลาง (สูงสุด 1 MB)
  • ใช้เวลานานในการบังคับใช้นโยบาย regularExpressionProtection
  • คำขอ API ที่มีเพย์โหลดขนาดใหญ่ (>1 MB) ล้มเหลวโดยมีข้อผิดพลาดเกี่ยวกับการหมดเวลาของเกตเวย์ 504 หาก พ้นระยะหมดเวลาที่กำหนดไว้ล่วงหน้าบน Edge Router แล้ว
  • การใช้งาน CPU สูงบนโปรเซสเซอร์ข้อความเนื่องจากมีการประมวลผลข้อมูลจำนวนมากซึ่งทำให้ ส่งผลต่อคำขอ API อื่นๆ

แนวทางปฏิบัติแนะนำ

  • หลีกเลี่ยงการใช้ตัวขยายที่ละลายอย่าง .* ในนิพจน์ทั่วไปที่มี นโยบาย regularExpressionProtection ให้ใช้ตัวขยายที่ไม่เต็มใจ เช่น .*? หรือตัวขยายแบบแสดงแทน เช่น .*+ (ไม่ค่อยนิยมใช้) ในตำแหน่งใดก็ตาม เท่าที่จะเป็นไปได้

อ่านเพิ่มเติม