OSINT וריקון
תהליך OSINT מאפס, עם AI כטייס משנה
תהליך OSINT חוזר ליעד שמותר לך להסתכל עליו: הגדרת היקף, איסוף בשלבים, הצלבה, ושהצ'אט של NotHoly יתכנן ויסכם.
איך לוגי Certificate Transparency מתעדים תעודות TLS ציבוריות, ואיך עוברים על תוצאות crt.sh לדומיין בבעלותך בלי לגעת במארחים שלו.
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/. בצורה מפושטת:
ה-precertificate פותר בעיית סדר. CA לא יכולה לקבל SCT לתעודה הסופית בלי לשלוח קודם משהו ללוג, ודפדפן לא אמור לקבל את התעודה הסופית לפני שיש לה SCT. ה-precertificate שובר את המעגל.
הלוגים הם append-only. אפשר להוסיף רשומות, אבל אי אפשר למחוק, לשנות או להכניס אותן בדיעבד. כל לוג מחזיק Merkle tree, שמאפשר לכל אחד לאמת שתעודה מסוימת כלולה בו (inclusion proof) ושהלוג רק גדל עם הזמן (consistency proof). סעיף 2 של RFC 9162 מתאר את העץ. לא צריך לממש אותו כדי להשתמש בנתונים.
שני פרטים חשובים למגינים. ראשית, ההבטחה נוגעת לרישום ואינה נוגעת לאמון. תעודה רשומה יכולה להיות תקפה, שגויה או מונפקת באופן לא תקין, והלוג לא יכול לומר מה מהשלושה. שנית, הכיסוי מוגבל לתעודות מ-CAs שמקובלות באמון ציבורי. תעודות מ-CA פרטית בדרך כלל לא מגיעות ללוג ציבורי, ולכן תוצאת CT נקייה לא מנקה את כל הנכסים שלך.
שלושה שימושים חוזרים שוב ושוב.
מלאי. צוותים יוצרים שמות מארחים לסביבות בדיקה, לדפי שיווק, לאינטגרציות עם ספקים ולפרויקטים ישנים. רבים מהשמות האלה אף פעם לא מגיעים לקובץ ה-zone של DNS שמישהו עובר עליו. בקשת תעודה משאירה רישום, ולכן CT יכול להציף שמות שהמלאי שלך פספס.
זיהוי תעודות שאף אחד לא ביקש. אם מופיעה תעודה לדומיין שלך ואף אחד בצוות לא ביקש אותה, כדאי לבדוק. ייתכן שזה ספק שפועל בשמך, חשבון ישן, ספק ששכחת ממנו, או תוקף שהשיג שליטה בנתיב אימות. הלוג לבדו לא יכול לומר מה מאלה, ולכן מעבירים את העניין לאנשים שמפעילים את ה-DNS של הדומיין ואת חשבונות התעודות.
היגיינת מחזור חיים. תעודות שפג תוקפן עדיין מופיעות ב-CT. ההיסטוריה הזו שימושית. אפשר לראות אילו שמות היו קיימים ולמצוא שירותים שיצאו משימוש ועדיין יש להם רשומות DNS.
תוצאת CT היא כיוון לבדיקה, ועדיין לא מסקנה. שם יכול להיות ישן, להיות שייך לספק, להיות wildcard שמכסה מארחים רבים או לנבוע מטעות הקלדה. כל כיוון כזה צריך אישור מהבעלים של הנכס.
crt.sh הוא ממשק חיפוש ציבורי ללוגי CT. צד שלישי מפעיל אותו. אפשר לחפש בדפדפן, או לקבל JSON על ידי הוספת output=json לשאילתה. השאילתה שלך מגיעה לשירות הזה, ולכן כדאי לחפש רק דומיינים שמותר לך לדבר עליהם. שם דומיין הוא מידע ציבורי. שם של מוצר שלא הוכרז או שם מארח פנימי לא אמורים להיכנס לתיבת חיפוש של צד שלישי.
קיימים שירותי חיפוש CT נוספים. התוצאות יכולות להשתנות בין אינדקסים ובין מועדי שאילתה, ולכן צריך לרשום באיזה שירות השתמשת ומתי.
המעבדה רק קוראת נתוני CT ציבוריים. לא מתחברים לאף מארח שנמצא. שאילתת DNS על שם היא שאילתה ל-resolver ולא חיבור למארח, אבל אין להתקדם מעבר לזה בלי הרשאה של הבעלים.
פותחים בדפדפן את https://crt.sh/?q=example.com ומחליפים את example.com בדומיין שלך. כל שורה היא תעודה אחת. קוראים את המנפיק, את תאריכי התוקף ואת השמות שמופיעים. אחר כך מנסים את צורת ה-wildcard, https://crt.sh/?q=%.example.com, שמבקשת שמות מתחת לדומיין, ומשווים את הספירות בין שני החיפושים.
מריצים:
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:
curl -s -o crt.json 'https://crt.sh/?q=example.com&output=json'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 שמות ייחודיים:
*.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. מה שקובע הוא אוסף השמות.
מייצאים את השמות מספק ה-DNS או מקובץ ה-zone: שם מלא אחד בכל שורה, באותיות קטנות, בלי נקודה בסוף. אחר כך משווים בין שתי הרשימות:
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 שלי" היא שאלה שצריך לברר, ואינה ממצא.
| ממצא | מה זה יכול להיות | הצעד הבא |
|---|---|---|
| קיים ב-zone, התעודה עדיין תקפה | צפוי | לתעד ולהמשיך |
| רק ב-CT, התעודה פגה | שירות שיצא משימוש או שם בדיקה ישן | לאשר מול הבעלים, ואז לעדכן את המלאי |
| רשומת wildcard | מכסה שמות שאולי לא ברשימה שלך | לבדוק אילו מהשמות שלך היא מגינה עליהם |
| טקסט חופשי או זהות אימייל | לא שם מארח | להוציא מהמלאי, להשאיר בהערות |
| שם לא מוכר, תעודה בתוקף | אולי שירות שנשכח | לשאול את הבעלים. אין לבדוק את המארח |
| תעודה מ-CA שהצוות שלך אף פעם לא משתמש בה | אולי הנפקה שגויה או בעיה בחשבון | להעביר למי ששולט ב-DNS ובחשבונות ה-CA |
שומרים רישום קצר על כל סקירה, כדי שהאדם הבא יוכל לחזור עליה:
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 monitor עבור הדומיין שלך. פרויקט CT מציין ש-monitors בודקים את הלוגים עבורך ויכולים להתריע כשנרשמת תעודה לדומיין שלך. כך סקירה חד־פעמית הופכת לבדיקה שוטפת.
כדאי לקרוא את RFC 9162, סעיפים 2 ו-8. סעיף 2 עוסק ב-Merkle trees שמאחורי הלוגים. סעיף 8 עוסק בגורמים שבודקים אותם, כולל monitors, והם הרלוונטיים לדומיין שלך.
בהמשך, איך כותבים את דוח האבטחה הראשון מראה איך הופכים כיוון כזה לתיאור קצר שהבעלים של הנכס יכול לאמת ולפעול לפיו.
OSINT וריקון
תהליך OSINT חוזר ליעד שמותר לך להסתכל עליו: הגדרת היקף, איסוף בשלבים, הצלבה, ושהצ'אט של NotHoly יתכנן ויסכם.
OSINT וריקון
אנמר תתי דומיין להיקף שלך: subfinder, amass, findomain ו-chaos דרך anew ו-httpx, עם הצ'אט של NotHoly למיון הרשימה.
OSINT וריקון
אסוף URL ופרמטרים בהיקף שלך עם gospider, hakrawler, waybackurls ו-gau, ואז סנן עם qsreplace והצ'אט של NotHoly.