אתר WizzoCMS ניתן לזיהוי מבחוץ לפי צורת הנתיבים שהוא מגיש: themes/<name>/, system/js/, minify/3.js, הסיומת הכפולה .scss.css ו-tag_manager.js. מצב ההסוואה מחליף אותם בשמות ניטרליים, ב-HTML שיוצא וגם בבקשות שנכנסות, בלי להזיז אף קובץ בדיסק. הוא כבוי כברירת מחדל ומופעל על ידי הגדרה אחת באתר.
זה כיסוי שיווקי ולא אבטחה. אין כאן סוד שמוגן: ההסוואה רק מונעת מאתרים שאמורים להיראות ללא מותג להיראות כאותו מוצר. הקוד נמצא ב-collections/MASK.php.
הפעלה#
הגדרות ההסוואה הן שדות סטטיים במחלקת ההגדרות של האתר (CONFIG_USER, שממנה CONFIG יורשת). ראו גם את הטבלה ב-הגדרות.
// ערך true: מפה ברירת מחדל, כולל ה-theme הפעיל של הפלטפורמה
public static $mask = true;
// או מפה מפורשת (מומלץ, קל לבדוק בביקורת קוד): אמיתי => מוסווה
public static $mask = [
'themes/shop/' => 'lib/ui/',
'system/js/' => 'lib/js/',
'minify/' => 'lib/b/',
'tag_manager.js' => 'lib/tm.js',
];
כש-$mask === true המפה היא:
| אמיתי | מוסווה |
|---|---|
minify/ | lib/b/ |
system/js/ | lib/js/ |
tag_manager.js | lib/tm.js |
themes/<deftheme>/ | lib/ui/ (רק אם לפלטפורמה מוגדר deftheme) |
בנוסף, בכל מצב פעיל הסיומת .scss.css מוחלפת ב-.css.
מפה ריקה, חסרה או שאינה true ואינה מערך לא ריקה משאירה את ההסוואה כבויה. אתר שלא הגדיר דבר משלם בדיקת property_exists אחת לבקשה.
קידומת לא חייבת להיות תיקייה. אפשר להסוות גם נקודת קצה של בקר שהדפדפן קורא לה, למשל 'system/analytics' => 'lib/a'. אותו כלל חל על כל קידומת במפה: היא מוחלפת ב-HTML היוצא ומוחזרת לערך האמיתי בבקשה הנכנסת.
איך זה עובד#
כיוון יציאה (אמיתי למוסווה)#
MASK::out($html) מריץ החלפה אחת (strtr) על טקסט שהדפדפן מקבל. המפתחות הארוכים קודמים, וטקסט שכבר הוחלף לא נסרק שוב, כך שהקריאה אידמפוטנטית. היא רצה ב:
core.php, על כל העמוד, לפני שמירת מטמון העמודים. המטמון מכיל בייטים מוסווים, וכל דרך הגשה (טרי, gz ישיר, מפוענח) מוציאה HTML מוסווה.PAGE::parse_page, אחריparse_page_funcולכן גם בפגיעת מטמון (ראו PAGE API).- הכותרת
scriptsש-PAGE::JsIncludeJsCssשולח בתשובותpmode=empg, כי היא נושאת את רשימת הנכסים. - כל קובץ טקסט שמוגש מנתיב מוסווה ופלט של בקר שמאחורי קידומת מוסווה (CSS מקומפל, תגובת
tag_manager).
בפאנל הניהול (system_type == "admin") ההסוואה לא פועלת, והנתיבים נשארים אמיתיים.
הערכים ב-JSON עוברים טיפול מיוחד: כל קידומת שכוללת / מוחלפת גם בצורה עם \\/ (כפי ש-json_encode כותב), כך שגם הקריאה applyTags([...]) של ה-tag manager מוסווית.
כיוון כניסה (מוסווה לאמיתי)#
בראש ROUTER::parse_friendly_url נקראת MASK::in($url), כך ששאר הנתב רואה רק נתיבים אמיתיים. כשהבקשה נושאת קידומת מוסווה:
- הקידומת מוחזרת לאמיתית (הקידומת המוסווית הארוכה ביותר קובעת).
- בקשה ל-
x.cssשהמקור שלהx.scss(ושאין לה.cssפיזי) מוחזרת ל-x.scss.css. נתיבים תחתminify/לא עוברים את ההמרה הזו. - אם הנתיב האמיתי הוא קובץ סטטי שקיים בדיסק (תמונה, גופן,
.css,.js,.jsonועוד),MASKמגיש אותו בעצמו, כפי ששרת האינטרנט היה עושה, ומסיים. - אחרת (קבוצת minify, SCSS,
tag_manager, נקודת קצה)REQUEST_URIמכוון לנתיב האמיתי, ופלט הבקר עובר מסנן שמסווה אותו שוב. הנתב ממשיך כרגיל.
הגשת קובץ סטטי: Cache-Control: public, max-age=604800 (שבוע), Last-Modified ו-Expires, ותשובת 304 לפי If-Modified-Since. לגופנים נוספות הכותרות Access-Control-Allow-Origin: * ו-Cross-Origin-Resource-Policy: cross-origin. קבצי טקסט (css, js, mjs, json, map, txt, xml) עוברים הסוואה לפני ההגשה, ושאר הקבצים מוגשים כמות שהם.
הגנות בהגשה#
- נתיב עם
..או תוNULנדחה, והנתיב הממשי (realpath) חייב להישאר בתוךbase_path, אחרת404. - הקובץ נשלף רק מנתיב שעבר החלפה של קידומת מוסווית. בקשה רגילה לא עוברת דרך ההגשה הזו.
- ההגשה עצמה מותרת רק לסיומות ברשימה קבועה (תמונות, גופנים, מדיה,
css,js,json,txt,xml,pdf,wasm,zipועוד).
mask_words: זיהוי מזהים ב-JS#
מזהים שהליבה שולחת לדפדפן (למשל wz_jquery, wz_cookies) מסגירים את המערכת כמו נתיב. $mask_words מוסיפה החלפות בכיוון יציאה בלבד:
public static $mask_words = [
'wz_jquery' => 'onReady',
'wz_cookies' => 'cookieJar',
];
ההחלפה חלה על כל טקסט שהדפדפן מקבל דרך PHP, ולכן שם משתנה מוחלף בהגדרה ובכל שימוש בו בבת אחת. התנאי: הקבצים שמגדירים אותם חייבים לעבור דרך PHP, כלומר שרת האינטרנט לא אמור להגיש .js ו-.css מתחת לקידומת מוסווית בעצמו.
mask_words פועל רק כשיש מפה פעילה (בלי mask הוא מתעלם). מילה יכולה להופיע גם בשם קובץ (למשל _tumb_ בכל תמונה ממוזערת). אז בקשה לשם הניטרלי מוחזרת לקובץ האמיתי, אבל רק לקבצים בינאריים (תמונות, גופנים, מדיה, PDF). קובץ טקסט אף פעם לא נשלף בדרך הזו.
בחרו מילים ארוכות וייחודיות. ההחלפה היא החלפת מחרוזת פשוטה בכל הפלט, כך שמילה קצרה (wz) תשבור קוד, כתובות ותוכן שבמקרה מכילים אותה. בדקו את הדף בדפדפן אחרי כל שינוי במפה.
מה לא מוסווה#
הקוד קובע במפורש שלושה דברים שנשארים גלויים:
- קידומת הקוקיז
CRM_(אימות, סיכון גבוה ובלי תועלת למבקר אנונימי). - ספריות הליבה תחת
/assets/(רובן קוד צד שלישי גנרי, והמזהים שבהן כבר משתמשים בשמות ניטרליים בנתב). - ה-meta של
copyright(מבוטל ב-CONFIG::$show_wizzo_credits = false, לא על ידי ההסוואה).
גם עם הסוואה, נתיבים של בקרי ליבה (system/Tools/...) וקוד הצד של הלקוח שמפנה אליהם (למשל MISC.js) לא מוסווים אלא אם הוספתם אותם למפה. אם הסוואה חשובה, עברו על ה-HTML והסקריפטים שהדפדפן מקבל וחפשו system/ ו-wz_.
פתרון תקלות#
| סימפטום | סיבה סבירה |
|---|---|
| תמונה או גופן מנתיב מוסווה מחזירים 404 | הקובץ לא קיים בדיסק באותו נתיב אמיתי, או שהנתיב יוצא מ-base_path |
| ה-CSS נטען אבל נראה ישן | הבקשה קיבלה 304 או מטמון חזק: הנתיב נושא ?ver=, ראו צינור הנכסים ונקו מטמון |
| עמוד מהמטמון מכיל נתיבים אמיתיים | העמוד נשמר לפני שהפעלתם הסוואה. ההסוואה נשמרת בתוך המטמון, ולכן צריך לנקות מטמון עמודים אחרי הפעלה או שינוי מפה |
סקריפט נשבר אחרי mask_words | המילה מופיעה גם בטקסט אחר. הגדילו אותה או הסירו אותה |
ראו גם#
- צינור הנכסים:
minify/,.scss.cssו-tag_manager.js - ה-runtime בדפדפן:
system/js/והמזהים שנשלחים לדפדפן - PAGE API:
parse_pageו-parse_page_func - הגדרות: המפתחות
maskו-mask_words - מטמון עמודים
- כתובות ו-Router: איפה
MASK::inנכנס לנתב