
تحليل وتتبع رموز OAuth 2.0 و OIDC و Microsoft Entra ID من عمليات الالتقاط عبر Burp أو mitmproxy أو Chrome DevTools. تصوّر دورات حياة الرموز، واكتشف النطاقات الخطرة، وصدّر الرموز لإعادة تشغيلها عبر لوحة تحكم تفاعلية.
تتبَّع رموز OAuth 2.0 وOIDC وMicrosoft Entra ID عبر حركة مرور الشبكة المُلتقطة. يستوعب صادرات Burp Suite بصيغة XML، وملفات تدفق mitmproxy، أو تدفقات بروتوكول Chrome DevTools المباشرة في قاعدة بيانات SQLite واحدة، ثم يقدّم لوحة تحكم ويب تفاعلية لتصفية الرموز المميزة، وتتبّع التبادلات، ورصد النطاقات الخطرة، وتصدير الرموز المميزة لإعادة التشغيل، وتصوّر دورات حياة الرموز المميزة كرسوم بيانية Mermaid.
الحالة: TATS مستقر للاستخدام الشخصي / في المهام. مُحسَّن لمنظومة Microsoft 365 / Entra (FOCI، BroCI/NAA، ملفات تعريف جلسة ESTSAUTH cookies، إثراء entrascopes.com) لكنه يعمل مع أي حركة مرور OAuth/OIDC شبه قياسية.
عند تمرير جلسة Microsoft 365 أو Azure طويلة عبر Burp / mitmproxy تكون النتيجة المُلتقطة ضخمة، ومعظم الأدوات إما:
تستخرج هذه الأداة كل رمز وصول / تحديث / هوية مُلاحَظ، وتُبصمها لتتمكن من ربط الرمز المميز نفسه عبر المصادر، وتفكّ شيفرة مطالبات JWT، وتحلّ معرّفات GUID الخاصة بعميل / مورد مايكروسوفت مقابل entrascopes.com، وتعرض الصورة الكاملة كلوحة تحكم واحدة — بما في ذلك عرض سلسلة رمز التحديث الذي يتبع تبادلات FOCI عبر التطبيقات وإصدار رموز BroCI للتطبيقات المتداخلة.
هذا المشروع مُوجَّه أساسًا لأغراض البحث والتعليم لكنه يوفّر خيارات مثل معاينة الأوامر وميزات تصدير الرموز المميزة التي يمكن أن تدعم بعض الأدوات الهجومية.
ingest — تصدير Burp Suite "Save items" بصيغة XMLmitm — ملف تدفق mitmproxy .mitm (إطارات HTTP و WebSocket)cdp — ربط مباشر بـ Chrome / Edge عبر بروتوكول DevTools
(في الوقت الفعلي، يلتقط HTTP المفكوك بـ TLS و إطارات WebSocket
دون شهادة وسيطة؛ يتتبَّع كل تبويب موجود وكل تبويب يُفتح
أثناء التشغيل عبر الربط التلقائي على مستوى المتصفح)--append للدمج في قاعدة بيانات موجودة؛ تُحدَّث الرموز المميزة (يتراكم عدد الاستخدامات + العمر المُلاحَظ)، وتُضاف الأحداث
والتبادلات، ويسجّل source_tag الخاص بالصف كل عملية
رأت الرمز المميز.pip install mitmproxy).access_token، refresh_token، id_token) و
استدلالات اسم ملف تعريف الارتباط تحدّد نوع الرمز المميز.ESTSAUTH، ESTSAUTHPERSISTENT،
ESTSAUTHLIGHT، SignInStateCookie) تُعرَّف صراحةً كرموز مميزة
مكافئة للتحديث (وإلا لصُنِّفت خطأً بواسطة
تلميح ملف تعريف الارتباط "auth" العام).foci
في استجابات نقطة نهاية الرمز المميز.brk_client_id، وbrk_redirect_uri، ومخططات إعادة التوجيه brk-<guid>://
في جسم الطلب.--enrich الاختيارية تجلب firstpartyscopes.json و
resources.json من https://entrascopes.com/ وتحلّ معرّفات GUID الخاصة بـ appid /
azp / aud إلى أسماء ودّية مع روابط قابلة للنقر.upn / preferred_username /
unique_name / email / name، مع الرجوع إلى sub@iss أو oid،
وإبراز حزم التطبيقات فقط والهويات المجهولة بشكل منفصل. يُظهر كل صف
هوية شارة captures عندما يظهر المستخدم في
≥2 من source_tags (البقاء عبر الالتقاطات، إشارة البحث الرئيسية لـ --append)
بالإضافة إلى نطاق first_seen → last_seen وزر
timeline يُبرز كل رمز مميز لذلك المستخدم على
تبويب مخطط التسلسل.appid / azp / client_id في جسم النموذج
/ brk_client_id / brk_nested_id) ظهر في
التبادلات، مع شارات FOCI / brokerable / broker / nested.aud مُلاحَظة، محلولة إلى أسماء موارد
entrascopes حيثما أمكن.tid المميزة مع أعداد الرموز المميزة / المستخدمين / التطبيقات.scp / scope /
roles لكل رمز مميز مقابل قائمة مراقبة منسّقة لأذونات Microsoft Graph
عالية التأثير ونطاقات موارد Azure.(token, host) حيث
استُخدم الرمز المميز عند مضيف لا يتوافق مع مطالبة aud الخاصة به
(يشير إلى تسرّب بيانات اعتماد أو سوء استخدام).amr) — توزيع pwd / mfa / pop / smartcard
.xms_cc=CP1)،
وربط إثبات الحيازة (مطالبة cnf، مع كشف kid المشترك
عبر الجماهير)، ومتطلبات المصادقة المتدرجة (acrs)، ومستوى
سياق المصادقة acr. كل صف قابل للنقر ويُصفّي
تبويب الرموز المميزة ليقتصر على الرموز المميزة التي تحمل ذلك المؤشر.⚠ priv — إشارة
البحث الخاصة بتوسّع الامتيازات على نمط FOCI / BroCI.source_tag لترى كم
صفًا جاء من كل عملية استيعاب.roadtx describe،
وroadtx auth، وcurl، وPython requests، وPowerShell
Invoke-RestMethod.ws-frame-sent /
ws-frame-received، ومصدر ws[body_json[<key>]]، و
ws_session_id يجمع كل الإطارات ضمن اتصال WebSocket واحد.تخزّن قاعدة البيانات بصمات SHA-256 (أول 12 حرفًا سداسيًا) وبادئة من 12 حرفًا لكل رمز مميز مُلاحَظ. لا تغادر سلاسل الرموز المميزة الكاملة ملف الإدخال أبدًا.
تُخزَّن محتويات مطالبات JWT المفكوكة (الترويسة + الحمولة، بما في ذلك oid، وsub،
وupn، وemail، وtid، وقوائم النطاقات، إلخ) حرفيًا
افتراضيًا لأنها جوهر التحليل. تعامل مع
قاعدة البيانات وأي رابط لوحة تحكم مشترك كحساسة كلما وُجدت رموز JWT.
--redact-claims (متاحة في ingest، وmitm، وcdp)
تستبدل قيم المطالبات المدرجة بعناصر نائبة ثابتة للتجزئة قبل أن
تصل إلى قاعدة البيانات أصلًا. تغطي قائمة الحقول الافتراضية sub، وoid،
وupn، وemail، وname، وunique_name، وpreferred_username، وemails،
وmail، وipaddr، وgiven_name، وfamily_name. مرّر قائمة صريحة
مفصولة بفواصل (مثل --redact-claims sub,upn,oid) لتجاوز
الافتراضي. يُعيَّن نفس الإدخال دائمًا إلى نفس العنصر النائب، لذا يظل
تجميع المستخدمين / المستأجرين في لوحة التحكم يعمل دون كشف
المستخدم.
--store-tokens (متاحة في ingest، وmitm، وcdp،
معطّلة افتراضيًا) تشترك في كتابة سلسلة الرمز المميز الكاملة إلى
قاعدة البيانات لتتمكن لوحة التحكم من تقديم:
.roadtools_auth وسيلتقطه أي أمر فرعي roadtx).roadtx describe، وroadtx auth، وcurl،
وPython requests، وPowerShell Invoke-RestMethod — باستخدام
مطالبات tid، وappid، و الفعلية للرمز المميز.dataclasses الحديثة). مُختبَر على 3.12.python -m tats مباشرةً.| الحاجة | التثبيت |
|---|---|
الأمر الفرعي mitm | pip install mitmproxy |
| التقاط مباشر من Chrome / Edge | لا شيء — يستخدم عميل WebSocket من المكتبة القياسية |
--enrich (entrascopes.com) | لا شيء — يستخدم urllib.request |
التشغيل من نسخة مستنسخة (دون تثبيت):```bash git clone tats cd tats python -m tats --help
يوجد HTML / CSS / JS الخاص بلوحة التحكم في `tats/static/` ويتم تحميله
عند أول استيراد، لذا لا حاجة إلى خطوة بناء — فقط شغّل الوحدة
مباشرة من نسخة الشيفرة.
**التثبيت كحزمة (يمنحك سكربت الطرفية `tats`):**```bash
pip install . # core only
pip install .[mitm] # + mitmproxy flow file support
pip install .[test] # + pytest for the test suite
pip install .[all] # everything
بعد التثبيت يمكنك استدعاء الأداة باسمها المختصر:```bash tats ingest engagement.xml -o tokens.db --enrich tats serve tokens.db
إذا كنت تحتاج فقط إلى مسارات Burp / CDP، فإن الملف مكتفٍ ذاتيًا بالكامل
مع مكتبة Python القياسية — لا يتطلب أي تثبيت أو إضافات.
---
## البدء السريع
**حلّل تصدير Burp XML وافتح لوحة المعلومات:**```bash
tats ingest examples/fixture.xml -o tokens.db --enrich
tats serve tokens.db
دمج التقاط Burp مع ملف تدفق mitmproxy في قاعدة بيانات واحدة:```bash tats ingest engagement.xml -o tokens.db --enrich tats mitm chat-session.mitm -o tokens.db --enrich --append tats serve tokens.db
**التقاط مباشر من متصفح Chrome (يرى إطارات HTTP + WebSocket مفكوكة تشفير TLS، دون الحاجة إلى شهادة CA وسيطة) — مع السماح للأداة بتشغيل المتصفح:**```bash
# Terminal 1 — auto-launch Chrome / Edge / Chromium / Brave
tats cdp -o tokens.db --enrich --launch-chrome
# Terminal 2 — open the dashboard (auto-refreshes every 5 s)
tats serve tokens.db
يتم إنهاء المتصفح الذي تم تشغيله وحذف ملف التعريف المؤقت الخاص به
عندما تضغط على Ctrl-C لأمر cdp.
إذا كنت تفضل الاتصال بمتصفح قيد التشغيل بالفعل، فابدأه باستخدام
--remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile وشغّل
cdp بدون --launch-chrome.
تعقيم قاعدة بيانات قبل مشاركتها (حجب المعلومات الشخصية):```bash
tats ingest engagement.xml -o tokens.db
--enrich --redact-claims
يتم حجب المحتوى بشكل ثابت: القيم المتطابقة تُعيّن إلى عناصر نائبة متطابقة، لذا يظل التجميع حسب المستخدم في لوحة المعلومات يعمل دون إظهار المستخدم.
يعرض رأس لوحة المعلومات `live · updated <time>` بمجرد أن تبدأ البيانات بالتدفق.
---
## الأوامر الفرعية
يقبل كل أمر فرعي `--help` للحصول على قائمة الخيارات الأساسية. توضح الملاحظات أدناه *متى* و*كيف* قد تلجأ إلى كل واحد منها.
### الأعلام العامة
تنطبق هذه على كل أمر فرعي وتوضع *قبل* اسم الأمر الفرعي:
* `-v` / `--verbose` — يضيف أسطر سجل INFO (حالة الإثراء، أعداد الحجب عند الاستيعاب). يضيف `-vv` مستوى DEBUG (كل طلب إلى الخادم).
* `-q` / `--quiet` — يكتم أسطر سجل INFO؛ لا تظهر سوى تحذيرات WARNING وأخطاء ERROR. لا يتأثر سطر مخرجات المستخدم النهائي (مثل `wrote tokens.db (...)`) ولا أي تشخيصات `error: …`، لذا ستظل ترى ما يهم من داخل سكربت.
* `--version` — يطبع إصدار الأداة ثم يخرج.
### `ingest` — تصدير Burp Suite بصيغة XML
يقرأ ملف XML من نوع "Save items" (Proxy → HTTP history → انقر بزر الفأرة الأيمن → Save items). ملفات مشروع `.burp` الثنائية **غير** مدعومة — فالصيغة مملوكة وغير مستقرة بين إصدارات Burp؛ وتصدير العناصر التي تهمك هو سير العمل المدعوم.```bash
tats [-v|-q] ingest <burp_items.xml> -o tokens.db \
[--enrich] [--enrich-cache-dir DIR] [--no-enrich-cache] \
[--append] [--source-tag TAG] [--no-progress] \
[--redact-claims [CLAIMS]] [--no-serve-hint]
أمثلة:```bash
tats ingest burp.xml -o tokens.db --enrich
tats ingest day2.xml -o tokens.db --append
--source-tag burp:day2
### `mitm` — ملف تدفق `.mitm` الخاص بـ mitmproxy
يقرأ ملف تدفق أنتجته `mitmdump` أو `mitmproxy` أو `mitmweb`. هذا
هو مسار الإدخال الوحيد الذي يلتقط **إطارات WebSocket** دون جلسة
متصفح حية — تحافظ ملفات التدفق على كل حمولة إطار نصي / ثنائي.```bash
tats [-v|-q] mitm <flow_file.mitm> -o tokens.db \
[--enrich] [--enrich-cache-dir DIR] [--no-enrich-cache] \
[--append] [--source-tag TAG] [--no-progress] \
[--redact-claims [CLAIMS]] [--no-serve-hint]
يتطلب pip install mitmproxy. ستُصدر الأداة خطأً واضحًا إذا كانت
الحزمة مفقودة.
التقط ملف تدفق باستخدام mitmproxy:```bash mitmdump -w session.mitm
tats mitm session.mitm -o tokens.db --enrich
### `cdp` — الاتصال المباشر بـ Chrome / Edge
يتصل بمتصفح من عائلة Chromium قيد التشغيل عبر بروتوكول DevTools
ويبث أحداث `Network.*` إلى قاعدة البيانات. يلتقط طلبات / استجابات HTTP
(مع جلب المحتوى عبر `Network.getResponseBody`)، وترقيات WebSocket،
وكل إطار WebSocket في كلا الاتجاهين. تُفرَّغ الذاكرة المؤقتة إلى
قاعدة البيانات كل N من الأحداث (الافتراضي 25)، لذا يلتقط الاستقصاء
كل 5 ثوانٍ في لوحة المعلومات الرموز الجديدة خلال ثوانٍ من قيام المتصفح
بالطلب.```bash
tats [-v|-q] cdp [-o tokens.db] \
[--host 127.0.0.1] [--port 9222] [--target ID] \
[--launch-chrome [PATH]] [--flush-every N] \
[--enrich] [--append] [--redact-claims [CLAIMS]]
--launch-chrome)```bashtats cdp -o tokens.db --launch-chrome
tats cdp -o tokens.db
--launch-chrome /opt/google/chrome-canary/chrome
يعمل المتصفح الذي تم تشغيله مع `--remote-debugging-port=<port>` ومجلد بيانات مستخدم مؤقت جديد. عند إيقاف أمر `cdp` (Ctrl-C)، يتم إنهاء المتصفح وحذف الملف الشخصي المؤقت.
### الاتصال بمتصفح قيد التشغيل بالفعل
قم بتشغيل المتصفح بنفسك، باستخدام ملف شخصي جديد، ثم شغّل `cdp` بدون `--launch-chrome`:```bash
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
--remote-debugging-port=9222 ^
--user-data-dir="%TEMP%\cdp-profile"
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile
يعمل دليل بيانات المستخدم المنفصل على تجنّب الارتباط بملف تعريف شخصي ويمنع المتصفح قيد التشغيل من رفض علامة التصحيح.
بشكل افتراضي، يرتبط cdp على مستوى المتصفح ويتتبّع كل تبويب
موجود عند بدء التشغيل وكذلك كل تبويب يُفتح أثناء التشغيل
(window.open، النقر مع Ctrl، زر التبويب الجديد). تشترك جميع التبويبات في
WebSocket الواحد عبر مُضاعِف جلسات بروتوكول CDP المسطّح، لذا فإن فتح
التبويبات أو إغلاقها أثناء تشغيل الالتقاط مدعوم بالكامل. كل ارتباط
/ فصل تبويب يطبع ملاحظة من سطر واحد إلى stderr عند مستوى INFO.
إذا كنت تفضّل التثبيت على تبويب واحد وإنهاء الارتباط عند إغلاق ذلك التبويب، فاسرد الأهداف المتاحة:```bash curl http://127.0.0.1:9222/json/list
…ثم مرّر `--target <id>`.
اضغط Ctrl-C للإيقاف. يتم تفريغ ذيل أي مخزن مؤقت قيد المعالجة إلى
قاعدة البيانات قبل خروج العملية.
### `serve` — لوحة تحكم الويب
يقرأ قاعدة بيانات موجودة ويقدّم واجهة مستخدم ويب أحادية الصفحة على
`127.0.0.1:8765`. الخادم للقراءة فقط؛ لا يكتب أبدًا إلى
قاعدة البيانات، لذا من الآمن تشغيله جنبًا إلى جنب مع عملية `cdp` أو `mitm`
قيد المعالجة.```bash
tats serve <tokens.db> \
[--host 127.0.0.1] [--port 8765] [--no-browser]
أمثلة:```bash
tats serve tokens.db
tats serve tokens.db --port 9000 --no-browser
tats serve tokens.db --host 0.0.0.0
> **تحذير:** تعرض واجهة الويب حمولات JWT المفكوكة (المطالبات)، وبصمات
> الرموز، والجدول الزمني للنشاط، ومخططات Mermaid لأي شخص يمكنه
> الوصول إلى عنوان الربط. إذا قمت بالاستيعاب باستخدام `--store-tokens`، فإنها
> تعرض أيضًا **الرموز الخام الكاملة** عبر `/api/token/<fp>` و
> `/api/export?fps=...`. لا يوجد **مصادقة**. أبقِ
> `--host` على `127.0.0.1` إلا إذا كنت تنوي خلاف ذلك تحديدًا.
#### تصدير جاهز لإعادة التشغيل
عندما تم بناء قاعدة البيانات باستخدام `--store-tokens`، يحصل كل رمز موسّع
في تبويب Tokens على صف من إجراءات النقرة الواحدة:
* **Copy raw** — سلسلة الرمز الكاملة إلى الحافظة.
* **Copy Bearer header** — `Authorization: Bearer <token>`، جاهز للصق.
* **Copy curl example** — أمر من سطر واحد يستهدف `aud` الخاص بالرمز
(أو مضيف المُصدر الخاص به) مع إرفاق ترويسة bearer.
* **Download JSON** — ملف JSON لرمز واحد يحتوي على الخام، والمطالبات،
والأحداث المرصودة، والتبادلات.
* **Copy as roadtx** — شكل JSON لذاكرة تخزين رموز roadtools
(`tokenType`، `accessToken` / `refreshToken` / `idToken`، `expiresOn`،
`tenantId`، `_clientId`، `resource`، `foci`، `scope`). الصقه مباشرة
في ملف `.roadtools_auth`.
* **Download .roadtools_auth** — نفس الحمولة، تُنزَّل كملف.
أعد تسميته إلى `.roadtools_auth` (أو مرّره عبر `roadtx <cmd>
--tokens-file`) وسيلتقطه أي أمر فرعي من roadtx.
تحتوي شريط أدوات تبويب Tokens أيضًا على **Export selected for replay**، الذي
يستدعي `/api/export?fps=fp1,fp2,...` وينزّل مستند JSON واحدًا
يحتوي على ما يصل إلى 200 رمز (خام، ومطالبات، وأحداث) في حزمة واحدة. بدون
`--store-tokens`، تعرض الأزرار نفسها تلميحًا لإعادة الاستيعاب قبل
أن يصبح التصدير الجاهز لإعادة التشغيل ممكنًا.
#### معاينة الأوامر
يحتوي كل رمز موسّع أيضًا على كتلة **Command preview** قابلة للطي
تملأ مسبقًا استدعاءات إعادة التشغيل / الفحص الأكثر شيوعًا باستخدام
المطالبات الفعلية للرمز (والقيمة الخام الكاملة عندما يكون `--store-tokens`
مفعّلًا). لكل مقتطف زر Copy بنقرة واحدة. تعتمد الخلطة الدقيقة على
نوع الرمز:
* **أي JWT:** `roadtx describe -t '<token>'` (فك التشفير دون شبكة).
* **رموز التحديث:**
* `roadtx auth --refresh-token '...' -c <client_id> -t <tenant_id>` —
استبدل رمز تحديث برموز وصول جديدة.
* `curl -X POST .../oauth2/v2.0/token` — المكافئ لـ OAuth
للمستخدمين الذين لا يشغّلون roadtx.
* **رموز الوصول / الهوية / غير المعروفة:**
* `curl -H 'Authorization: Bearer ...' '<aud>'`
* Python `requests.get(...)` مع تعيين ترويسة bearer.
* PowerShell `Invoke-RestMethod` مع نفس الترويسة.
* **دائمًا:** كائن JSON لإسقاطه في `.roadtools_auth`.
عندما يكون `--store-tokens` معطّلًا، تُعرض المقتطفات مع `<TOKEN>` كعنصر
نائب بحيث تظل اللوحة مفيدة كمرجع توثيقي.
---
## واجهة الويب بالتفصيل
### التنقل العلوي
`Summary | Tokens | Exchanges | FOCI | BroCI | Graph | Sequence`
يُعرض كل تبويب بشكل مستقل من نفس اللقطة الموجودة في الذاكرة لـ
`/api/data`. التبديل بين التبويبات فوري؛ ويُعاد عرض مخططات
الرسم والتسلسل عند الطلب وتحترم التحديد الحالي في
تبويب Tokens.
### Summary
بلاطات إحصائية عبر الأعلى (tokens / access / refresh / id / unknown /
used / unused / events / exchanges / FOCI exchanges / BroCI exchanges /
hosts) تليها شبكة من البطاقات الموصوفة في
[Features → Dashboard cards](#dashboard-cards).
انقر على أي صف في أي بطاقة للانتقال إلى تبويب Tokens مُفلتر مسبقًا — على
سبيل المثال، النقر على صف مستأجر يفلتر الجرد إلى الرموز التي تحمل
`tid` هذا.
### Tokens
جرد قابل للفلترة والترتيب. يقود التحديد المتعدد أزرار
highlight / isolate / sequence. يُظهر توسيع الصف JWT المفكوك بالكامل
(الترويسة + الحمولة كـ JSON خام)، وكل حدث يتضمن ذلك الرمز، و
كل تبادل كان فيه مدخلًا أو مخرجًا.
### Exchanges
قائمة قابلة للترتيب لكل تبادل رمز مقابل رمز مكتشف — دورات
رموز التحديث، والاستبدالات المتقاطعة FOCI، وتبادلات التطبيقات المتداخلة BroCI. يعرض
عمود BroCI معرّفات الوسيط + العميل المتداخل جنبًا إلى جنب مع
الدليل الذي أثار الاكتشاف.
### FOCI
جدولان: كل رمز تحديث موسوم بعائلة FOCI (حاليًا
تصدر Microsoft فقط `"1"`)، وكل تبادل حملت استجابته
حقل `foci`.
### BroCI
تبادلات مصادقة التطبيقات المتداخلة. لكل واحد منها: تطبيق الوسيط
(`brk_client_id`)، والعميل المتداخل (`client_id`)، والدليل الذي
أثار الاكتشاف (`brk_client_id`، `brk_redirect_uri`،
`brk-<guid>://` redirect URI)، وبصمات رموز
الإدخال / الإخراج.
### Graph
مخطط `flowchart LR` من Mermaid لعلاقات الرمز ↔ الخدمة. تُرسم رموز التحديث
كأسطوانات، ورموز الوصول / الهوية كملاعب. تُظهر الحواف
الإصدار، والعرض، والتبادل، والدوران. الإبراز (من
تبويب Tokens) يضيف لمسة صفراء؛ والعزل يعيد عرض المخطط مع
الرموز المحددة فقط والرموز التي تتبادل معها.
### Sequence
مخطط تسلسل Mermaid لكل حدث بترتيب الالتقاط. اختيار
رمز واحد يعرض تسلسله فقط؛ واختيار عدة رموز يحتفظ بالعرض الكامل
لكنه يضع نجمة على الرموز المحددة. حد أقصى قابل للتهيئة للأحداث (افتراضيًا
200؛ تصبح مخططات تسلسل Mermaid غير مقروءة بعد بضع مئات
من الرسائل).
---
## الدعم الخاص بـ Microsoft
### عائلة معرّفات العملاء (FOCI)
تسمح Microsoft لرمز تحديث صادر لتطبيق واحد في "عائلة" بأن
يُستبدل عند نقطة نهاية الرمز بواسطة **أي تطبيق آخر** في نفس العائلة.
يكتشف الأداة FOCI على الشبكة عبر تحليل JSON استجابة نقطة نهاية الرمز
بحثًا عن حقل `foci` (حاليًا دائمًا `"1"` للعائلة الوحيدة المعروفة).
تُوسم رموز التحديث الصادرة في مثل هذه الاستجابة بمعرّف
العائلة وتُعرض في تبويب **FOCI** المخصص.
إذا كان `--enrich` مفعّلًا، يعرض عمود التطبيق في الجرد أيضًا
علامة `foci: true/false` من `firstpartyscopes.json` — لاحظ أن هذا قد
يختلف مع الاكتشاف على الشبكة (مجموعة بيانات entrascopes تكون أحيانًا
متحفظة). حقل `foci` على الشبكة هو دائمًا الإشارة
الموثوقة.
### Brokered Client Init / مصادقة التطبيقات المتداخلة (BroCI / NAA)
تستخدم إضافات Office، وتطبيقات Teams، وAzure Portal بروتوكول NAA للحصول على
رموز لعميل متداخل عبر تطبيق وسيط. تكتشف الأداة هذا
على جانب الطلب عبر:
* معامل النموذج `brk_client_id` (GUID تطبيق الوسيط)،
* معامل النموذج `brk_redirect_uri` (عنوان URI الفعلي لإعادة توجيه الوسيط)،
* `redirect_uri` بالشكل `brk-<guid>://...` (حيث `<guid>` هو
الوسيط).
مطالبة `appid` / `azp` لرمز الوصول الناتج هي العميل
المتداخل؛ يظهر الوسيط فقط على الشبكة — وليس أبدًا كمطالبة JWT. تعرض
لوحة المعلومات كلا الجانبين بوضوح.
### ملفات تعريف جلسة `ESTSAUTH`
`ESTSAUTH`، و`ESTSAUTHPERSISTENT`، و`ESTSAUTHLIGHT`، و
`SignInStateCookie` هي ملفات تعريف جلسة Microsoft Entra التي لا
تنتقل في `Authorization: Bearer` لكن المتصفح يستخدمها لإصدار
رموز وصول جديدة عبر تدفقات المصادقة الصامتة. تصنفها الأداة كـ
`refresh` (دورها الوظيفي) بدلًا من ترك قاعدة السلسلة الفرعية العامة `auth`
تصنفها خطأً كـ `access`.
### إثراء entrascopes.com (`--enrich`)
يجلب ويخزّن مؤقتًا `firstpartyscopes.json` (~2.8 MB؛ 504 تطبيق
طرف أول مع علامة FOCI الخاصة به، وعناوين URI لإعادة التوجيه، والنطاقات، وقدرة
الوسيط) و`resources.json` (~170 KB؛ أكثر من 1,750 تعيين مورد → اسم
عرض) من <https://entrascopes.com/>. يوجد التخزين المؤقت في:
| المتغير | الافتراضي |
|---|---|
| `$TATS_CACHE` | (أعلى أولوية؛ يُحترم `$BURP_TOKEN_TRACKER_CACHE` كخيار احتياطي لترحيل إصدار واحد) |
| `$XDG_CACHE_HOME/tats` | (Linux/macOS) |
| `%LOCALAPPDATA%\tats\cache` | (Windows) |
| `~/.cache/tats` | (احتياطي) |
مدة الصلاحية 7 أيام. استخدم `--no-enrich-cache` لفرض إعادة الجلب. يُعاد استخدام التخزين المؤقت
كخيار احتياطي قديم عندما تُشغَّل الأداة دون اتصال.
عندما يكون `--enrich` مفعّلًا، يُحل كل GUID لـ `appid` / `azp` / `client_id` وكل
مطالبة `aud` بصيغة GUID-أو-URL إلى اسم ودّي مع رابط
`https://entrascopes.com/?appId=<guid>` قابل للنقر.
---
## البنية
### لقطة واحدة: ملف → قاعدة بيانات → واجهة ويب```
burp.xml ─┐
.mitm ─┼─→ Tracker ─→ ingest_to_db ─→ tokens.db ─→ Store ─→ /api/data ─→ dashboard
CDP WS ─┘ ▲ │
(live, repeated) └───── --append upserts on every flush ─┘
كل مسار مصدر ينتج نفس كائن Tracker. يقوم ingest_to_db
بتحويله إلى صفوف في قاعدة البيانات. يقرأ Store قاعدة البيانات لخادم
HTTP، الذي يعرض JSON عبر /api/data و /api/meta
و /api/token/<fp> و /api/export و /api/graph و /api/sequence.
tokens (المفتاح الأساسي fp) — البصمة، بادئة العينة، النوع،
التنسيق، العمر الملاحظ، ترويسة / حمولة JWT بصيغة JSON، حقول
الإثراء، الحقول المشتقة (user_identity، exp_unix، tenant_id،
scopes_text)، source_tag مفصولة بفواصل، raw (سلسلة الرمز
الكاملة، NULL ما لم يتم الاستيعاب مع --store-tokens)، و
security_features (JSON مضغوط يصف علامات CAE / PoP / step-up
المكتشفة — انظر بطاقة Security features).
قواعد بيانات v2 / v3 الأقدم تُرحَّل تلقائيًا عند إعادة فتحها في وضع
الإلحاق: v2 → v3 يضيف عمود raw القابل للقيمة الفارغة؛ v3 → v4
يضيف عمود security_features القابل للقيمة الفارغة ويعيد تعبئته من
jwt_payload_json المخزّن لكل رمز عند أول فتح. تحتفظ الصفوف
الموجودة مسبقًا بكلا العمودين بقيمهما السابقة.events — كل تفاعل ملاحظ مع الرمز: طلب / استجابة HTTP أو إطار
WebSocket. الأدوار: issued / returned / presented / used /
exchanged-in / ws-frame-sent / ws-frame-received. يحمل
ws_session_id لتجميع الإطارات ضمن اتصال واحد.exchanges — عندما أنتج طلب يحمل رمزًا إلى نقطة نهاية رمز
رموزًا جديدة في استجابته. يسجّل بيانات FOCI / BroCI الوصفية.exchange_inputs، exchange_outputs — بصمات الرموز على
كل جانب من كل تبادل.hosts — تسميات host:port المتميزة.meta — إصدار المخطط، قائمة المصادر، generated_at، last_modified
(يستخدمه الاستقصاء المباشر للوحة المعلومات)، الأعداد.كل صف يُكتب في قاعدة البيانات يحمل source_tag — افتراضيًا
burp:<filename> أو mitm:<filename> أو cdp:<host>:<port>، لكن
يمكن تجاوزه عبر --source-tag. عندما تُرى نفس البصمة بواسطة أكثر من
تمريرة استيعاب واحدة، يتراكم حقل source_tag كقائمة مفصولة بفواصل،
حتى تتمكن بطاقة Sources في لوحة المعلومات من عرض المصدر لكل رمز.
يحتفظ --append بقاعدة بيانات موجودة ويدمج فيها عبر UPSERT للرموز
(يتراكم عدد الاستخدامات + العمر الملاحظ، وتُرقّى الأنواع غير
المعروفة) و INSERT للأحداث / التبادلات (مع إزاحة أرقام seq الخاصة
بها بعد الحد الأقصى الموجود، حتى يبقى الجدول الزمني للنشاط
متزايدًا). يرفض عدم تطابق إصدار المخطط الدمج لمنع فقدان البيانات
الصامت.
تُرجع نقطة نهاية /api/meta لخادم الويب جدول meta (~200
بايت). تستقصي لوحة المعلومات هذا كل 5 ثوانٍ وتعيد جلب
/api/data الكامل فقط عندما يتغير last_modified. يقوم مسار
الاستيعاب cdp بتفريغ متتبعه في الذاكرة إلى قاعدة البيانات كل 25
حدثًا افتراضيًا، لذا فإن زمن الاستجابة من طلب المتصفح إلى تحديث لوحة
المعلومات عادةً < 10 ثوانٍ.
.burp غير مدعومة. استخدم Save items
لإنتاج XML الذي يستهلكه الأداة.alg=none، وهجمات الخلط بين المفاتيح خارج
النطاق. استخدم مدقق JWT مخصصًا لتلك الأمور.unknown وتُخفى افتراضيًا ما
لم يُضبط --include-unknown على العلامة الأقدم (الخاصة بـ Burp
فقط).--enrich يجري طلبات HTTP صادرة إلى
https://entrascopes.com/. تجاوز العلامة إذا كانت بيئتك لا
تسمح بذلك.| العَرَض | السبب المحتمل | الإصلاح |
|---|---|---|
error: could not parse <file> as XML | محاولة استيعاب ملف مشروع .burp ثنائي | في Burp: Proxy → HTTP history → حدد العناصر → انقر بزر الفأرة الأيمن → Save items |
error: no <item> elements found | لم يُنتج XML بواسطة Save items في Burp | أعد التصدير من Burp؛ يجب أن يكون العنصر الجذر <items> |
error: cannot append to DB with schema_version 1 | أُنشئت قاعدة البيانات بواسطة إصدار أقدم | احذف قاعدة البيانات وأعد استيعاب المصادر الأصلية؛ ترحيل المخطط غير تلقائي عن قصد |
error: the 'mitm' source needs the mitmproxy Python package | mitmproxy غير مثبّت | pip install mitmproxy |
error: cannot reach Chrome at 127.0.0.1:9222 | لم يُشغَّل Chrome مع --remote-debugging-port | انظر تعويذة التشغيل في cdp subcommand |
| يرتبط CDP لكن لا تتدفق أي أحداث | لم تُجرِ الصفحة أي طلبات شبكة بعد، أو كل النشاط في OOPIF / worker (غير مرتبط تلقائيًا) | أعد تحميل الصفحة؛ تأكد من تسجيل علامات التبويب (ابحث عن أسطر سجل tab attached: … على stderr) |
no browser-level webSocketDebuggerUrl at /json/version | إصدار Chrome قديم جدًا لـ CDP على مستوى المتصفح، أو أعاد شكلًا خاطئًا | حدّث Chrome، أو مرّر --target <id> لاستخدام الربط القديم بعلامة تبويب واحدة |
target … has no webSocketDebuggerUrl | مصحح أخطاء آخر (مثل نافذة DevTools) مرتبط بالفعل | أغلق DevTools، أو ارتبط بهدف مختلف |
تعرض لوحة المعلومات Failed to load /api/data | الخادم لا يستطيع قراءة ملف قاعدة البيانات | تحقق من صحة مسار قاعدة البيانات، وأن الملف قابل للقراءة، وأن إصدار المخطط متطابق |
| تتوقف التحديثات المباشرة عن الوصول | خرجت عملية cdp أو لم يُفعَّل تفريغ مخزن الشبكة بعد | تحقق من طرفية cdp بحثًا عن أخطاء؛ قلّل --flush-every لتحديثات أسرع |
يوجد بانيا تجهيزات في examples/:```bash
python examples/make_fixture.py examples/fixture.xml tats ingest examples/fixture.xml -o tokens.db --enrich
python examples/make_mitm_fixture.py examples/fixture.mitm tats mitm examples/fixture.mitm -o tokens.db --enrich --append
بعد تشغيل كلا الأمرين، يحتوي `tokens.db` على 15 رمزًا (11 من Burp + 4 من
mitmproxy)، و23 حدثًا بما في ذلك حدث إطار WebSocket، و3
تبادلات.
### مجموعة الاختبار```bash
pip install .[test]
pytest
تغطي المجموعة استخراج الرموز، وتحليل JWT، وتصنيف ملفات تعريف ارتباط جلسة Microsoft، والكشف عن FOCI / BroCI، وملخص المطالبات، وتنقيح PII، ومسار استيعاب Burp XML بدلالات UPSERT في وضع الإلحاق، ومسار استيعاب إطار WebSocket الخاص بـ mitmproxy (يُتخطى تلقائيًا عند غياب الاعتمادية الاختيارية mitmproxy).```text
$ pytest tests/
============================= test session starts =============================
…
======================== 62 passed in 1.4s =================================
### تشغيل الخادم في المقدمة```bash
tats serve tokens.db --no-browser
…وافتح http://127.0.0.1:8765 يدويًا. يسجّل الخادم كل
طلب وأي أخطاء في المعالجات إلى stderr.
| المسار | الغرض |
|---|---|
tats/__init__.py | الأداة بأكملها — المحلّلات، طبقة قاعدة البيانات، خادم HTTP، عميل CDP؛ يحمّل لوحة المعلومات من tats/static/ |
tats/__main__.py | نقطة الدخول لـ python -m tats؛ نفس منطق سكربت الطرفية tats المثبَّت |
tats/static/index.html | الهيكل الأساسي لـ HTML للوحة المعلومات مع عناصر نائبة {{CSS}} / {{JS}} |
tats/static/style.css | تنسيق لوحة المعلومات — حرّره بأدوات CSS المعتادة لديك |
tats/static/app.js | منطق لوحة المعلومات — حرّره بأدوات JS المعتادة لديك (LSP / lint / formatter) |
pyproject.toml | بيانات وصفية للتغليف، إضافات اختيارية ([mitm]، [test]، [all])، نقطة دخول الطرفية |
LICENSE | رخصة GNU العامة v3 |
README.md | هذا الملف |
examples/ | التقاطات اصطناعية + سكربتات بناء العيّنات (انظر examples/README.md) |
examples/make_fixture.py | مولّد XML اصطناعي لـ Burp |
examples/make_mitm_fixture.py | مولّد ملف تدفق mitmproxy اصطناعي |
examples/fixture.xml | عيّنة Burp XML مُعدّة مسبقًا |
examples/fixture.mitm | عيّنة تدفق mitmproxy مُعدّة مسبقًا |
tests/ | مجموعة اختبارات pytest (شغّلها بـ pytest) |
التخطيط أحادي الملف مقصود: الأداة مُصمَّمة لتُقرأ، وتُدقَّق، وتُدرَج في التحقيقات من قِبل أي شخص لديه Python مثبَّت. لا يوجد إعداد خفي، ولا شجرة تبعيات لتقييمها، ولا سطح آخر غير الملف نفسه.
إذا غيّرت الأوامر الفرعية، أو المخطط، أو بطاقات لوحة المعلومات، أو سطح واجهة
البرمجة العامة (أعلام CLI، نقاط نهاية /api/*)، فحدّث الأقسام ذات الصلة
من هذا الملف في التغيير نفسه. الأقسام الأكثر عرضة للانحراف:
رخصة GNU العامة v3.0 أو أحدث — النص الكامل في
ملف LICENSE في جذر المستودع. يحمل مصدر السكربت الترويسة
القصيرة القياسية التي تشير إلى الشيء نفسه.
يجوز لك إعادة توزيع و/أو تعديل الأداة بموجب شروط رخصة GPL v3 (أو أي إصدار أحدث، حسب اختيارك). وهي موزَّعة دون أي ضمان؛ راجع LICENSE للاطلاع على الشروط الكاملة.
aud/api/export?fps=... تُعيد حتى 200 رمز مميز (raw، claims،
events، exchanges) في حزمة JSON واحدة للأدوات اللاحقة.تفعيل هذا يحوّل قاعدة البيانات إلى بيانات اعتماد جملةً — كل
بايت مطلوب لإعادة تشغيل أي جلسة مُلتقطة موجود فيها. ادمجه مع
--redact-claims لتنقية عرض JWT المفكوك، لكن كن على علم أن
الرمز المميز الخام لا يزال يحمل المطالبات غير المنقّحة مُشفَّرة داخله.
عندما تكون العلامة معطّلة، تظل كتلة معاينة الأوامر في لوحة التحكم
تُعرَض، لكن مع <TOKEN> كعنصر نائب لتعمل كمرجع
للصياغة؛ وتعرض أزرار التصدير تلميحًا لإعادة الاستيعاب.