
مجمّع BloodHound OpenGraph لـ GitHub يقوم برسم هيكل المنظمة، والأذونات، ومسارات الهجوم عبر السحابات في رسم بياني قابل للتنقل لعمليات تدقيق الأمن والاستجابة للحوادث.

GitHound هو أداة جمع بيانات OpenGraph من BloodHound لـ GitHub، مصممة لرسم هيكل مؤسستك وأذوناتها في رسم بياني قابل للتصفح لمسارات الهجوم. يقوم بـ:
نمذجة الكيانات الرئيسية لـ GitHub
التصور والتحليل في BloodHound
مع GitHound، تحصل على رسم بياني واضح وتفاعلي لمشهد أذونات GitHub الخاص بك - مثالي لمراجعات الأمان وعمليات التدقيق الامتثالي والتحقيقات السريعة في الحوادث.
للحصول على توثيق مفصل، راجع BloodHound Docs - GitHound.
# 1. Load the collector
. ./githound.ps1
# 2. Create a session with your Personal Access Token
$session = New-GitHubSession -OrganizationName "YourOrgName" -Token (Get-Clipboard)
# 3. Run the collection
Invoke-GitHound -Session $session
# 4. Upload the resulting githound_<orgId>.json file to BloodHound
إذا تمت مقاطعة التجميع، استأنف من حيث توقفت:
Invoke-GitHound -Session $session -Resume
يدعم GitHound كلًا من جلسات رمز الوصول الشخصي وجلسات تثبيت تطبيق GitHub. سير عمل تطبيق GitHub الموجود على نطاق المنظمة لم يتغير:
. ./githound.ps1
$session = New-GitHubJwtSession `
-OrganizationName "YourOrgName" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId
Invoke-GitHound -Session $session -CollectAll
يمكن للدالة نفسها أيضًا إنشاء جلسات قادرة على التعامل مع المؤسسات:
. ./githound.ps1
$session = New-GitHubJwtSession `
-EnterpriseName "YourEnterpriseSlug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId `
-PersonalAccessToken $pat
تحتفظ الجلسات القادرة على التعامل مع المؤسسات بسياقات مصادقة متعددة على الكائن المرتجع GitHound.Session:
Headers: رؤوس رمز تثبيت تطبيق GitHub المستخدمة للتجميع العاديJwtHeaders: رؤوس JWT لتطبيق GitHub المستخدمة لنقاط النهاية على مستوى التطبيق مثل تعداد التثبيتاتPatHeaders: رؤوس رمز الوصول الشخصي الاختيارية لمسارات التجميع التي تتطلب مصادقة رمز المستخدملتعداد التثبيتات التي تنتمي إلى تطبيق GitHub المُوثق:
Get-GitHubAppInstallation -Session $session |
Select-Object TargetType, InstallationId, Login, Name, SuspendedAt
تم دمج تحليل سير العمل الآن في Invoke-GitHound عند استخدام -CollectAll. سيقوم المُجمّع بـ:
GH_Workflow ومحتويات سير العملGH_WorkflowJob و GH_WorkflowStepGH_CanPwnRequest و GH_CanDispatchTogithound_<orgId>.jsonلأغراض الاستئناف/التصحيح، تتم كتابة نقطة التفتيش الوسيطة لتحليل سير العمل كـ githound_WorkflowAnalysis_<orgId>.json.
يتضمن GitHound الآن أساسًا بسيطًا لجمع المؤسسات من خلال Git-HoundEnterprise.
يقوم هذا المُجمّع حاليًا بإنشاء:
GH_EnterpriseGH_Organization خفيفة الوزن للمنظمات الأعضاءGH_Contains من المؤسسة إلى منظماتهاجمع مستخدمي المؤسسة من خلال Git-HoundEnterpriseUser يضيف:
GH_UserGH_HasMember من المؤسسة إلى هؤلاء المستخدمينجمع SAML للمؤسسة من خلال Git-HoundEnterpriseSamlProvider يضيف:
GH_SamlIdentityProviderGH_ExternalIdentityGH_HasSamlIdentityProvider من المؤسسة إلى الموفريتطلب هذا المسار جلسة مدعومة بـ PAT لأن GitHub يعرض SAML للمؤسسة من خلال enterprise.ownerInfo.
جمع فريق المؤسسة من خلال Git-HoundEnterpriseTeam يضيف:
GH_EnterpriseTeamGH_AssignedTo من فرق المؤسسة إلى المنظمات المعينةGH_MemberOf من فرق المؤسسة إلى عُقد GH_Team المرئية للمنظمة ent: باستخدام مطابقة الخصائصmembers في فريق المؤسسة وحواف GH_HasRole من المستخدمين إلى تلك الأدوارجمع دور المؤسسة من خلال Git-HoundEnterpriseRole يضيف:
GH_EnterpriseRoleGH_Contains من المؤسسة إلى تلك الأدوارGH_HasRole من المستخدمين المعينين مباشرة وفرق المؤسسةowners افتراضي يتم ملؤه من enterprise.ownerInfo.admins عندما تكون بيانات مشرف المؤسسة المدعومة بـ PAT متاحةفي الوقت الحالي، يتم الاحتفاظ بسلاسل أذونات المؤسسة الأولية على عقدة GH_EnterpriseRole في خاصية permissions الخاصة بها بدلاً من توسيعها إلى حواف أذونات مخصصة.
جمع SCIM للمؤسسة يضيف حاليًا:
SCIM_UserSCIM_GroupSCIM_Provisioned من SCIM_User إلى GH_ExternalIdentitySCIM_Provisioned من SCIM_Group إلى GH_EnterpriseTeam عندما يعرض GitHub group_id لفريق المؤسسةSCIM_MemberOf من SCIM_User إلى SCIM_Groupيمنح هذا GitHound جسرًا غير مرتبط بالموفر من مخطط SCIM المشترك إلى نموذج هوية المؤسسة والفريق الأصلي لـ GitHub.
عندما يحدد GH_SamlIdentityProvider الذي تم جمعه موفر الهوية العلوي، يمكن لـ GitHound أيضًا إضافة حواف ارتباط SCIM الواعية بالموفر داخل مخرجات الـ sidecar لـ SCIM:
Okta_User -> SCIM_User
Okta_User.id = SCIM_User.externalIdOkta_Group -> SCIM_Group
Okta_Group.name = SCIM_Group.externalIdOkta_Group.oktaDomain = GH_SamlIdentityProvider.foreign_environmentidيحتفظ GitHound بطبقة SCIM في مخرجات sidecar الخاصة بها بحيث تظل هذه التعيينات مرئية دون خلط العُقد الأصلية لـ SCIM في الرسم البياني للمؤسسة الأصلي لـ GitHub:
githound_<entId>.json يحتوي على بيانات المؤسسة الأصلية لـ GitHubgithound_scim_<entId>.json يحتوي على عُقد SCIM الأصلية وحواف جسر SCIMgithound_saml_<entId>.json يحتوي على بيانات SAML وهوية خارجيةgithound_hybrid_<entId>.json يحتوي على حواف عبر النماذج مثل SAML_Implements و SAML_HasAccount و GH_SyncedTogithound_saml_<entId>.json يحتوي أيضًا على طوبولوجيا SAML الموحدة لموفر خدمة GitHub، بما في ذلك SAML_TrustsIssuer و SAML_HasAssertionConsumerServiceيبقى نموذج موفر الهوية الأصلي لـ GitHub سليمًا في مخرجات GitHub/SAML الأصلية:
GH_ExternalIdentityGH_HasExternalIdentityGH_MapsToUserطبقة SAML الموحدة في githound_hybrid_<entId>.json تضع الآن SAML_HasAccount مباشرة على GH_User، مع استخلاص match_values من خصائص GH_ExternalIdentity الموجهة لـ SAML مثل saml_identity_name_id و saml_identity_username.
تم وضع علامة collected = false على عُقد الغلاف GH_Organization التي يصدرها جمع المؤسسة عمدًا. إنها تمثل اكتشافًا هيكليًا من سياق المؤسسة ومن المقرر إثراؤها لاحقًا بواسطة جمع المنظمة العادي.
للتنسيق القائم على المؤسسة أولاً، سيقوم Invoke-GitHoundEnterprise بجمع البيانات المدعومة في نطاق المؤسسة، وتعداد تثبيتات المنظمة ذات الصلة، ثم تشغيل سير العمل الحالي Invoke-GitHound لكل منظمة في دليله الفرعي الخاص ضمن مسار نقطة التفتيش المختار.
مثال:
$session = New-GitHubJwtSession `
-EnterpriseName "your-enterprise-slug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $enterpriseInstallationId `
-PersonalAccessToken $pat
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -CollectAll
للاختبار الخاص بالمؤسسة فقط دون تعداد المنظمات ذات الصلة:
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -EnterpriseOnly

