דילוג לתוכן
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Certificate Transparency: איך מוצאים כל תעודה שהונפקה לדומיין שלך

איך לוגי Certificate Transparency מתעדים תעודות TLS ציבוריות, ואיך עוברים על תוצאות crt.sh לדומיין בבעלותך בלי לגעת במארחים שלו.

מתחילים7 דקות קריאהמאת NotHoly

מה זה Certificate Transparency

Certificate Transparency (CT) הוא רישום ציבורי של תעודות TLS. כשרשות תעודות (CA) מנפיקה תעודה שמקובלת באמון ציבורי, היא כותבת אותה ללוג CT אחד או יותר. כל אחד יכול לקרוא את הלוגים, ואף אחד לא יכול לערוך אותם בשקט. לבעלים של דומיין זה נותן היסטוריה שאפשר לחפש בה של תעודות ציבוריות שהונפקו לשמות תחת הדומיין, כולל תעודות שאף אחד בצוות לא זוכר שביקש.

הפרוטוקול מוגדר ב-RFC 9162, "Certificate Transparency Version 2.0," שפורסם בדצמבר 2021. הוא מחליף את המפרט המקורי, RFC 6962. לפני שמצטטים אותו, צריך לבדוק את שורת הסטטוס. RFC 9162 הוא מסמך Experimental ואינו מפרט ב-Internet Standards Track, וה-RFC עצמו אומר זאת. הוא עדיין מסמך הייחוס לאופן שבו לוגים עובדים, ודפדפנים מסתמכים על אותו תכנון.

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

למה כל תעודה ציבורית מגיעה ללוג

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

פרויקט CT מסביר את התהליך בעמוד how-it-works שלו בכתובת https://certificate.transparency.dev/howctworks/. בצורה מפושטת:

  1. ה-CA מכינה precertificate, רשומה בצורת תעודה שדפדפנים לא מקבלים כתעודה אמיתית.
  2. ה-CA שולחת את ה-precertificate ללוג CT אחד או יותר. כל לוג מחזיר Signed Certificate Timestamp (SCT), התחייבות חתומה שהלוג יכלול את הרשומה.
  3. ה-CA מנפיקה את התעודה הסופית עם ה-SCTs מצורפים, כדי שהדפדפן יוכל לוודא שהתעודה נרשמה.
  4. הדפדפן בודק את ה-SCTs. דפדפנים כמו Chrome ו-Safari אוכפים את זה על תעודות שמקובלות באמון ציבורי.

ה-precertificate פותר בעיית סדר. CA לא יכולה לקבל SCT לתעודה הסופית בלי לשלוח קודם משהו ללוג, ודפדפן לא אמור לקבל את התעודה הסופית לפני שיש לה SCT. ה-precertificate שובר את המעגל.

הלוגים הם append-only. אפשר להוסיף רשומות, אבל אי אפשר למחוק, לשנות או להכניס אותן בדיעבד. כל לוג מחזיק Merkle tree, שמאפשר לכל אחד לאמת שתעודה מסוימת כלולה בו (inclusion proof) ושהלוג רק גדל עם הזמן (consistency proof). סעיף 2 של RFC 9162 מתאר את העץ. לא צריך לממש אותו כדי להשתמש בנתונים.

שני פרטים חשובים למגינים. ראשית, ההבטחה נוגעת לרישום ואינה נוגעת לאמון. תעודה רשומה יכולה להיות תקפה, שגויה או מונפקת באופן לא תקין, והלוג לא יכול לומר מה מהשלושה. שנית, הכיסוי מוגבל לתעודות מ-CAs שמקובלות באמון ציבורי. תעודות מ-CA פרטית בדרך כלל לא מגיעות ללוג ציבורי, ולכן תוצאת CT נקייה לא מנקה את כל הנכסים שלך.

למה מגינים משתמשים ב-CT

שלושה שימושים חוזרים שוב ושוב.

מלאי. צוותים יוצרים שמות מארחים לסביבות בדיקה, לדפי שיווק, לאינטגרציות עם ספקים ולפרויקטים ישנים. רבים מהשמות האלה אף פעם לא מגיעים לקובץ ה-zone של DNS שמישהו עובר עליו. בקשת תעודה משאירה רישום, ולכן CT יכול להציף שמות שהמלאי שלך פספס.

זיהוי תעודות שאף אחד לא ביקש. אם מופיעה תעודה לדומיין שלך ואף אחד בצוות לא ביקש אותה, כדאי לבדוק. ייתכן שזה ספק שפועל בשמך, חשבון ישן, ספק ששכחת ממנו, או תוקף שהשיג שליטה בנתיב אימות. הלוג לבדו לא יכול לומר מה מאלה, ולכן מעבירים את העניין לאנשים שמפעילים את ה-DNS של הדומיין ואת חשבונות התעודות.

