מודל האבטחה

מי מזדהה איך ב-WIZZO CMS, מה הליבה מגנה עליו בפועל, ומה נשאר באחריות מפתח האתר: מפת הנקודות הציבוריות, סוגי האימות והציפיות.

⏱ 5 דק' קריאה 821 מילים ערוך דף זה ב-GitHub

העמוד הזה הוא המפה: מי יכול להגיע לאיזה חלק במערכת, איך הוא מזדהה, ואיפה הליבה עוצרת ומפתח האתר צריך להמשיך. הוא לא מחליף את צ'קליסט ההתקשחות (מה להגדיר באתר חדש) ואת CSRF, XSS ו-SQL injection (איך כותבים קוד נכון), אלא נותן את התמונה שמסבירה למה שניהם נחוצים.

system/ בעמוד הזה הוא תיקיית הליבה הפרוסה (api/core בריפו), ו-{admin} הוא CONFIG::$admin_url.

סוגי המזדהים#

מיאיך מזדההאיפה נבדק
מנהל אתר (פאנל הניהול)סיסמה (bcrypt) + קוד חד-פעמי, ואז עוגיית admin_sessionADMIN::is_admin(), ADMIN::get_id()
מפתח (הרשאות מוגברות בפאנל)טוקן מפתח שחתום ב-RSA על ידי WIZZO ID, נבדק מקומיתADMIN::is_developer()
משתמש אתר (לקוח של האתר)עוגיית CRM_login_<table> (LOGIN) או CRM_user_<table> (COOKIES::user_log)LOGIN::is_logged(), COOKIES::user_is_logged()
משימת cronטוקן tk מול CRM_params.cron_runner_token, בהשוואה בטוחה (hash_equals)cron_runner::index()
שירותי Market ו-MCPמפתח API או Bearer token מול טבלת טוקנים, ובחלק מהנקודות גם רשימת IPWIZZO_KEY, controllers/mcp.php
אורחכלוםכל מה שלא נחסם במפורש

מנהלי אתר#

התחברות לפאנל היא POST /system/admin_login?action=login. הליבה בודקת Referer מול הדומיינים המותרים, בודקת סיסמה עם bcrypt, מגבילה ניסיונות (5 כשלונות למשתמש ו-15 ל-IP בתוך 10 דקות), ואז דורשת קוד חד-פעמי. אחרי ההתחברות נוצר טוקן אקראי של 64 תווי hex (bin2hex(random_bytes(32))) שנשמר ב-CRM_adminPanel_sessions יחד עם ה-IP וה-User-Agent, ועוגיית admin_session (HttpOnly, Secure, SameSite=Lax) מחזיקה אותו. אורך הסשן הוא 7 ימים.

אפשר להוסיף שער מדינות (CONFIG::$admin_countries) שחוסם גישה לפאנל מ-IP שלא בארצות המותרות. פרטי התהליך המלאים בעמוד אימות והרשאות לפי קבוצות ב-הרשאות.

משתמשי אתר#

הליבה מספקת שתי דרכים להזדהות של לקוחות האתר, ושתיהן אופציונליות: מחלקת LOGIN (טבלת users, טוקנים ב-users_logins, מגבלת מכשירים) והמנגנון הישן שב-COOKIES::user_log. שתיהן מבוססות על MISC::encode, כלומר מידת האבטחה שלהן שווה לסודיות המפתח שהגדרתם. פרטים ב-משתמשי אתר.

מה הליבה מגינה עליו#

  • סיסמאות מנהלים: bcrypt, הגבלת ניסיונות, קוד חד-פעמי.
  • סשן הניהול: טוקן אקראי בצד שרת, עוגייה HttpOnly, פג תוקף ונבדק בכל בקשה מול בסיס הנתונים.
  • קבצי הגדרות רגישים: market_service::protect_settings_dir() כותבת system/.htaccess שחוסם גישת HTTP לקובצי market_settings.json*, system_tags.json, config.php, קבצי *_key.json / *_keys.json וקבצים שמתחילים בנקודה.
  • מנהל הקבצים: מוגבל לשורש האתר, נועל את תיקיית הליבה ומסתיר קבצים רגישים, דורש הרשאת מפתח ואסימון CSRF, ומתעד כל פעולה ב-CRM_file_manager_log. ראו מנהל קבצים.
  • cron: טוקן שנבדק ב-hash_equals, וריצה ידנית דורשת טוקן או אדמין.
  • סינון בסיסי של קלט: MISC::init_security() דוחה בקשות שנראות כמו SQL injection (ראו בהמשך מה הוא לא).

