לכל כלל במדיניות האבטחה של Google Cloud Armor יש עדיפות, תנאי התאמה ופעולה. Cloud Armor מבצע את הפעולה של הכלל בעל העדיפות הגבוהה ביותר שתואם לבקשה. כללים עם עדיפות נמוכה יותר מהכלל התואם בעל העדיפות הגבוהה ביותר לא נבדקים, גם אם יש להם את אותם תנאי התאמה.
כל כלל במדיניות האבטחה תומך בשני סוגים של תנאי התאמה:
- תנאי התאמה בסיסי מכיל רשימות של כתובות IP או רשימות של טווחי כתובות IP. תנאי התאמה בסיסיים מוגדרים באמצעות הדגל
--src-ip-rangesכשיוצרים כלל באמצעות Google Cloud CLI. - תנאי התאמה מתקדם מכיל ביטוי עם עד חמישה ביטויי משנה שיכולים להתאים למגוון מאפיינים של בקשה נכנסת.
תנאי התאמה מתקדמים מוגדרים באמצעות הדגל
--expressionכשיוצרים כלל באמצעות Google Cloud CLI.
בדף הזה מוסבר איך ליצור ולהציג כללים של מדיניות אבטחה, ומופיעה בו הפניה לשפת הכללים בהתאמה אישית של Cloud Armor שמשמשת לכתיבת ביטויים בתנאי התאמה מתקדמים. שפת הכללים בהתאמה אישית של Cloud Armor היא קבוצת משנה של Common Expression Language (CEL).
ביטויים שנכתבים בשפת הכללים בהתאמה אישית של Cloud Armor דורשים שני רכיבים:
- המאפיין: הנתונים שרוצים לבדוק
- הפעולה: איך להשתמש בנתונים
לדוגמה, בביטוי הבא נעשה שימוש במאפיינים origin.ip ו-198.51.100.0/24 בפעולה inIpRange. במקרה הזה, הביטוי מחזיר את הערך true אם origin.ip נמצא בטווח כתובות ה-IP של 198.51.100.0/24.
inIpRange(origin.ip, '198.51.100.0/24')
למרות שביטוי הדוגמה הקודם תואם רק לכתובת ה-IP של הלקוח, כשמשתמשים בביטוי הדוגמה בכלל מדיניות אבטחה של Cloud Armor, הכלל נחשב לכלל עם תנאי התאמה מתקדמים מבחינת המכסות. מידע נוסף זמין במאמר מכסות ומגבלות ב-Cloud Armor.
יצירת כללים של מדיניות אבטחה
כדי להוסיף כללים למדיניות האבטחה של Cloud Armor, פועלים לפי השלבים שמפורטים בקטע הזה.
המסוף
נכנסים לדף Cloud Armor policies במסוף Google Cloud .
לוחצים על שם מדיניות האבטחה כדי לפתוח את הדף Policy details, ואז לוחצים על הכרטיסייה Rules.
לוחצים על הוספת כלל.
אופציונלי: מזינים תיאור של הכלל.
בוחרים את המצב:
- מצב בסיסי: מאשרים או דוחים תעבורת נתונים על סמך כתובות IP או טווחי IP.
- מצב מתקדם: מאפשרים או חוסמים תנועה על סמך ביטויים של כללים.
בשדה Match, מציינים את התנאים שהכלל חל עליהם:
מצב בסיסי: מזינים בין 1 ל-10 טווחי כתובות IP שיתאימו לכלל. אפשר להוסיף עד 10 טווחים של כתובות IP. למידע על המגבלות, קראו את המאמר המכסות והמגבלות של Cloud Armor.
מצב מתקדם:
- הכלי להגדרת תנאי התאמה (גרסת טרום-השקה (Preview)): משתמשים בכלי החזותי כדי ליצור ביטויים בלי לכתוב קוד CEL גולמי. לשלב ולקבץ תנאים, ולהחיל טרנספורמציות של מחרוזות. איך משתמשים בכלי להגדרת תנאי התאמה
- Match condition editor: מזינים ביטוי להערכה של בקשות נכנסות. מידע נוסף זמין במאמרים פעולות ומאפיינים.
ברשימה פעולה, בוחרים באפשרות אישור או דחייה.
אם אתם מגדירים כלל דחייה, בוחרים קוד תגובה ברשימה Response code.
כדי להפעיל את מצב התצוגה המקדימה של הכלל, לוחצים על הפעלה.
בשדה Priority, מזינים מספר שלם מ-0 עד 2,147,483,646. Cloud Armor מעריך את הכללים לפי סדר העדיפות, מ-0 (הגבוה ביותר) עד 2,147,483,647 (הנמוך ביותר). כלל ברירת המחדל הוא בעדיפות 2,147,483,647.
לוחצים על הוספה.
gcloud
משתמשים בפקודה gcloud compute security-policies rules create
PRIORITY. מחליפים את PRIORITY בעדיפות של הכלל במדיניות:
gcloud compute security-policies rules create PRIORITY \
--security-policy POLICY_NAME \
--description DESCRIPTION \
--src-ip-ranges IP_RANGES | --expression EXPRESSION \
--action=[ allow | deny-403 | deny-404 | deny-502 ] \
--preview
לדוגמה, הפקודה הבאה מוסיפה כלל עם עדיפות 1000 כדי לחסום תנועה מטווחים של כתובות IP 192.0.2.0/24 ו-198.51.100.0/24:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--description "block traffic from 192.0.2.0/24 and 198.51.100.0/24" \
--src-ip-ranges "192.0.2.0/24","198.51.100.0/24" \
--action "deny-403"
משתמשים בדגל --expression כדי לציין תנאי. הפקודה הבאה מוסיפה כלל שמאפשר תנועה מכתובת ה-IP 1.2.3.4 שמכילה את המחרוזת example בכותרת User-Agent:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')" \
--action allow \
--description "Block User-Agent 'example'"
הפקודה הבאה מוסיפה כלל לחסימת בקשות אם קובץ ה-cookie של הבקשה מכיל ערך ספציפי:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "has(request.headers['cookie']) && request.headers['cookie'].contains('80=SomeValue')" \
--action deny-403 \
--description "Cookie Block"
הפקודה הבאה מוסיפה כלל לחסימת בקשות מהאזור AU:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "origin.region_code == 'AU'" \
--action deny-403 \
--description "AU block"
הפקודה הבאה מוסיפה כלל לחסימת בקשות מהאזור AU שלא נמצאות בטווח ה-IP שצוין:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "origin.region_code == \"AU\" && !inIpRange(origin.ip, '1.2.3.0/24')" \
--action deny-403 \
--description "country and IP block"
הפקודה הבאה מוסיפה כלל לחסימת בקשות עם URI שתואם לביטוי רגולרי:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "request.path.matches('/example_path/')" \
--action deny-502 \
--description "regex block"
הפקודה הבאה מוסיפה כלל לחסימת בקשות אם הערך המפוענח ב-Base64 של הכותרת user-id מכיל ערך ספציפי:
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')" \
--action deny-403 \
--description "country and IP block"
הפקודה הבאה מוסיפה כלל שמשתמש בקבוצת ביטויים שהוגדרה מראש מ-OWASP Core Rule Set (CRS) 4.22 כדי לצמצם את ההשפעה של התקפות הזרקת SQL (SQLi):
gcloud compute security-policies rules create 1000 \
--security-policy my-policy \
--expression "evaluatePreconfiguredWaf('sqli-v422-stable')" \
--action deny-403
שימוש בכלי להגדרת תנאי ההתאמה
הכלי להגדרת תנאי התאמה הוא ממשק חזותי במסוף Google Cloud , שמאפשר ליצור ביטויים מורכבים של כללי Cloud Armor בלי לכתוב קוד ב-Common Expression Language (CEL). במקום לכתוב קוד, אתם יכולים להשתמש בממשק המשתמש המובנה של הכלי כדי לשלב תנאים ולוגיקה של קבוצות. כך תוכלו להימנע משגיאות תחביר ולהבין טוב יותר את מבנה הכלל. הכלי תומך ברשימות שטוחות ובלוגיקה בתצוגת עץ של עד חמש רמות של ביטויים. הכלי הזה שימושי כשמגדירים כללים להגנה על קצוות עורפיים בכמה עננים או על פריסות היברידיות, שבהן יכול להיות שצריך לבדוק מאפייני בקשות ספציפיים לפני ניתוב התנועה.
תכונות של הכלי להגדרת תנאי התאמה
הכלי להגדרת תנאי התאמה כולל את התכונות הבאות:
- לוגיקה והטמעה: שילוב של כמה תנאים באמצעות האופרטורים
ANDו-OR. הכלי תומך בקיבוץ ובהטמעה של עד חמישה ביטויים. - טרנספורמציות של מחרוזות: במאפיינים שמבוססים על מחרוזות (כמו
request.pathאוrequest.headers), אפשר להחיל טרנספורמציות כדי לנרמל את הנתונים לפני ההערכה. הטרנספורמציות הנתמכות כוללות:- אותיות קטנות וגדולות
- פענוח Base64
- פענוח כתובת URL ופענוח כתובת URL (יוניקוד)
- המרת UTF-8 ל-Unicode
- ניתוח דו-כיווני: מעבר בין הכלי להגדרת תנאי התאמה החזותי לבין עורך תנאי ההתאמה של הטקסט הגולמי. ממשק המשתמש מנתח קוד CEL גולמי וממיר אותו לבלוקים חזותיים באופן אוטומטי.
- תמיכה בפונקציות: הכלי מספק רכיבים אינטראקטיביים לביטויים שמבוססים על פונקציות, כמו כללי WAF שהוגדרו מראש, קבוצות של כתובות ומודיעין איומי סייבר.
מגבלות
הכלי להגדרת תנאי ההתאמה הוא הממשק שמוגדר כברירת מחדל ליצירת כללים מתקדמים. אם ביטוי מכיל לוגיקה לא נתמכת (כמו פקודות מאקרו לא ידועות), הכלי ליצירת ביטויים מושבת. במקרים כאלה, צריך להשתמש בטקסט הגולמי בעורך תנאי ההתאמה כדי לערוך את הכלל.
בנוסף, הזמינות של ביטויים מסוימים בכלי ליצירת ביטויים תלויה ברמת Google Cloud Armor Enterprise של הפרויקט ובסוג מדיניות האבטחה.
ביטויים לדוגמה
הנה כמה ביטויים לדוגמה. למידע נוסף על פעולות ומאפיינים נתמכים, קראו את המאמרים פעולות ומאפיינים.
אם הכלל או הביטוי משתמשים בקודי מדינה או אזור לפי תקן ISO 3166-1 alpha-2, Cloud Armor מתייחס לכל קוד בנפרד. הכללים והביטויים של Cloud Armor משתמשים בקודים האלה כדי לאשר או לדחות בקשות.
הביטוי הבא תואם לבקשות מכתובת ה-IP
1.2.3.4שמכילות את המחרוזתexampleבכותרתUser-Agent:inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')לחלופין, אפשר להתאים לטווח כתובות ה-IP של כותרת מותאמת אישית של כתובת ה-IP של הלקוח באמצעות המאפיין
origin.user_ip:inIpRange(origin.user_ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')הביטוי הבא תואם לבקשות שיש להן קובץ Cookie עם ערך ספציפי:
has(request.headers['cookie']) && request.headers['cookie'].contains('cookie_name=cookie_value')הביטוי הבא תואם לבקשות מהאזור
AU:origin.region_code == 'AU'
הביטוי הבא תואם לבקשות מהאזור
AUשלא נמצאות בטווח כתובות ה-IP שצוין:origin.region_code == "AU" && !inIpRange(origin.ip, '1.2.3.0/24')
הביטוי הבא תואם לבקשות עם נתיב משתנה ממוספר לקובץ ספציפי, אם ה-URI תואם לביטוי רגולרי:
request.path.matches('/path/[0-9]+/target_file.html')הביטוי הבא תואם לבקשות אם הערך המפוענח ב-Base64 של הכותרת
user-idמכיל ערך ספציפי:has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')הביטוי הבא משתמש בקבוצת ביטויים שהוגדרה מראש מקבוצת הכללים OWASP CRS 4.22 כדי להתאים להתקפות SQLi:
evaluatePreconfiguredWaf('sqli-v422-stable')
מעבר בנתיב ונירמול
כדי לנהל את הכללים של מעבר נתיב וקידוד, וליצור כללים כלליים שמונעים שימוש באותיות רישיות או קידוד ספציפי לתוכן, צריך לנרמל את התוכן בכללים שמבוססים על נתיב.
כשכותבים כללים שמשתמשים ב-startsWith, ב-endsWith או ב-contains כדי להתאים ל-request.path, צריך להשתמש ב-lower וב-urlDecode כדי לנרמל את הנתיב לפני ההתאמה. כך אפשר למנוע עקיפות שמשתמשות בקידוד כתובות URL או בווריאציות של אותיות רישיות וקטנות.
לדוגמה, כדי לחסום את הגישה לספרייה /admin, משתמשים בביטוי הבא:
request.path.lower().urlDecode().startsWith('/admin')
הכלל הזה חוסם בקשות ל-/admin, ל-/Admin, ל-/a%64min ולגרסאות אחרות.
כשכותבים כללים שמשתמשים ב-matches כדי להתאים ל-request.path, צריך להביא בחשבון את תו הלוכסן ההפוך (\) בביטוי הרגולרי.
לדוגמה, כדי לחסום את הגישה לספרייה /admin, משתמשים בביטוי הבא כדי לחסום מעקפים שמשתמשים בתו הלוכסן ההפוך (\):
request.path.matches(r'^/\\*admin')
אפשר לשלב את זה עם urlDecode כדי לטפל גם בקידוד כתובות URL וגם במעקפים של תו הלוכסן ההפוך (\):
request.path.urlDecode().matches(r'^/\\*admin')
הצגת הכללים של מדיניות האבטחה
בקטעים הבאים מוסבר איך להציג את הכללים שהוגדרו במדיניות אבטחה, ואיך לראות את כללי ה-WAF שהוגדרו מראש.
הצגת רשימת הכללים במדיניות אבטחה
כדי להציג את רשימת הכללים במדיניות האבטחה של Cloud Armor, פועלים לפי השלבים שבקטע הזה.
המסוף
נכנסים לדף Cloud Armor policies במסוף Google Cloud .
לוחצים על השם של מדיניות האבטחה הספציפית. בדף פרטי המדיניות מוצגים כללי המדיניות בכרטיסייה כללים.
gcloud
כדי להציג את כל הכללים במדיניות אבטחה, משתמשים בפקודה הבאה של gcloud:
gcloud compute security-policies describe NAME
כדי להציג את כל הכללים במדיניות אבטחה אחת באזור מסוים, יחד עם תיאור של המדיניות, משתמשים בפקודה הבאה של gcloud:
gcloud compute security-policies describe NAME \ --region REGION
כדי לתאר כלל, משתמשים בפקודה gcloud הבאה:
gcloud compute security-policies rules describe PRIORITY \
--security-policy POLICY_NAME
לדוגמה, הפקודה הבאה מתארת את הכלל עם עדיפות 1000 במדיניות האבטחה my-policy:
gcloud compute security-policies rules describe 1000 \
--security-policy my-policy
פלט:
action: deny(403) description: block traffic from 192.0.2.0/24 and 198.51.100.0/24 kind: compute#securityPolicyRule match: srcIpRanges: - '192.0.2.0/24' - '198.51.100.0/24' preview: false priority: 1000
מידע נוסף זמין במאמר gcloud compute security-policies
describe.
רשימת הכללים הזמינים שהוגדרו מראש
בנוסף לכללים שאתם מגדירים בעצמכם, Cloud Armor מספק כללים שהוגדרו מראש שאפשר להשתמש בהם במדיניות האבטחה. אתם יכולים להציג רשימה של כללים שהוגדרו מראש כדי לראות את הכללים והחתימות להגנה על אפליקציות, כמו קבוצת כללי הליבה (CRS) של OWASP, ש-Cloud Armor מספק. הכללים האלה מכילים חתימות מובנות ש-Cloud Armor בודק מול בקשות נכנסות. אפשר להוסיף את הכללים המוגדרים מראש האלה לכללים חדשים או קיימים באמצעות שפת הכללים בהתאמה אישית. מומלץ להשתמש בגרסה העדכנית ביותר של כללי CRS כשאפשר.
gcloud
מריצים את הפקודה
gcloud compute security-policies list-preconfigured-expression-sets:gcloud compute security-policies list-preconfigured-expression-sets
בדוגמה הבאה מוצג הפורמט של הפלט מהפקודה:
EXPRESSION_SET expression-set-1 RULE_ID SENSITIVITY expression-set-1-id-1 sensitivity-value-1 expression-set-1-id-2 sensitivity-value-2 expression-set-2 alias-1 RULE_ID SENSITIVITY expression-set-2-id-1 sensitivity-value-1 expression-set-2-id-2 sensitivity-value-2
הדוגמה הבאה כוללת דוגמה לפלט בפועל מהפקודה. שימו לב שהפלט בפועל כולל את כל הכללים שמפורטים במאמר כוונון כללי WAF ב-Cloud Armor.
gcloud compute security-policies list-preconfigured-expression-sets
EXPRESSION_SET sqli-canary RULE_ID SENSITIVITY owasp-crs-v042200-id942120-sqli 2 … xss-canary RULE_ID SENSITIVITY owasp-crs-v042200-id941110-xss 1 owasp-crs-v042200-id941120-xss 2 … sourceiplist-fastly sourceiplist-cloudflare sourceiplist-imperva
תפעול
בטבלה הבאה מתוארים האופרטורים שאפשר להשתמש בהם עם מאפיינים (המיוצגים על ידי x, y ו-k) כדי להגדיר ביטויים של כללים.
| תפעול | ביטויים | תיאור |
|---|---|---|
| שוויון | x == y |
הפונקציה מחזירה את הערך true אם x שווה ל-y. |
| שוויון, מחרוזת מילולית | x == "foo" |
הפונקציה מחזירה את הערך true אם x שווה למחרוזת הקבועה שצוינה. |
| שוויון, מחרוזת מילולית גולמית | x == R"fo'o" |
הפונקציה מחזירה את הערך true אם x שווה למחרוזת הגולמית שצוינה, שלא מפרשת רצפי תווי בריחה (escape). ליטרלים של מחרוזות גולמיות נוחים לביטוי מחרוזות שצריכות להשתמש בעצמן בתווי בריחה (escape).
|
| שלילה לוגית | !x |
הפונקציה מחזירה את הערך true אם הערך הבוליאני x הוא false, או מחזירה את הערך false אם הערך הבוליאני x הוא true. |
| אי שוויון | x != y |
הפונקציה מחזירה את הערך true אם x לא שווה ל-y. |
| שרשור | x + y |
הפונקציה מחזירה את המחרוזת המשורשרת xy. |
| "וגם" לוגי | x && y |
הפונקציה מחזירה את הערך true אם גם x וגם y הם true. |
| "או" לוגי | x || y |
הפונקציה מחזירה את הערך true אם x, y או שניהם הם true. |
| מכיל מחרוזת משנה | x.contains(y) |
הפונקציה מחזירה את הערך true אם המחרוזת x מכילה את מחרוזת המשנה y. |
| מתחיל במחרוזת משנה | x.startsWith(y) |
הפונקציה מחזירה את הערך true אם המחרוזת x מתחילה במחרוזת המשנה y. |
| מסתיים במחרוזת משנה | x.endsWith(y) |
הפונקציה מחזירה את הערך true אם המחרוזת x מסתיימת במחרוזת המשנה y. |
| התאמה של ביטוי רגיל | x.matches(y) |
הפונקציה מחזירה את הערך true אם המחרוזת x תואמת חלקית לתבנית RE2 y שצוינה. תבנית ה-RE2 עוברת הידור באמצעות האפשרות RE2::Latin1 שמשביתה את תכונות ה-Unicode. |
| כתובת IP בטווח | inIpRange(x, y) |
הפונקציה מחזירה את הערך true אם כתובת ה-IP x כלולה בטווח ה-IP y. |
| אותיות קטנות | x.lower() |
הפונקציה מחזירה את הערך של המחרוזת x באותיות קטנות. |
| אותיות גדולות | x.upper() |
הפונקציה מחזירה את הערך של המחרוזת x באותיות רישיות. |
| ערך מפוענח ב-Base64 | x.base64Decode() |
הפונקציה מחזירה את הערך המפוענח של x ב-base64. קודם, הקו התחתון (_) והמקף (-) מוחלפים בלוכסן (/) ובסימן פלוס (+), בהתאמה.
הפונקציה מחזירה "" (מחרוזת ריקה) אם x הוא לא ערך base64 תקין. |
| ערך של מיפוי מקשים | m['k'] |
מחזירה את הערך במפתח k במפה m של מחרוזת למחרוזת אם k זמין. אחרת, מחזירה שגיאה. הגישה המומלצת היא לבדוק קודם את הזמינות באמצעות "has(m['k'])==true". |
| בדיקת הזמינות של המפתח במפה | has(m['k']) |
הפונקציה מחזירה את הערך true אם המפתח k זמין במפה m. |
| המרה למספר שלם | int(x) |
הפונקציה ממירה את תוצאת המחרוזת של x לסוג int. אחר כך אפשר להשתמש בו כדי לבצע השוואה של מספרים שלמים באמצעות אופרטורים אריתמטיים רגילים כמו > ו-<=. זה עובד רק עבור ערכים שאמורים להיות מספרים שלמים. |
| אורך | size(x) |
הפונקציה מחזירה את האורך של המחרוזת x. |
| פענוח כתובת URL | x.urlDecode() |
הפונקציה מחזירה את הערך של x אחרי פענוח כתובת ה-URL. רצפי תווים בפורמט %## מוחלפים בתווים המקבילים שאינם ASCII, והתו + מוחלף ברווח. קידודים לא חוקיים מוחזרים כמו שהם. |
| פענוח כתובת URL (יוניקוד) | x.urlDecodeUni() |
הפונקציה מחזירה את הערך של x אחרי פענוח כתובת ה-URL. בנוסף ל-urlDecode(), הפונקציה מטפלת גם ברצפים של תווי Unicode בפורמט %u###. קידודים לא חוקיים מוחזרים כמו שהם. |
| המרת utf8 ל-Unicode | x.utf8ToUnicode() |
הפונקציה מחזירה את הייצוג של x ב-Unicode באותיות קטנות, בקידוד UTF-8. |
| קיים | m.exists(k, expr) |
הפונקציה מחזירה את הערך true אם לפחות רשומה אחת במפה m עומדת בתנאי expr,
כאשר k מייצג את המפתח של כל רשומה במפה.
|
| קיים אחד | m.exists_one(k, expr) |
הפונקציה מחזירה את הערך true אם בדיוק רשומה אחת במפה m עומדת בתנאי expr,
כאשר k מייצג את המפתח של כל רשומה במפה.
|
| הכול | m.all(k, expr) |
הפונקציה מחזירה את הערך true אם כל הרשומות במפה m עומדות בתנאי expr,
כאשר k מייצג את המפתח של כל רשומה במפה.
|
| מסנן | m.filter(k, expr) |
הפונקציה מחזירה מפה שמכילה רק את הרשומות מהמפה m שבהן הרשומה עומדת בתנאי expr, כאשר k מייצג את המפתח של כל רשומה במפה. |
| מפה | m.map(k, expr) |
מחזירה רשימה שמכילה את התוצאה של הערכת expr לכל מפתח במפה m, כאשר k מייצג את המפתח של כל רשומה במפה. |
מאפיינים
המאפיינים מייצגים מידע מבקשה נכנסת, כמו כתובת ה-IP של הלקוח או נתיב כתובת ה-URL המבוקשת.
| שדה | סוג | תיאור |
|---|---|---|
origin.ip |
מחרוזת | כתובת ה-IP של הלקוח שיזם את הבקשה. |
origin.user_ip |
מחרוזת | כתובת ה-IP של הלקוח שממנו נשלחה הבקשה, שנכללת ב-HTTP-HEADER על ידי שרת proxy במעלה הזרם. לפני שמשתמשים במאפיין הזה, צריך להגדיר את האפשרות userIpRequestHeaders[] בשדה advancedOptionsConfig של מדיניות האבטחה כך שתתאים למקור כמו True-Client-IP, X-Forwarded-For או X-Real-IP. מידע נוסף זמין במאמר סקירה כללית של כתובות IP של משתמשים.
אם לא מגדירים את האפשרות |
origin.tls_ja4_fingerprint |
מחרוזת | טביעת אצבע של JA4 TLS/SSL אם הלקוח מתחבר באמצעות HTTPS, HTTP/2 או HTTP/3. אם הוא לא זמין, מוחזרת מחרוזת ריקה. |
origin.tls_ja3_fingerprint |
מחרוזת | טביעת אצבע של JA3 TLS/SSL אם הלקוח מתחבר באמצעות HTTPS, HTTP/2 או HTTP/3. אם הוא לא זמין, מוחזרת מחרוזת ריקה. |
request.headers |
מפה | מפה של מחרוזת למחרוזת של כותרות בקשת ה-HTTP. אם לכותרת יש כמה ערכים, הערך התואם במפה הזו הוא מחרוזת אחת שמכילה את כל הערכים, מופרדים בפסיקים. כל המפתחות במפה הזו הם אותיות קטנות. מאזני העומסים החיצוניים של האפליקציות בודקים את כל הכותרות שהתקבלו, וחלות עליהם אותן מגבלות של כותרות. אפשר להשתמש ב- אפשר לעבור על המפה כדי לבדוק גם את המפתחות וגם את הערכים.
עם זאת, אפשר להשתמש באופרטורים של איטרציית מפה ( |
request.body |
מחרוזת | מייצג את גוף הבקשה כמחרוזת גולמית. הוא יכול לייצג נתונים של כל Content-Type. הוא מאחסן את התוכן כמחרוזת ללא ניתוח אוטומטי.
|
request.params |
מפה | מפה של צמדי מפתח/ערך שמצורפים לכתובת ה-URL או נכללים בגוף הבקשות. בקשת URI: name1=value1&name2=value2גוף בקשת JSON עם Content-Type: application/json:{ "username": "johndoe", "email": "johndoe@example.com" }גוף בקשת GraphQL בקשת POST עם Content-Type: application/graphql:{ Username: "exampleUser", query: "/* other fields */" }גוף בקשת Form בקשת POST עם Content-Type: application/x-www-form-urlencoded:"username=exampleUser&email=johndoe%40example.com"
|
request.method |
מחרוזת | שיטת בקשת ה-HTTP. |
request.path |
מחרוזת | נתיב כתובת ה-URL מסוג HTTP שנכלל בבקשה. כשכותבים כללים שתואמים ל-request.path, מומלץ לנרמל את הנתיב כדי לאפשר התאמה של התחביר במקרה של קידוד כתובת URL, וריאציות של אותיות רישיות או לוכסנים הפוכים.
מידע נוסף ודוגמאות זמינים במאמר מעבר בנתיב ונורמליזציה. |
request.scheme |
מחרוזת | סכמת כתובת ה-URL מסוג HTTP, כמו http או https.
הערכים של המאפיין הזה הם כולם באותיות קטנות. |
request.query |
מחרוזת | השאילתה של כתובת ה-URL מסוג HTTP בפורמט name1=value&name2=value2, כפי שהיא מופיעה בשורה הראשונה של בקשת ה-HTTP. לא מתבצע פענוח.
|
origin.region_code |
מחרוזת | קוד המדינה ב-Unicode שמשויך לכתובת ה-IP של הלקוח, למשל US. אם אתם יוצרים כלל או ביטוי שמשתמש בקודי מדינה או אזור לפי תקן ISO 3166-1 alpha 2, Cloud Armor מתייחס לכל קוד בנפרד. בכללים ובביטויים של Cloud Armor משתמשים בקודים האלה של האזורים כדי לאשר או לדחות בקשות.
|
origin.asn |
מספר שלם | מספר המערכת האוטונומית (ASN) שמשויך לכתובת ה-IP של הלקוח. ה-ASN הייחודי בעולם נקבע על סמך מפעיל הרשת שתומך בתחיליות של כתובות ה-IP שמכילות את כתובת ה-IP של הלקוח. |
ביטויים לדוגמה
לכל אחד מהביטויים האלה, הפעולה שננקטת תלויה בשאלה אם הביטוי נכלל בכלל דחייה או בכלל הרשאה.
לאשר או לדחות גישה על סמך טווח כתובות IP ב-IPv4 או ב-IPv6
הביטוי הבא תואם לבקשות מטווח כתובות ה-IP של
198.51.100.0/24:inIpRange(origin.ip, '198.51.100.0/24')
הביטוי הבא תואם לבקשות מטווח כתובות ה-IP של
2001:db8::/32:inIpRange(origin.ip, '2001:db8::/32')
אישור או דחייה של גישה על סמך טווח מותאם אישית של כתובות ה-IP של הלקוח מאחורי שרת proxy במעלה הזרם
אם הגדרתם את האופרטור origin.user_ip, אתם יכולים לבצע התאמה על סמך ערכי הכותרת שציינתם בשדה advancedOptionsConfig.userIpRequestHeaders[].
הביטוי הבא תואם לבקשות שמקורן בטווח כתובות ה-IP של
192.0.2.0/24:inIpRange(origin.user_ip, '192.0.2.0/24')
הביטוי הבא תואם לבקשות שמקורן בטווח כתובות ה-IP של
2001:db8::/32:inIpRange(origin.user_ip, '2001:db8::/32')
אישור או דחייה של תנועה עם קובץ Cookie ספציפי
הביטוי הבא תואם לבקשות שיש בהן קובץ Cookie שמכיל את הערך
80=BLAH:has(request.headers['cookie']) && request.headers['cookie'].contains('80=BLAH')
אישור או דחייה של תנועה עם כותרת referer לא ריקה
הביטוי הבא תואם לבקשות עם כותרת
refererלא ריקה:has(request.headers['referer']) && request.headers['referer'] != ""
אישור או דחייה של תנועה על סמך כותרת המארח
אתם יכולים לאשר או לדחות תנועה על סמך הערך של הכותרת Host בבקשה.
הביטוי הבא תואם לבקשות לכתובת URL ספציפית באמצעות
==:request.headers['host'].lower() == 'test.example.com'
הביטוי הבא תואם לבקשות לכתובת URL ספציפית באמצעות
endsWith:request.headers['host'].lower().endsWith('.example.com')הביטוי הבא תואם לבקשות לכתובת URL ספציפית באמצעות
contains:request.headers['host'].lower().contains('test.example.com')
הביטוי הבא תואם לבקשות לכמה דומיינים באמצעות
contains:request.headers['host'].lower().contains('test.example.com') || request.headers['host'].lower().contains('test22.example.com')הביטוי הבא תואם לבקשות לדומיין ולתת-הדומיינים שלו באמצעות
matches:request.headers['host'].matches('(?i:(?:sub\.)?test\.example\.com)')
אישור או דחייה של תנועה מאזור ספציפי
אם אפליקציית האינטרנט לא זמינה באזור AU, צריך לחסום את כל הבקשות מהאזור הזה.
בכלל דחייה, משתמשים בביטוי הבא שתואם לבקשות מהאזור
AU:origin.region_code == 'AU'
לחלופין, אם אפליקציית האינטרנט זמינה רק באזור AU, צריך לחסום בקשות מכל שאר האזורים.
בכלל דחייה, משתמשים בביטוי הבא, שתואם לבקשות מכל האזורים מלבד האזור
AU:origin.region_code != 'AU'
קודי האזור מבוססים על הקודים של ISO 3166-1 alpha 2. במקרים מסוימים, אזור תואם למדינה, אבל לא תמיד. לדוגמה, הקוד US כולל את כל המדינות בארצות הברית, מחוז אחד ושישה אזורים מרוחקים.
אישור או דחייה של תנועה מ-ASN ספציפי
אם אתם צריכים לחסום את אפליקציית האינטרנט שלכם ללקוחות שמקבלים שירות ממפעיל רשת ספציפי, אתם יכולים להשתמש במספר ה-ASN של מפעיל הרשת כדי לחסום.
בכלל דחייה, משתמשים בביטוי הבא, שתואם לבקשות מ-ASN ספציפי:
origin.asn == 123
לחלופין, אם אפליקציית האינטרנט שלכם צריכה להיות זמינה רק ללקוחות של מפעיל רשת ספציפי, צריך לחסום בקשות מכל מפעילי הרשת האחרים.
בכלל דחייה, משתמשים בביטוי הבא, שתואם לכל מפעילי הרשת האחרים מלבד זה שרוצים לאפשר:
origin.asn != 123
כמה הבעות פנים
כדי לכלול כמה תנאים בכלל אחד, משלבים כמה ביטויי משנה.
בדוגמה הבאה, בקשות מ-
1.2.3.0/24(כמו בודקי אלפא) באזורAUתואמות לביטוי הבא:origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
הביטוי הבא תואם לבקשות מ-
1.2.3.4שבהן סוכן המשתמש מכיל את המחרוזתWordPress:inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('WordPress')
אישור או דחייה של תנועה ל-URI של בקשה שתואם לביטוי רגולרי
הביטוי הבא תואם לבקשות שמכילות את המחרוזת
/example_path/ב-URI:request.path.matches('/example_path/')הביטוי הבא תואם לבקשות שכוללות את הערך
Chromeבשדה הכותרתUser-Agent:request.headers['user-agent'].matches('Chrome')הביטוי הבא מציג התאמה לא תלוית-רישיות לכותרת
User-Agentשמכילה אתwordpress. הוא תואם ל-User-Agent:WordPress/605.1.15, ל-User-Agent:wordPressולגרסאות אחרות שלwordpress:request.headers['user-agent'].matches('(?i:wordpress)')
אישור או דחייה של תנועה שמכילה ערך ספציפי שפוענח מ-base64
הביטוי הבא תואם לבקשות עם ערך מפוענח ב-base64 של
myValueלכותרתuser-id:has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
אישור או דחייה של תנועה שמכילה ערך מחרוזת באורך מסוים
הביטוי הבא תואם לבקשות שבהן אורך כתובת ה-URL גדול מ-10 תווים:
size(request.path) > 10
הביטוי הבא תואם לבקשות שבהן אורך הכותרת
x-dataגדול מ-1,024 תווים או שווה לו:size(request.headers['x-data']) >= 1024
אישור או דחייה של תנועה עם אפס content-length בגוף ה-HTTP
הביטוי הבא תואם לבקשות שיש בהן אפס
content-lengthבגוף ה-HTTP:int(request.headers["content-length"]) == 0
אישור או דחייה של תנועה שמכילה ערך ספציפי בקידוד URL
הביטוי הבא תואם לבקשות שערך קובץ ה-Cookie שלהן מכיל את המחרוזת
%3c:has(request.headers['cookie']) && request.headers['cookie'].urlDecode().contains('<')
אישור או דחייה של תנועה שמכילה ערך ספציפי בקידוד URL של מחרוזת Unicode
הביטוי הבא תואם לבקשות שבהן הערך של קובץ ה-Cookie שווה ל-
Match%2BValueאו ל-Match%u002BValue:has(request.headers['cookie']) && request.headers['cookie'].urlDecodeUni() == 'Match+Value'
אישור או דחייה של תנועה שמכילה מחרוזת Unicode ספציפית של טקסט UTF-8
הביטוי הבא תואם לבקשות שבהן הערך של קובץ ה-Cookie שווה ל-
¬:has(request.headers['cookie']) && request.headers['cookie'].utf8ToUnicode() == '%u00ac'
אישור או דחייה של תנועה על סמך טביעת אצבע מוכרת של JA4
הביטוי הבא תואם לבקשות עם טביעת אצבע מסוג JA4 ששווה ל-
t13d1516h2_8daaf6152771_b186095e22b6:origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
אישור או דחייה של תנועה על סמך רשימה של טביעות אצבע מסוג JA4
הביטוי הבא תואם לבקשות עם טביעת אצבע מסוג JA4 שזהה לאחת מטביעות האצבע הבאות מסוג JA4:
t00d0000h0_000000000000_000000000000t13d1516h2_8daaf6152771_b186095e22b6
origin.tls_ja4_fingerprint == 't00d0000h0_000000000000_000000000000' || origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
אישור או דחייה של תנועה על סמך תוכן גוף הבקשה
הביטוי הבא תואם לבקשות POST שמכילות את הערך
malicious-valueבגוף הבקשה:request.method == 'POST' && request.body.contains('malicious-value')הביטוי הבא תואם לבקשות שמתחילות ב-
<!DOCTYPE html>:request.body.startsWith('<!DOCTYPE html>')הביטוי הבא תואם לבקשות שבהן גוף הבקשה תואם לביטוי הרגולרי
\w+@\w+.com:request.body.matches('\w+@\w+.com')
לאשר או לדחות תנועה על סמך פרמטרים של בקשות
הביטוי הבא תואם לבקשות שלא מכילות פרמטר בשם
category:!has(request.params.category)
הביטוי הבא תואם לבקשות שבהן הפרמטר
categoryהואelectronics:request.params.category == 'electronics'
הביטוי הבא תואם לבקשות שבהן כל ערכי הפרמטרים לא ריקים:
request.params.all(k, request.params[k] != '')
הביטוי הבא תואם לבקשות שבהן פרמטר כלשהו מכיל את המחרוזת
admin:request.params.exists(k, request.params[k].contains('admin'))הביטוי הבא תואם לבקשות שבהן שם של פרמטר אחד בדיוק מכיל את
admin:request.params.exists_one(k, k.contains('admin'))הביטוי הבא תואם לבקשות שבהן לפחות שם אחד של פרמטר מכיל את
id:size(request.params.filter(k, k.contains('id'))) > 0הביטוי הבא תואם לבקשות שבהן ערכי הפרמטרים כוללים את המחרוזת
admin:request.params.map(k, request.params[k]).contains('admin')
אישור או דחייה של תנועה על סמך נתונים מובְנים בגוף הבקשה
הביטוי הבא תואם לבקשות שבהן השדה
passwordבגוף בקשת JSON מכיל את הערך123:has(request.params.password) && request.params.password.contains('123')הביטוי הבא תואם לבקשות שבהן השדה
cityבנתוני הטופס הואNewYork:has(request.params.city) && request.params.city == 'NewYork'
הביטוי הבא תואם לבקשות שבהן השדה המקונן
newsletterהואtrue:has(request.params.preferences) && has(request.params.preferences.newsletter) && request.params.preferences.newsletter == true
הביטוי הבא תואם לבקשות שבהן השדה
nameשל הרכיב הראשון במערךfriendsהואjohndoe:request.params['friends'][0]['name'] == 'johndoe'
כללי WAF שהוגדרו מראש
כללי WAF מוגדרים מראש משתמשים בחתימות סטטיות מוגדרות מראש, בביטויים רגולריים או בשניהם כדי להתאים לגוף הבקשה של HTTP, לכותרות של בקשת HTTP ולפרמטרים של שאילתה. כללי ה-WAF שהוגדרו מראש מבוססים על OWASP Core Rule Set 4.22. ב-Cloud Armor יש כמה כללי WAF מוגדרים מראש. בסקירה הכללית על כללי WAF שהוגדרו מראש ב-Cloud Armor תוכלו למצוא רשימה מלאה של כללי WAF שהוגדרו מראש.
כדי להציג את כל כללי ה-WAF שהוגדרו מראש, קראו את המאמר הצגת כללי ה-WAF שהוגדרו מראש.
למידע נוסף על כללי WAF שהוגדרו מראש, קראו את תרחיש השימוש צמצום התקפות על שכבת האפליקציה באמצעות כללי WAF שהוגדרו מראש.
שמות של כללי WAF שהוגדרו מראש
השמות של כללי WAF שהוגדרו מראש הם בפורמט <attack category>-<OWASP CRS version>-<version field>. קטגוריית המתקפה מציינת את סוג המתקפות שאתם רוצים להתגונן מפניהן, כמו xss (פרצת אבטחה XSS) או sqli (הזרקת SQL).
השדות של הגרסאות הנתמכות הם stable ו-canary. תוספות ושינויים בכללים מתפרסמים קודם בגרסה canary. כשהתוספות והשינויים נחשבים בטוחים ויציבים, הם מקודמים לגרסה stable.
מזהי החברים בכללי WAF שהוגדרו מראש
כלל WAF מוגדר מראש מכיל כמה ביטויים, ולכל אחד מהם יש חתימה משלו.
לדוגמה, כלל ה-WAF שהוגדר מראש xss-v422-stable כולל ביטוי שנקרא owasp-crs-v042200-id941100-xss, שתואם למזהה הכלל id941100 בגרסה 4.22. אתם יכולים להשתמש בחתימות כדי להחריג ביטויים ספציפיים, למשל אם ביטוי מסוים מפעיל באופן עקבי תוצאה חיובית מוטעית. למידע נוסף, קראו את המידע על פתרון בעיות של תוצאות חיוביות כוזבות.
למידע על קבוצת כללי הליבה ועל כוונון ברמות רגישות שונות, קראו את המאמר כוונון כללי WAF של Cloud Armor.
אופרטור לכללי WAF שהוגדרו מראש
| ביטויים | תיאור |
|---|---|
evaluatePreconfiguredWaf(string, MAP<string, dyn>) |
הפונקציה מחזירה את הערך true אם אחת מהחתימות של WAF בקבוצת הכללים שצוינה של WAF מחזירה את הערך true. הארגומנט הראשון הוא השם של קבוצת הכללים של WAF, למשל xss-v422-stable. הארגומנט השני (אופציונלי) הוא מפה שבה המפתח הוא מחרוזת והערך מוקלד באופן דינמי בהתאם למפתח. מטרת הארגומנט הזה היא לכוונן את החתימות של ה-WAF שמוערכות. המפתחות הקבילים כוללים את המפתחות הבאים:
המפתחות |
evaluatePreconfiguredWaf(string, LIST) |
הפונקציה מחזירה את הערך הארגומנט הראשון הוא השם של כלל ה-WAF שהוגדר מראש, למשל |
דוגמאות לכללי WAF שהוגדרו מראש
הביטוי הבא משתמש בכלל WAF שהוגדר מראש
xss-v422-stableכדי לצמצם התקפות XSS:evaluatePreconfiguredWaf('xss-v422-stable')הביטוי הבא משתמש בכל הביטויים מכלל ה-WAF שהוגדר מראש
xss-v422-stable, חוץ ממספרי החברים941100ו-941110:evaluatePreconfiguredWaf('xss-v422-stable', {'opt_out_rule_ids': ['owasp-crs-v042200-id941100-xss', 'owasp-crs-v042200-id941110-xss']})הביטוי הבא משתמש בכלל WAF שהוגדר מראש כדי לצמצם את ההתקפות של הזרקת SQL מטווח כתובות ה-IP של
198.51.100.0/24:inIpRange(origin.ip, '198.51.100.0/24') && evaluatePreconfiguredWaf('sqli-v422-stable')הביטוי הבא משתמש בכלל WAF שהוגדר מראש
xss-v422-stableכדי לצמצם התקפות XSS לבקשות אלexample.com, לא כולל נתיבים שמתחילים ב-/login/api/:request.headers['host'].lower() == 'example.com' && !request.path.startswith('/login/api/') && evaluatePreconfiguredWaf('xss-v422-stable')
מפעילים אחרים
| ביטויים | תיאור |
|---|---|
evaluateThreatIntelligence(string)evaluateThreatIntelligence(string, LIST)evaluateThreatIntelligence(string, string, LIST)
|
הפונקציה מחזירה הארגומנט הראשון הוא השם של פיד Google Threat Intelligence, למשל |
evaluateAddressGroup(string, string)evaluateAddressGroup(string, string, LIST)evaluateOrganizationAddressGroup(string, string)evaluateOrganizationAddressGroup(string, string, LIST)
|
הפונקציה מחזירה את הערך הארגומנט הראשון הוא השם של קבוצת הכתובות. הארגומנט השני קובע מאיפה כתובת ה-IP נשלפת, והוא יכול להיות |
evaluateAdaptiveProtection(string) |
הפונקציה מחזירה את הערך הארגומנט הוא המזהה של התראה ספציפית שנוצרה על ידי ההגנה המותאמת כשזוהתה התקפה. |
evaluateAdaptiveProtectionAutoDeploy() |
הפונקציה מחזירה את הערך |
דוגמאות
הביטוי הבא משווה את הבקשה הנכנסת לפיד
iplist-known-malicious-ipsשל Google Threat Intelligence, כדי להגן מפני הרשימה הידועה של כתובות IP זדוניות:evaluateThreatIntelligence('iplist-known-malicious-ips')הביטוי הבא משווה בין הבקשה הנכנסת לבין הפיד
iplist-known-malicious-ipsשל Google Threat Intelligence, כדי להגן מפני הרשימה הידועה של כתובות IP זדוניות, חוץ מכתובות ה-IP ב-203.0.113.0/24:evaluateThreatIntelligence('iplist-known-malicious-ips', ['203.0.113.0/24'])הביטוי הבא בודק אם כותרת הבקשה המותאמת אישית של כתובת ה-IP של המשתמש תואמת לקבוצת הכתובות שנקראת
my-own-list-of-bad-ips:evaluateAddressGroup('my-own-list-of-bad-ips', origin.user_ip)