היגיינת מחזור חיים. תעודות שפג תוקפן עדיין מופיעות ב-CT. ההיסטוריה הזו שימושית. אפשר לראות אילו שמות היו קיימים ולמצוא שירותים שיצאו משימוש ועדיין יש להם רשומות DNS.

תוצאת CT היא כיוון לבדיקה, ועדיין לא מסקנה. שם יכול להיות ישן, להיות שייך לספק, להיות wildcard שמכסה מארחים רבים או לנבוע מטעות הקלדה. כל כיוון כזה צריך אישור מהבעלים של הנכס.

מה זה crt.sh

crt.sh הוא ממשק חיפוש ציבורי ללוגי CT. צד שלישי מפעיל אותו. אפשר לחפש בדפדפן, או לקבל JSON על ידי הוספת output=json לשאילתה. השאילתה שלך מגיעה לשירות הזה, ולכן כדאי לחפש רק דומיינים שמותר לך לדבר עליהם. שם דומיין הוא מידע ציבורי. שם של מוצר שלא הוכרז או שם מארח פנימי לא אמורים להיכנס לתיבת חיפוש של צד שלישי.

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

מעבדה מעשית: סקירת התעודות של דומיין

מה צריך

  • דפדפן
  • curl ו-jq, או Python 3 כחלופה
  • דומיין בבעלותך. אם אין דומיין כזה, אפשר להשתמש ב-example.com, דומיין ששמור לדוגמאות, כמו במעבדה הזו.

המעבדה רק קוראת נתוני CT ציבוריים. לא מתחברים לאף מארח שנמצא. שאילתת DNS על שם היא שאילתה ל-resolver ולא חיבור למארח, אבל אין להתקדם מעבר לזה בלי הרשאה של הבעלים.

שלב 1: צפייה בתוצאות בדפדפן

פותחים בדפדפן את https://crt.sh/?q=example.com ומחליפים את example.com בדומיין שלך. כל שורה היא תעודה אחת. קוראים את המנפיק, את תאריכי התוקף ואת השמות שמופיעים. אחר כך מנסים את צורת ה-wildcard, https://crt.sh/?q=%.example.com, שמבקשת שמות מתחת לדומיין, ומשווים את הספירות בין שני החיפושים.

שלב 2: ייצוא השמות

מריצים:

bash
curl -s 'https://crt.sh/?q=example.com&output=json' | jq -r '.[].name_value' | sort -u | head -50

ה-pipeline עובד בארבעה חלקים. הפקודה curl מורידה מערך JSON עם אובייקט אחד לכל תעודה. הביטוי jq -r '.[].name_value' מדפיס את השדה name_value של כל אובייקט בלי מירכאות. חלק מהרשומות מחזיקות כמה שמות שמופרדים בשורות חדשות, והפקודה sort -u מסירה כפילויות. הפקודה head -50 שומרת על פלט קריא.

jq לא מותקן במחשב הבדיקה שלי, ולכן לא יכולתי להריץ כאן את השורה הזו. הרצתי את אותה לוגיקה עם Python 3.12 אחרי שהורדתי את ה-JSON עם curl:

bash
curl -s -o crt.json 'https://crt.sh/?q=example.com&output=json'
python
import json
import sys

records = json.load(open(sys.argv[1], encoding="utf-8"))
names = set()
for record in records:
    for name in record["name_value"].split("\n"):
        names.add(name.strip())

for name in sorted(names)[:50]:
    print(name)

יש לשמור את זה בשם crt_names.py ולהריץ עם python crt_names.py crt.json. זה הפלט שראיתי ב-2026-11-08. crt.sh החזיר HTTP 200 עם 85 רשומות תעודה, שהכילו 12 שמות ייחודיים:

text
*.example.com
AS207960 Test Intermediate - example.com
dev.example.com
emudhra-lab.example.com
example.com
m.example.com
m.testexample.com
products.example.com
[email protected]
support.example.com
[email protected]
www.example.com

שלושה דברים בולטים. ה-wildcard *.example.com מכסה כל תת־דומיין ישיר, אבל לא אומר אילו מארחים קיימים. השורה "AS207960 Test Intermediate - example.com" אינה שם מארח, ונראית כמו שם subject שהועתק מתעודה של CA לבדיקות. הרשומות [email protected] וגם [email protected] נראות כמו זהויות אימייל מתעודות שהונפקו למטרה הזו. סקריפט שמתייחס לכל שורה כשם מארח ייצור רעש.

הסדר שמפיקה הפקודה sort -u תלוי ב-locale שלך, ולכן הוא יכול להיות שונה מהפלט של Python. מה שקובע הוא אוסף השמות.

שלב 3: השוואת השמות ל-zone של ה-DNS שלך

מייצאים את השמות מספק ה-DNS או מקובץ ה-zone: שם מלא אחד בכל שורה, באותיות קטנות, בלי נקודה בסוף. אחר כך משווים בין שתי הרשימות:

