כתובת URL מרגישה פרטית, כי רק מי ששלחתם לו אותה אמור להחזיק בה. בפועל, URL הוא אחד מפריטי המידע שנרשמים הכי הרבה ברשת: מערכות שמעולם לא ביקשו את רשותכם, ושאין לכם דרך לבדוק אותן, רושמות אותו, מעתיקות אותו ומעבירות אותו הלאה. כאן מפורט בדיוק איפה הוא דולף, ואיך מתכננים קישורים שעומדים בזה. זו גם הסיבה שמחולל קישורים סודיים חד-פעמיים שומר את מפתח הפענוח אחרי הסימן # בקישור: החלק הזה אף פעם לא מגיע ליומן של שרת.
איפה ה-URL דולף
- היסטוריית הדפדפן. כל URL שהמשתמש מבקר בו נשמר מקומית, ויכול להסתנכרן למכשירים אחרים וגם לשירות הסנכרון של יצרן הדפדפן.
- יומני הגישה של שרת ה-HTTP. רוב השרתים רושמים כברירת מחדל את נתיב הבקשה המלא ואת מחרוזת השאילתה. לכל מי שיש גישה ליומנים יש גם את ה-URL.
- פרוקסי הפוך ורשתות CDN. Cloudflare, Fastly, מאזן העומסים שלכם: כולם רושמים את ה-URL, וכל אחד מהם לפי מדיניות שמירה משלו.
- צינורות לאיסוף יומנים. יומני גישה כמעט אף פעם לא נשארים על מכונה אחת. הם נשלחים לשירותי לוגים וניטור מרכזיים, וכך גדל מספר המערכות שמחזיקות את ה-URL.
- כותרות Referer. כשהדף מקשר למשאב של צד שלישי, הדפדפן יכול לשלוח את ה-URL של דף המקור בכותרת
Referer. סקריפטים של סטטיסטיקות, סרטונים מוטמעים ופיקסלים של פרסומות מקבלים אותו. - תוספים לדפדפן. תוספים עם הרשאה לקרוא את היסטוריית הגלישה רואים כל URL, כולל החלק שאחרי הסימן #.
- סנכרון סימניות. כתובות URL שנשמרו בסימניות מסתנכרנות בין המכשירים של המשתמש ולשרתים של יצרן הדפדפן.
- בוטים של תצוגה מקדימה. Slack, Teams, iMessage, LinkedIn ותוכנות אימייל טוענים את ה-URL כדי להציג תצוגה מקדימה, בשקט, ברגע שההודעה נשלחת.
- פרוקסי ארגוניים ושערי אימייל. ארגונים רבים בודקים, משכתבים ורושמים כל URL שחוצה את הגבול שלהם.
האם HTTPS שומר על פרטיות ה-URL?
לא. HTTPS מצפין את ה-URL בזמן המעבר ותו לא; שני הקצוות עדיין שומרים אותו. כדאי לדייק כאן, כי "החיבור מוצפן" מתפרש בטעות כ"ה-URL פרטי".
TLS מצפין את הנתיב ואת מחרוזת השאילתה בזמן המעבר: מי שמאזין לרשת בין הדפדפן לשרת לא יכול לקרוא את הכתובת /reset?token=.... מה ש-TLS לא מסתיר: את שם המארח של היעד (שגלוי בשאילתת ה-DNS ובשדה ה-SNI של TLS ברוב החיבורים כיום), ואת כל מה שקורה בקצוות. הדפדפן עדיין רושם את ה-URL המלא בהיסטוריה, והשרת עדיין כותב אותו ליומן הגישה שלו. הצפנה בזמן המעבר מגינה על הקו, לא על שני הקצוות, ובקצוות בדיוק כתובות URL דולפות.
דוגמה מעשית: חייו של URL אחד
עקבו אחרי URL רגיש אחד, למשל קישור לאיפוס סיסמה, https://example.com/reset?token=8f3a91..., מהשליחה ועד הלחיצה:
- ספק האימייל שומר את ההודעה (כולל ה-URL) ללא הגבלת זמן, וסורק האבטחה שלו עשוי לטעון את ה-URL כבר במסירה.
- שער האימייל של הנמען משכתב את ה-URL ורושם אותו, ואחר כך טוען אותו שוב ברגע הלחיצה.
- DNS מתרגם את
example.comלכתובת: שם המארח (לא הנתיב) נמצא עכשיו ביומנים של שרת ה-DNS. - שרת האינטרנט כותב את שורת הבקשה המלאה ליומן הגישה שלו. רשומה בפורמט "combined", ברירת המחדל של nginx/Apache, נראית כך:
203.0.113.7 - - [14/Jul/2026:09:12:45 +0000]
"GET /reset?token=8f3a91... HTTP/1.1" 200 5123 "-" "Mozilla/5.0 ..."
- ה-CDN שלפניו רושם את אותו URL, עם מדיניות שמירה משלו.
- סקריפט הסטטיסטיקות בדף רושם את ה-URL של הדף, כולל מחרוזת השאילתה, במערכת של צד שלישי, אלא אם הוגדר במפורש להסיר אותה.
- הדפדפן שומר את ה-URL בהיסטוריה ומסנכרן אותו.
שליחה אחת, שבעה עותקים, אצל חמישה ארגונים לפחות. שום דבר מזה לא דרש התקפה: כך הרשת עובדת, בדיוק כפי שתוכננה.
כותרת Referer בפועל
אם דף הצגת הסוד שלכם מקשר למשאב חיצוני כלשהו (גופן מ-CDN, סקריפט סטטיסטיקות, תמונה מוטמעת), הדפדפן עשוי לשלוח את ה-URL של הדף בכותרת Referer למקור הזה.
דפדפנים מודרניים משתמשים כברירת מחדל ב-strict-origin-when-cross-origin (MDN: Referrer-Policy), שמקצר את ה-referrer בבקשות למקור אחר כך שנשאר רק המקור (https://example.com/ במקום הנתיב המלא). זו התקדמות אמיתית, אבל לא כדאי לסמוך עליה: בקשות לאותו מקור עדיין נושאות את ה-URL המלא, מדיניות ברמת הדף יכולה להחליש את ברירת המחדל, ותוכנות ישנות ו-webview מוטמעים מתנהגים כל אחד אחרת.
שתי דרכים מעשיות לצמצם את הבעיה:
<!-- Strip the referer for outbound requests on the page -->
<meta name="referrer" content="no-referrer" />
Referrer-Policy: no-referrer
הגרסה של כותרת ה-HTTP חלה על כל האתר; תגית ה-meta חלה על הדף הספציפי. השתמשו בשתיהן, כדי שתהיה שכבת הגנה נוספת. ועוד יותר טוב: הגישו דפים רגישים בלי שום משאבים של צד שלישי, כך שלא יהיה למי לשלוח referrer.
האם טוקן בטוח יותר בנתיב, במחרוזת השאילתה או בחלק שאחרי הסימן #?
רק החלק שאחרי הסימן # לא נשלח בבקשה, ולכן רק הוא לא מגיע ליומני השרת; הנתיב ומחרוזת השאילתה שקולים. המקום שבו שמים את הטוקן ב-URL קובע מי רואה אותו:
| מיקום | נשלח לשרת? | ביומני השרת? | ב-Referer? | בהיסטוריית הדפדפן? |
|---|---|---|---|---|
נתיב (/s/abc123) | כן | כן | תלוי במדיניות | כן |
שאילתה (?token=abc123) | כן | כן | תלוי במדיניות | כן |
החלק שאחרי # (#abc123) | לא | לא | לא | כן |
החלק שאחרי הסימן # באמת שונה: לפי RFC 3986, סעיף 3.5 הוא מעובד בצד הלקוח ואף פעם לא נכלל בבקשת ה-HTTP. לכן כלי הדבקה עם הצפנה מקצה לקצה שמים בו את מפתח הפענוח: השרת לא מקבל אותו בכלל. ובכל זאת הוא לא בלתי נראה. היסטוריית הדפדפן, תוספים וכל JavaScript שרץ בדף יכולים לקרוא אותו. ההבדל בין נתיב לשאילתה, לעומת זאת, לא משנה דבר מבחינת פרטיות: שניהם מגיעים לאותם יומנים.
הבעיה של טוקנים לאיפוס סיסמה
טוקנים רגישים בתוך URL הם סוג מוכר של פגיעות. CWE-598 של MITRE ("Use of GET Request Method With Sensitive Query Strings") מתאר בדיוק את זה: מידע רגיש במחרוזות שאילתה מגיע ליומנים, להיסטוריות ול-referrer, בלי קשר להצפנה בזמן המעבר. לכן תהליכי איפוס סיסמה שבנויים היטב אף פעם לא סומכים רק על כך שה-URL נשאר סודי. הם הופכים את הטוקן לחד-פעמי, לקצר חיים ולקשור לפעולה שבאה אחריו (הגדרת סיסמה חדשה), כך שטוקן שנמצא ביומן שלושה שבועות אחר כך לא שווה כלום.
זה הלקח הכללי: בדרך כלל אי אפשר להשאיר URL מחוץ ליומנים, אבל אפשר לדאוג שה-URL שנרשם יהיה חסר ערך עד שמישהו יקרא אותו.
תכנון כתובות URL שמותר להן לדלוף
הניחו שכל URL שאתם יוצרים יופיע בסוף במקום לא צפוי, ותכננו כך שזה לא ישנה:
- שימוש חד-פעמי. מחקו את הסוד אחרי הקריאה המוצלחת הראשונה, כך ש-URL שדלף כבר לא יעבוד כשהוא יופיע בהיסטוריה של מישהו.
- תפוגה קצרה. הגבילו את חלון הדליפה. URL שעבד חמש דקות שווה הרבה פחות מ-URL שעבד שבוע.
- ביטוי סיסמה שנמסר בערוץ נפרד. דרשו סוד שמעולם לא היה ב-URL. כך ה-URL לבדו, הדבר היחיד שיש ביומנים, לא מספיק.
- הפרדה בין טעינה להצגה. החזירו מטא-נתונים בבקשת
GETושחררו את התוכן רק בבקשתPOSTמפורשת, כדי שבוטים של תצוגה מקדימה וסורקים לא יוכלו לצרוך את הסוד. - בלי משאבים של צד שלישי בדפים רגישים, ובנוסף
Referrer-Policy: no-referrerו-<meta name="robots" content="noindex">. - הסתירו נתיבים סודיים ביומנים שלכם. ב-nginx, מפו את ה-URI של הבקשה לפני הרישום (ראו את התיעוד של ngx_http_log_module לגבי
log_format):
map $request_uri $loggable_uri {
~^/s/ "/s/[redacted]";
default $request_uri;
}
log_format redacted '$remote_addr - $remote_user [$time_local] '
'"$request_method $loggable_uri" $status';
access_log /var/log/nginx/access.log redacted;
אתם שולטים רק ביומנים שלכם. העותקים ב-CDN, בפרוקסי ובדפדפן נשארים, ובדיוק בגלל זה שלושת הסעיפים הראשונים ברשימה נושאים את רוב המשקל.
איך זה מעצב את הקישורים הסודיים
מודל האיומים הזה הוא הסיבה שהקישורים הסודיים של LinkPilot עובדים כמו שהם עובדים: ה-URL נחשב כמשהו שידלוף בהכרח, ולכן ה-URL לבדו אף פעם לא מספיק. בקשת GET מחזירה רק מטא-נתונים; כדי לקבל את התוכן צריך הצגה מפורשת בבקשת POST, ואפשר להגן עליה גם בביטוי סיסמה שעובר hash של SHA-256 בצד הלקוח. סודות שנמחקו, שפג תוקפם או שבוטלו מחזירים HTTP 410, והתוכן שלהם נדרס באופן בלתי הפיך. תגובות ההצגה נושאות Cache-Control: no-store, ואירועי צפייה רושמים hash של כתובת ה-IP עם salt שמתחלף כל יום, ולא את הכתובת עצמה. ומגבלה אחת שאנחנו מציינים בגלוי בדף ארכיטקטורת האבטחה: מפתח הפענוח נמצא בחלק של הקישור שאחרי הסימן #, ולכן צריך להתייחס לקישור כולו כאל הסוד. זו בדיוק הסכנה שהמאמר הזה עוסק בה. תפוגה קצרה, מחיקה לאחר קריאה וביטוי סיסמה שנמסר בערוץ נפרד הם מה שמגביל את הנזק כשקישור דולף.
עדכון, 29 בספטמבר 2026: במקור נכתב בפסקה הזו ש-LinkPilot לא מציע הצפנה מקצה לקצה. עכשיו הוא מצפין בדפדפן תוכן טקסט, כולל קבצים מצורפים.
נסו בחינם, בלי הרשמה
הודעה שמשמידה את עצמה
שלחו פתק שנעלם אחרי קריאה אחת.
מגבלות
תכנון נכון של URL לא פותר הכול. הוא לא שולט במה שהנמען עושה אחרי קריאה לגיטימית, הוא לא יכול למחוק עותקים שכבר נמצאים אצל צדדים שלישיים, והוא לא יציל URL שמכיל מידע אישי גלוי לעין: אם כתובת האימייל של משתמש נמצאת במחרוזת השאילתה, שום תפוגה לא תמנע את הרישום שלה. הכלל שתמיד תקף: לעולם אל תכניסו ל-URL מידע שתצטרכו למחוק אחר כך, כי כמעט בלתי אפשרי למחוק URL מכל מקום שאליו הוא הועתק. במקום זה, תכננו כתובות URL שאין להן ערך כשהן דולפות.
קריאה נוספת
- איך עובדים קישורים סודיים חד-פעמיים
- סורקי קישורים וסודות חד-פעמיים
- שיתוף סיסמאות מאובטח: השוואה בין 5 שיטות
