העמוד הזה הוא המפה: מי יכול להגיע לאיזה חלק במערכת, איך הוא מזדהה, ואיפה הליבה עוצרת ומפתח האתר צריך להמשיך. הוא לא מחליף את צ'קליסט ההתקשחות (מה להגדיר באתר חדש) ואת CSRF, XSS ו-SQL injection (איך כותבים קוד נכון), אלא נותן את התמונה שמסבירה למה שניהם נחוצים.
system/ בעמוד הזה הוא תיקיית הליבה הפרוסה (api/core בריפו), ו-{admin} הוא CONFIG::$admin_url.
סוגי המזדהים#
| מי | איך מזדהה | איפה נבדק |
|---|---|---|
| מנהל אתר (פאנל הניהול) | סיסמה (bcrypt) + קוד חד-פעמי, ואז עוגיית admin_session | ADMIN::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 מול טבלת טוקנים, ובחלק מהנקודות גם רשימת IP | WIZZO_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 (ראו בהמשך מה הוא לא).
מה הליבה לא עושה בשבילכם#
הרשימה הזו חשובה יותר מהקודמת, כי כאן נולדים רוב הפערים.
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 ושמות עמודות |
| פלט HTML | MISC::special_chars() | ` |
| CSRF | generate_csrf_cookie / verify_csrf_token | קורא להם בכל POST שמשנה מצב |
| העלאות | STORAGE חוסם סיומות הרצה מוכרות | מגביל סוגים וגודל, ומוודא שהספרייה לא מריצה קוד |
| כותרות HTTP ו-HTTPS | כמעט כלום (ראו למעלה) | מגדיר HTTPS, HSTS, CSP ועוד בשרת |
| גיבויים | אין | מגדיר ובודק שחזור |