מה הליבה לא עושה בשבילכם#

הרשימה הזו חשובה יותר מהקודמת, כי כאן נולדים רוב הפערים.

ה-WAF המובנה הוא היוריסטיקה, לא הגנה
MISC::init_security() מחפש מילות מפתח של SQL בערכי $_GET ובשמות המפתחות של $_GET ו-$_POST. הוא לא בודק ערכי $_POST (הבדיקה מושבתת בקוד), ובדיקת קבצי ההעלאה MISC::is_file_secure() מושבתת (היא מחזירה true מיד). אל תסתמכו עליהם: כל קלט עובר דרך הבילדר של DB או DB::escape, ראו CSRF, XSS ו-SQL injection.

  • אין escape אוטומטי בתבניות. {$x} ב-Smarty מדפיס את הערך כמו שהוא. אתם מוסיפים |escape.
  • אין הגנת CSRF גלובלית. אסימון CSRF נאכף רק במנהל הקבצים ובטופס ההתחברות. פעולות POST אחרות בפאנל, וכל נקודת קצה של האתר שלכם, חשופות אם אינכם מוסיפים בדיקה.
  • אין כותרות אבטחה. הליבה לא שולחת Content-Security-Policy, X-Frame-Options, Strict-Transport-Security או Referrer-Policy (פרט ל-nosniff בהורדות של מנהל הקבצים). מגדירים אותן בשרת.
  • אין שכבת הרשאות מרכזית על /system/*. ראו בסעיף הבא.
  • ההעלאה ב-STORAGE חוסמת רשימה שחורה של סיומות ולא מוודאת MIME או גודל. ראו אבטחת העלאות.
  • המפתחות הם ברירת המחדל עד שאתם מחליפים אותם. ראו הצפנה.

נקודות קצה ציבוריות: /system/<controller>#

ב-system/controllers/ יושבים בקרי מערכת. שלא כמו בקרי האתר שלכם, שנטענים רק אם יש להם שורה פעילה ב-CRM_modules, בקר מערכת נטען כל עוד הקובץ קיים, וכל מתודה ציבורית בו היא נקודת קצה (/system/<controller>/<method>). אין בדיקת הרשאה מרכזית: כל בקר אחראי לעצמו.

קבוצהדוגמאותהגנה
מוגנים בטוקןcron_runner, agent_mcp (גם לפי IP), mcp (Bearer)נבדק בבקר
דורשים אדמיןנקודות ההעלאה של Tools (gallery_upload, CKEditor_upload*, save_url_to_storage)ADMIN::is_admin()
פתוחים לציבורcore_ping, cache_cleanup, admin_session_cleanup, system_health, ai_cron, Tools::cron_*אין בדיקה בבקר; רובם מנקים או מדווחים, אבל ai_cron מריץ כלי AI מוגדרים

העיקרון למפתח האתר: כשאתם כותבים בקר משלכם, האימות הוא חלק מהמתודה. בקר שמחזיר מידע או משנה מצב ושאין בו בדיקה, פתוח לכולם. ראו גם בקרי מערכת.

חלוקת האחריות#

נושאהליבהמפתח האתר
הצפנת עוגיות וטוקניםמספקת MISC::encodeמגדיר מפתחות אקראיים בהתקנה
SQLהבילדר מקצה ערכים כמחרוזות מוגנותמשתמש בבילדר, (int) למספרים, DB::escape בתוך מרכאות ב-SQL גולמי, רשימה לבנה ל-order_by ושמות עמודות
פלט HTMLMISC::special_chars()`
CSRFgenerate_csrf_cookie / verify_csrf_tokenקורא להם בכל POST שמשנה מצב
העלאותSTORAGE חוסם סיומות הרצה מוכרותמגביל סוגים וגודל, ומוודא שהספרייה לא מריצה קוד
כותרות HTTP ו-HTTPSכמעט כלום (ראו למעלה)מגדיר HTTPS, HSTS, CSP ועוד בשרת
גיבוייםאיןמגדיר ובודק שחזור

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.