الأمان

    كيف تعمل الروابط السرية لمرة واحدة

    الرابط السري لمرة واحدة يُظهر محتواه مرة واحدة: يشفره المتصفح، ولا يخزن الخادم إلا النص المشفر، وأول إظهار يحذف النسخة المخزنة نهائيًا.

    W. Miller · آخر تحديث · عن LinkPilot

    الرابط السري لمرة واحدة عنوان URL يُظهر محتواه مرة واحدة بالضبط ثم يتعطل نهائيًا. يشفر متصفح المرسل السر باستخدام AES-GCM-256، ولا يخزن الخادم إلا النص المشفر، وينتقل المفتاح في الجزء الذي يلي #k= في الرابط، وهو جزء لا يرسله المتصفح أبدًا. وعندما يفتح المستلم الرابط أول مرة، يُفك تشفير المحتوى وتُحذف النسخة المخزنة نهائيًا في العملية نفسها.

    يمكنك إنشاء رابط كهذا بدون حساب عبر أداة إنشاء الروابط السرية المجانية.

    الآلية بسيطة، لكن الحالات الحدية هي ما يستحق الانتباه، ففيها تسرّب التطبيقات المهملة الأسرار دون أن يلاحظ أحد.

    المسار الأساسي

    1. يلصق المرسل السر. يولّد المتصفح مفتاحًا عشوائيًا، ويشفر المحتوى باستخدام AES-GCM-256 عبر Web Crypto API، ولا يرسل إلا النص المشفر. يخزنه الخادم تحت نهاية رابط عشوائية يصعب تخمينها ويعيد عنوان URL، فيضيف المتصفح المفتاح إليه في الجزء #k=، وهذا الجزء لا يغادر جهاز المرسل.
    2. يشارك المرسل عنوان URL عبر أي قناة: البريد الإلكتروني أو المحادثة أو الرسائل النصية.
    3. يفتح المستلم عنوان URL. طلب GET العادي لا يعيد إلا الحالة. وعندما يضغط على زر الإظهار، يعلّم الخادم السر بأنه استُهلك ويعيد النص المشفر في خطوة واحدة لا تنقسم، ثم يفك متصفح المستلم تشفيره بالمفتاح الموجود في الجزء الذي يلي علامة #.
    4. أي زيارة لاحقة تحصل على صفحة تقول إن المحتوى حُذف نهائيًا، بدل المحتوى.

    الخطوة الحاسمة هي الخطوة 3. إن جرت القراءة وتحديث الحالة في استعلامين منفصلين، SELECT للتحقق ثم UPDATE للتعليم، فقد يجتاز زائران متزامنان التحقق قبل أن يكتب أي منهما. فيحصل كلاهما على المحتوى. هذا خطأ TOCTOU المعروف (time-of-check to time-of-use، أي الفارق بين وقت التحقق ووقت الاستخدام)، وهو يحوّل ضمان «مرة واحدة بالضبط» إلى «مرة واحدة في الغالب».

    لماذا يجب أن يكون الحذف والقراءة عملية واحدة؟

    لأن زائرين متزامنين قد يجتازان التحقق معًا قبل أن يعلّم أي منهما السر بأنه استُهلك. والحل أن يُدمج التحقق والتعليم والقراءة في عملية واحدة على قاعدة البيانات. في Postgres، وباستخدام UPDATE ... RETURNING، يبدو ذلك هكذا:

    UPDATE secrets
    SET burned_at = now()
    WHERE slug = $1
      AND burned_at IS NULL
      AND expires_at > now()
    RETURNING payload;
    

    يقفل UPDATE الصف، فتُنفَّذ الطلبات المتزامنة واحدًا تلو الآخر: أولها يطابق شرط WHERE ويضبط burned_at ويستلم المحتوى عبر RETURNING. وكل طلب بعده يجد burned_at مضبوطًا مسبقًا، فلا يطابق أي صف ويحصل على حالة الحذف. لا توجد فجوة بين «التحقق» و«الاستهلاك» لأنهما العبارة نفسها.

    لهذا السبب تحديدًا يسجل LinkPilot المشاهدات عبر دالة في قاعدة البيانات تنفذ ذلك في خطوة واحدة لا تنقسم، فلا يمكن لمحاولات الإظهار المتزامنة أن تسرّب السر مرتين. إن كنت تقيّم أداة ما، فهذا سؤال مشروع توجهه إلى المزوّد مباشرة: هل يجري الحذف والقراءة في عملية واحدة؟

    لأن 410 Gone تعني أن المورد كان موجودًا وأصبح غير متاح نهائيًا، وهذا وصف السر المحذوف بالضبط. بعد استهلاك الرابط، يجب أن يفشل فشلًا واضحًا ودائمًا. يفعل LinkPilot أمرين عند الحذف:

    • يُستبدل المحتوى المخزن بالقيمة [REDACTED] في عملية الكتابة نفسها التي تغيّر الحالة، فحتى لو اختُرقت قاعدة البيانات لاحقًا لا يمكن استرجاع سر مستهلك.
    • تعيد محاولات الإظهار اللاحقة HTTP 410 Gone مع صفحة واضحة تقول «شوهد ودُمّر مسبقًا».

    410 هو رمز الحالة الصحيح: معناه أن المورد كان موجودًا وأصبح غير متاح عمدًا ونهائيًا، بخلاف 404 الذي يقول «لم أسمع به قط». والفرق مهم للبشر أيضًا: المستلم الذي يرى «هذا السر شوهد مسبقًا» يعرف أن عليه إبلاغ المرسل، فيراجع المرسل سجل التدقيق ويغيّر بيانات الدخول إن لم يكن المستلم هو من فتحه.

    نهايات روابط يصعب تخمينها، ولماذا لا تكفي

    نهاية الرابط هي ما يفصل الإنترنت العام عن نص مشفر لم يُقرأ بعد (فالمفتاح في الجزء الذي يلي علامة # لا على الخادم)، لذا يجب أن تحمل عشوائية حقيقية. نهاية رابط مأخوذة من مصدر عشوائي آمن تشفيريًا، بطول 22 حرفًا من base62 مثلًا، تحمل نحو 128 بت، فلا يكون تعداد الاحتمالات هجومًا واقعيًا بأي معدل طلبات يستطيع خادم تحمّله.

    لكن عشوائية نهاية الرابط لا تحمي إلا من التخمين. ولا تفعل شيئًا إن رأى أحد عنوان URL: في سجل المتصفح، أو سجلات الخوادم الوسيطة، أو رسائل بريد أُعيد توجيهها، أو مشاركة الشاشة، أو برامج إدارة الحافظة. لهذا تضيف التطبيقات الجادة طبقات أخرى:

    • انتهاء الصلاحية، فيتعطل عنوان URL الذي رآه أحد في الموعد المحدد.
    • عبارة مرور، فلا يكفي عنوان URL الذي رآه أحد وحده.
    • الحذف بعد القراءة، فيصبح عنوان URL الذي رآه أحد بلا قيمة بعد القراءة المشروعة.

    تطبيقات المحادثة (Slack و Teams و iMessage) وأدوات فحص أمان البريد الإلكتروني تعرض معاينة لعناوين URL بجلبها بطلب GET لحظة تسليم الرسالة. إن كانت نقطة الإظهار تحذف المحتوى عند GET، فإن أداة المعاينة تدمّر السر قبل أن يراه الإنسان، وهذا أكثر أعطال أدوات الحذف بعد القراءة الساذجة شيوعًا في الواقع.

    وسائل الحماية كما يطبقها LinkPilot:

    • فصل البيانات الوصفية عن الإظهار. طلب GET على نقطة الإظهار لا يعيد إلا الحالة وما إذا كانت عبارة المرور مطلوبة. ولا تُسجَّل المشاهدة إلا عند طلب POST صريح، وهو ما يحدث حين يضغط الإنسان على زر الإظهار.
    • بوابة عبارة المرور (Pro). عند ضبط عبارة مرور، لا يُعاد المحتوى لأي أحد، روبوتًا كان أو إنسانًا، دون التجزئة الصحيحة لعبارة المرور.
    • Cache-Control: no-store على كل استجابة إظهار، فلا تخزّن الخوادم الوسيطة محتوى الأسرار مؤقتًا أبدًا.

    توثّق صفحة بنية الأمان في LinkPilot هذه المعالجة من أولها إلى آخرها.

    دورة الحياة، حالة بعد حالة

    الحالةسببهاما يراه الزائرهل يمكن استرجاع المحتوى؟
    نشطالإنشاءصفحة الإظهار (مع طلب عبارة المرور إن ضُبطت)نعم، إظهار واحد متاح
    محذوف نهائيًابلوغ حد عدد المشاهدات«شوهد ودُمّر مسبقًا»، مع HTTP 410لا، فقد استُبدل المحتوى
    منتهي الصلاحيةمرور موعد انتهاء الصلاحيةصفحة حالة انتهاء الصلاحيةلا، يُمحى عند الوصول التالي
    مُبطَليبطله المرسل من لوحة التحكميرفض الإظهار، مع HTTP 410لا، فورًا ونهائيًا

    كل انتقال بين الحالات يُسجَّل في سجل التدقيق، وهو ميزة من خطة Pro في LinkPilot. أنواع الأحداث هي created و viewed و failed_passphrase و burned و expired و revoked، ولكل منها طابع زمني وعنوان IP مجزّأ (SHA-256 مع قيمة ملح تتغير يوميًا، ولا يُخزَّن عنوان IP الأصلي أبدًا). هذا السجل هو ما يحوّل «أظنه استلمه» إلى «شوهد الساعة 10:05 من البلد المتوقع، مشاهدة واحدة، ثم حُذف نهائيًا».

    إضافات شائعة

    • بوابة عبارة المرور: اشترط عبارة مرور تُرسل عبر قناة أخرى قبل الإظهار، فلا يكون تسرّب عنوان URL وحده تسربًا للسر. هذه في LinkPilot ميزة من خطة Pro ($29 شهريًا)، مع انتهاء الصلاحية المخصص وسجل التدقيق، ولا تستطيع الأداة التي تعمل بدون حساب ضبطها. حدّد عدد المحاولات: يسمح LinkPilot بحد أقصى 5 محاولات لكل عنوان IP في الدقيقة لكل سر، ويسجل كل محاولة فاشلة.
    • انتهاء الصلاحية بالوقت: يُحذف السر بعد مدة محددة حتى لو لم يُقرأ قط. يتيح النموذج في LinkPilot بعد تسجيل الدخول 1 ساعة أو 24 ساعة أو 7 أيام في كل الخطط، مع تاريخ ووقت مخصصين في Pro، أما الأداة التي تعمل بدون حساب فتضبط 7 أيام افتراضيًا. وهذا يغطي حالة الرابط المنسي في صندوق الوارد، التي لا يعالجها الحذف بعد القراءة.
    • الإبطال اليدوي: يستطيع المرسل إبطال سر لم يُقرأ من لوحة التحكم حالما يشعر بأن شيئًا ما ليس على ما يرام. احتياط قليل الكلفة لحالة «أرسلته إلى أليكس آخر غير المقصود».

    حالات حدية تميّز التطبيقات الجيدة

    الشخص الخطأ يفتحه أولًا

    الحذف بعد القراءة لا يمنع الشخص الخطأ من المشاهدة، لكنه يجعل خطأ التسليم ظاهرًا. يصل المستلم المقصود إلى صفحة تقول إن المحتوى حُذف نهائيًا، ويُظهر سجل التدقيق مشاهدة واحدة لم تكن تتوقعها، فتغيّر بيانات الدخول. أمر مزعج، لكنه محدود: انكشاف واحد بالضبط، يُكتشف بسرعة. قارن ذلك بسر لُصق في محادثة، حيث لن تعرف أبدًا.

    مشكلة لقطة الشاشة

    «لمرة واحدة» تعني إظهارًا واحدًا، لا نسخة واحدة. يستطيع المستلم التقاط صورة للشاشة أو نسخ السر أو إعادة كتابته، ولا شيء في الرابط يمنع ذلك، والمزوّدون الذين يوحون بغير ذلك يبيعون وهمًا. الوصف الصادق: الحذف بعد القراءة يتحكم في قناة التسليم، لا في المستلم. الثقة بالمستلم شرط مسبق، لا نتيجة.

    الجلب المسبق والتحميل التخميني في المتصفحات

    بعض المتصفحات والتطبيقات تجلب مسبقًا عناوين URL التي يُرجّح أن يُضغط عليها. ولأن الأداة المبنية جيدًا لا تحذف المحتوى إلا عند طلب POST صريح، يتصرف الجلب المسبق تمامًا كأداة المعاينة: قد يجلب هيكل الصفحة، لكنه لا يجلب المحتوى أبدًا.

    • ستحتاج إلى القيمة مرة أخرى. إمكانية الاسترجاع هي الهدف الأساسي من مدير كلمات المرور، وهي عكس ما صُمم له الرابط لمرة واحدة. استخدم عنصرًا في الخزنة.
    • يحتاج إليه أكثر من مستلم. رابط واحد، قراءة واحدة. التوزيع على عدة أشخاص يعني إما إنشاء رابط لكل شخص (لا بأس، ويمكن تدقيقه) وإما الإقرار بأنك تحتاج إلى نظام مشترك للتحكم في الوصول.
    • المستهلك آلة. يجب أن تقرأ الخدمات وأنظمة CI من مدير أسرار، لا أن تضغط على روابط.

    إن أردت أن ترى الآلية وهي تعمل، فأنشئ رابطًا عبر أداة إنشاء الروابط السرية المجانية: بدون حساب، مشفر في متصفحك، ويختفي بعد أول إظهار.

    المراجع

    أدوات لهذا المقال

    الأسئلة الشائعة

    يرسل LinkPilot رابطًا سريًا يختفي بعد فتحه.

    يُشفَّر في متصفحك، ويظهر محتواه مرة واحدة، ثم يُحذف نهائيًا. بدون حساب.

    إنشاء رابط سري

    اقرأ أيضًا

    الأمان

    الروابط محدودة الصلاحية: يُحذف السر نفسه، لا التوجيه وحده

    الرابط السري محدود الصلاحية يحذف السر عند الموعد، أما رابط الاختصار المنتهي فيتوقف عن التوجيه فقط. كيف تختار المدة، وما الحالات الحدية.

    الأمان

    التشفير من جهة العميل لمشاركة الأسرار: ما يحميه وما لا يحميه

    يحمي التشفير من جهة العميل السر المخزن من المشغّل ومن تسريب قاعدة البيانات، ولا شيء غير ذلك: تُسقطه شيفرة JavaScript خبيثة والإضافات والرابط المسرَّب.

    الأمان

    مشاركة بيانات الدخول لمرة واحدة عند تهيئة العملاء

    للوكالات ومزودي الخدمات المُدارة: أرسل بيانات الدخول الأولى في رابط لمرة واحدة، وشارك تعليمات التهيئة السرية بالطريقة نفسها، وسجّل التسليم.