للحصول على توثيق مفصل، راجع BloodHound Docs - GitHound Schema.
فئات الحواف الرئيسية:
نمط مسار الهجوم الأساسي:
(:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_AdminTo|GH_CanPush]->(:GH_Repository)
ابحث عن معرّف الكائن للمستخدم المستهدف:
MATCH (n:GH_User)
RETURN n
تلميح: حدد تخطيط الجدول
https://github.com/user-attachments/assets/1ddfd075-2a15-4aa9-bad7-74c43e6c82d6
استبدل قيمة <object_id> في الاستعلام التالي بمعرف الكائن الخاص بالمستخدم:
MATCH p = (:GH_User {objectid:"<object_id>"})-[:GH_MemberOf|GH_AddMember|GH_HasRole|GH_HasBaseRole|GH_Owns*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository)
RETURN p

احصل على معرّف الكائن للمستودع المستهدف:
MATCH (n:GH_Repository)
RETURN n
خذ معرّف الكائن للمستودع المستهدف واستبدل قيمة <object_id> في الاستعلام التالي به:
MATCH p = (:GH_User)-[:GH_MemberOf|GH_HasRole|GH_HasBaseRole|GH_Owns|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository {objectid:"<object_id>"})
RETURN p

MATCH p = (:GH_User)-[:GH_HasRole|GH_HasBaseRole]->(:GH_OrgRole {short_name: "owners"})
RETURN p