bash
LC_ALL=C sort -u zone-names.txt > zone.sorted
LC_ALL=C sort -u ct-names.txt > ct.sorted
LC_ALL=C comm -13 zone.sorted ct.sorted

הפקודה comm -13 מדפיסה שורות שמופיעות רק בקובץ השני. אלה שמות שמופיעים ב-CT אבל לא ב-zone שלך. גם wildcards יופיעו שם, ולכן צריך לבדוק אותם ביד. להשוואה מלאה, מסירים את החיתוך [:50] מסקריפט ה-Python לפני הכתיבה לקובץ ct-names.txt. לא הרצתי את השלב הזה מול zone אמיתי, כי ה-zone של example.com לא בשליטתי. ההשוואה עובדת באותה צורה עם כל רשימת שמות.

חלק מהשמות לגיטימיים אבל נמצאים מחוץ ל-zone שייצאת, למשל ב-zone אחר אצל אותו ספק, או מאחורי CNAME. "לא נמצא בקובץ ה-zone שלי" היא שאלה שצריך לברר, ואינה ממצא.

שלב 4: טריאז׳ לכל שם

ממצא מה זה יכול להיות הצעד הבא
קיים ב-zone, התעודה עדיין תקפה צפוי לתעד ולהמשיך
רק ב-CT, התעודה פגה שירות שיצא משימוש או שם בדיקה ישן לאשר מול הבעלים, ואז לעדכן את המלאי
רשומת wildcard מכסה שמות שאולי לא ברשימה שלך לבדוק אילו מהשמות שלך היא מגינה עליהם
טקסט חופשי או זהות אימייל לא שם מארח להוציא מהמלאי, להשאיר בהערות
שם לא מוכר, תעודה בתוקף אולי שירות שנשכח לשאול את הבעלים. אין לבדוק את המארח
תעודה מ-CA שהצוות שלך אף פעם לא משתמש בה אולי הנפקה שגויה או בעיה בחשבון להעביר למי ששולט ב-DNS ובחשבונות ה-CA

שלב 5: כתיבת הרישום

שומרים רישום קצר על כל סקירה, כדי שהאדם הבא יוכל לחזור עליה:

text
Domain:
Query and date (UTC):
Source and format (crt.sh, JSON):
Certificates returned:
Unique names:
Names matching the zone:
Names needing owner confirmation:
Owner contacted (who, when):

טעויות נפוצות

  • התייחסות לרשומה בלוג כאל שירות חי. CT מתעד הנפקה. תעודה יכולה להתקיים עבור מארח שהושבת לפני שנים.
  • התעלמות מתפוגה. צריך לבדוק את תאריך ה-not-after לפני שמרימים דגל על שם ישן.
  • הנחה שהרשימה מלאה. שם שחסר לא מוכיח שהשם לא קיים. תעודות של CA פרטית בדרך כלל לא מופיעות בלוגים ציבוריים, ושם יכול להתקיים ב-DNS בלי תעודה ציבורית. צריך לשלב את CT עם רשומות DNS ועם המלאי שלך.
  • בדיקה אקטיבית כדי לאשר. האישור שייך לבעלים. חיבור למארח שנמצא, סריקת הפורטים שלו או בקשת הדפים שלו הם עבודה אקטיבית, והיא דורשת הרשאה של הבעלים.
  • פרסום פלט גולמי. שמות מארחים יכולים לחשוף מבנה פנימי. את הרשימה הגולמית משאירים בתוך הדוח ומשתפים רק עם מי שצריך אותה.
  • אמון בכלי חיפוש אחד בלי הערה. צריך לתעד באיזה שירות השתמשת ומתי, כדי שמישהו יוכל לחזור על השאילתה.

איך ממשיכים מכאן

כדאי להירשם ל-CT monitor עבור הדומיין שלך. פרויקט CT מציין ש-monitors בודקים את הלוגים עבורך ויכולים להתריע כשנרשמת תעודה לדומיין שלך. כך סקירה חד־פעמית הופכת לבדיקה שוטפת.

כדאי לקרוא את RFC 9162, סעיפים 2 ו-8. סעיף 2 עוסק ב-Merkle trees שמאחורי הלוגים. סעיף 8 עוסק בגורמים שבודקים אותם, כולל monitors, והם הרלוונטיים לדומיין שלך.

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

מקורות

מקורות

  1. RFC 9162: Certificate Transparency Version 2.0
  2. How Certificate Transparency works
  3. crt.sh

עוד בנושא OSINT וריקון

OSINT וריקון

תהליך OSINT מאפס, עם AI כטייס משנה

תהליך OSINT חוזר ליעד שמותר לך להסתכל עליו: הגדרת היקף, איסוף בשלבים, הצלבה, ושהצ'אט של NotHoly יתכנן ויסכם.

מתחילים2 דקות קריאה