MATCH p = (:AZUser)-[:GH_SyncedTo]->(:GH_User)
RETURN p

ابحث عن كيانات GitHub التي يمكنها افتراض هويات Azure الموحدة (علاقات الثقة OIDC):
// All GitHub → Azure OIDC attack paths
MATCH p = (:GH_Repository|GH_Branch|GH_Environment)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
// Users with paths to Azure via GitHub Actions
MATCH p = (:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_CanPush]->(:GH_Repository)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
MATCH p = (:GH_Repository)-[:GH_HasSecret]->(:GH_OrgSecret)
RETURN p
MATCH p = (:GH_Repository)-[:GH_Contains]->(:GH_SecretScanningAlert)
RETURN p
نرحب بمساهماتكم ونقدرها! لجعل العملية سلسة وفعالة، يرجى اتباع الخطوات التالية:
ناقش فكرتك
انشئ نسخة وفرعًا
انشئ نسخة من هذا المستودع إلى حسابك الخاص.
أنشئ فرعًا موضوعيًا لعملك:
git checkout -b feat/my-new-feature
نفذ واختبر
اتبع النمط والنماذج الموجودة في المستودع.
أضف أو حدث أي اختبارات/أمثلة لتغطية تغييراتك.
تحقق من أن الكود الخاص بك يعمل كما هو متوقع:
# e.g. dot-source the collector and run it, or load the model.json in BloodHound
قدم طلب سحب
ادفع فرعك إلى نسختك:
git push origin feat/my-new-feature
افتح طلب سحب موجهًا إلى فرع main لهذا المستودع.
في وصف طلب السحب الخاص بك، يرجى تضمين:
المراجعة والدمج
شكرًا لك على المساعدة في تحسين هذا الامتداد! 🎉
Copyright 2025 Jared Atkinson
Licensed under the Apache License, Version 2.0
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
ما لم يتم الإشارة إلى خلاف ذلك بواسطة ملف ترخيص ذي مستوى أدنى أو رأس ترخيص، يتم إصدار جميع الملفات في هذا المستودع بموجب ترخيص Apache-2.0. يمكن العثور على نسخة كاملة من الترخيص في ملف LICENSE ذي المستوى الأعلى.
| الفئة | الحواف الرئيسية | الوصف |
|---|
| الاحتواء | GH_Contains, GH_Owns | التسلسل الهرمي التنظيمي |
| تعيين الأدوار | GH_HasRole, GH_MemberOf, GH_HasBaseRole | من لديه أي أدوار |
| أذونات المستودع | GH_AdminTo, GH_CanPush, GH_CanPull | ما يمكن للأدوار فعله |
| حماية الفروع | GH_BypassPullRequestAllowances, GH_RestrictionsCanPush | الوصول على مستوى الفرع |
| الأسرار | GH_HasSecret | تعيين الوصول إلى الأسرار |
| عبر السحابة | GH_CanAssumeIdentity, GH_SyncedTo | مسارات هجوم إلى Azure/AWS |