
أداة استخراج وتدقيق SharePoint باستخدام PowerShell للفرق الحمراء/الزرقاء/الأرجوانية. تقوم بتعداد جميع مواقع/محركات SharePoint التي يمكن للمستخدم الوصول إليها عبر Microsoft Graph، وتنزيل الملفات بشكل متكرر، وتسجيل كل طلب HTTP لـ Graph وSharePoint لربط SIEM وهندسة الكشف واختبار الاستجابة للحوادث.
SharePointDumper هي أداة استخراج وتدقيق مبنية على PowerShell، تقوم بتعداد مواقع SharePoint التي يمكن للمستخدم الوصول إليها عبر Microsoft Graph وتنزيل الملفات عبر SharePoint.
تم تصميمها لاختبارات SOC / DLP، وفرق الأرجواني، وتقييمات الفريق الأحمر غير المتطورة، وبالتالي تنتج تقارير مفصلة تتضمن الملفات التي تم تنزيلها وكل طلب HTTP (Graph + SharePoint) لربطها مع SIEM.
الأداة لا تقوم بالمصادقة. بدلاً من ذلك، تتطلب رمز وصول OAuth2 تم الحصول عليه مسبقًا مع الأذونات المناسبة لـ Microsoft Graph (Sites.Read.All أو Sites.ReadWrite.All).
إذا كنت بحاجة إلى مساعدة في الحصول على مثل هذا الرمز، يمكنك استخدام EntraTokenAid (أمثلة مرفقة أدناه)، والذي يبسط توليد رموز الوصول القابلة للاستخدام.
التنفيذ:

مثال على سجل API بتنسيق CSV (يمكن أن يكون CSV أو JSON):

مثال على سجل تنزيل الملفات (يمكن أن يكون CSV أو JSON)

git clone https://github.com/zh54321/SharePointDumper.git
cd SharePointDumper
يتطلب SharePointDumper رمز وصول Microsoft Graph صالحًا بأذونات مفوضة لتعداد المواقع والملفات:
Sites.Read.All أوSites.ReadWrite.Allعلاوة على ذلك، يجب أن يكون عميل OAuth مسموحًا له باستدعاء SharePoint API.
أكثر من 23 تطبيقًا من الطرف الأول من Microsoft لديهم بالفعل أذونات Sites.Read… موافق عليها مسبقًا. يمكنهم تنزيل الملفات من SharePoint، ويمكن استخدامهم للحصول على رمز صالح دون تكوين إضافي للمستأجر.
إذا أمكن، استخدم رمز وصول مفعل بـ CAE، والذي يظل صالحًا لمدة تصل إلى 24 ساعة ويقلل الانقطاعات أثناء عمليات التفريغ الطويلة.
يمكنك استخدام EntraTokenAid للحصول على رمز وصول مناسب عبر PowerShell
(يتم طلب رموز CAE افتراضيًا):
# استنساخ الوحدة
git clone https://github.com/zh54321/EntraTokenAid.git
Import-Module EntraTokenAid/EntraTokenAid.psm1
# الحصول على الرموز
$tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# اختياري: تخزين في متغير متوافق مع الأمثلة أدناه
$AccessToken = $tokens.access_token
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -UserAgent "Not SharePointDumper"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -IncludeSites "Finance","Projects"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -ExcludeSites "HR","Legal"
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -IncludeExtensions pdf,docx
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -ExcludeExtensions jpg,bmp
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -MaxFiles 500
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -MaxTotalSizeMB 100
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -RequestDelaySeconds 2
مع التذبذب:
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -RequestDelaySeconds 2 -Variation 3
.\Invoke-SharePointDumper.ps1 -AccessToken $accesstoken -Resume -OutputFolder .\20251121_1551_MyTenant
في وضع الاستئناف، يجب أن يشير -OutputFolder إلى مجلد التشغيل السابق.
يمكن لـ SharePointDumper تحديث رمز الوصول منتهي الصلاحية (HTTP 401) تلقائيًا باستخدام رمز التحديث و EntraTokenAid.
# إلزامي: يجب استيراد الوحدة حتى تتمكن الأداة من استخدام أمر Invoke-Refresh
Import-Module .\EntraTokenAid\EntraTokenAid.psm1
# اختياري: الحصول على الرموز باستخدام EntraTokenAid (طرق أخرى ممكنة أيضًا)
$tokens = Invoke-Auth -ClientId 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob'
# تشغيل SharePointDumper مع دعم التحديث
.\Invoke-SharePointDumper.ps1 -AccessToken $tokens.access_token -RefreshToken $tokens.refresh_token -RefreshClientId 'b26aadf8-566f-4478-926f-589f601d9c74'
ملاحظة: محاولات تحديث الرمز لا يتم تسجيلها في سجل API.
20261115_MySecureTenant/
├── SharePointDumper_Report_20261115_080333.txt
├── SharePointDumper_ApiLog_20261115_080333.csv
├── SharePointDumper_FileLog_20261115_080333.csv
├── Site A/
│ └── Documents/
│ ├── file1.docx
│ └── file2.pdf
└── Site B/
└── Site Assets/
Report_*.txt)ApiLog_*.csv أو .json)SharePointDumper_ReportResume_*SharePointDumper_ApiLogResume_*رمز الوصول غير صالح أو منتهي الصلاحية.
رمز الوصول صالح، لكنه يفتقر إلى أذونات Microsoft Graph أو SharePoint المطلوبة.
يتم تسجيل أنشطة SharePointDumper في:
/organization، /sites، /drives).مثال على UAL:

مثال على سجل نشاط Graph:

صدرت بموجب رخصة MIT.
| اسم التطبيق | معرف العميل | FOCI | أمر مصادقة EntraTokenAid |
|---|
| Microsoft Teams | 1fec8e78-bce4-4aaf-ab1b-5451cc387264 | TRUE | $tokens = Invoke-Auth -ClientID '1fec8e78-bce4-4aaf-ab1b-5451cc387264' -RedirectUrl 'https://login.microsoftonline.com/common/oauth2/nativeclient' |
| Outlook Mobile | 27922004-5251-4030-b22d-91ecd9a37ea4 | TRUE | $tokens = Invoke-Auth -ClientID '27922004-5251-4030-b22d-91ecd9a37ea4' -RedirectUrl 'x-msauth-outlook-prod://com.microsoft.Office.Outlook' |
| OneDrive SyncEngine | ab9b8c07-8f02-4f72-87fa-80105867a763 | TRUE | $tokens = Invoke-Auth -ClientID 'ab9b8c07-8f02-4f72-87fa-80105867a763' -RedirectUrl 'https://login.microsoftonline.com/common/oauth2/nativeclient' |
| OneDrive iOS App | af124e86-4e96-495a-b70a-90f90ab96707 | TRUE | $tokens = Invoke-Auth -ClientID 'af124e86-4e96-495a-b70a-90f90ab96707' -RedirectUrl 'ms-onedrive-auth://com.microsoft.skydrive.shareextension' |
| Microsoft Bing Search | cf36b471-5b44-428c-9ce7-313bf84528de | TRUE | $tokens = Invoke-Auth -ClientID 'cf36b471-5b44-428c-9ce7-313bf84528de' -RedirectUrl 'msauth.com.microsoft.bing://auth' |
| OneDrive | b26aadf8-566f-4478-926f-589f601d9c74 | TRUE | $tokens = Invoke-Auth -ClientID 'b26aadf8-566f-4478-926f-589f601d9c74' -RedirectUrl 'urn:ietf:wg:oauth:2.0:oob' |
| SharePoint | d326c1ce-6cc6-4de2-bebc-4591e5e13ef0 | TRUE | $tokens = Invoke-Auth -ClientID 'd326c1ce-6cc6-4de2-bebc-4591e5e13ef0' -RedirectUrl 'msauth://code/ms-sharepoint-auth%3A%2F%2Fcom.microsoft.sharepoint' |
| SharePoint Android | f05ff7c9-f75a-4acd-a3b5-f4b6a870245d | TRUE | $tokens = Invoke-Auth -ClientID 'f05ff7c9-f75a-4acd-a3b5-f4b6a870245d' -RedirectUrl 'msauth://com.microsoft.sharepoint/gSoqzhbCjkyvI%2Fl7kC7IdG7KbPU%3D' |
| OfficeHome | 4765445b-32c6-49b0-83e6-1d93765276ca | FALSE | $tokens = Invoke-Auth -ClientID '4765445b-32c6-49b0-83e6-1d93765276ca' -RedirectUrl 'https://scuprodprv.www.microsoft365.com/spalanding' -Origin 'https://doesnotmatter' |
| SharePoint Online Web Client Extensibility | 08e18876-6177-487e-b8b5-cf950c1e598c | FALSE | $tokens = Invoke-Auth -ClientID '08e18876-6177-487e-b8b5-cf950c1e598c' -RedirectUrl 'https://onedrive.cloud.microsoft/_forms/spfxsinglesignon.aspx' -Origin 'https://doesnotmatter' |
| Microsoft Teams Web Client | 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 | FALSE | $tokens = Invoke-Auth -ClientID '5e3ce6c0-2b1f-4285-8d4b-75ee78787346' -RedirectUrl 'https://teams.cloud.microsoft/convene/townhall' -Origin 'https://doesnotmatter' |
| Portfolios | f53895d3-095d-408f-8e93-8f94b391404e | FALSE | $tokens = Invoke-Auth -ClientID 'f53895d3-095d-408f-8e93-8f94b391404e' -RedirectUrl 'https://project.microsoft.com/msal-redirect2' -Origin 'https://doesnotmatter' |
| Microsoft Remote Assist | fca5a20d-55aa-4395-9c2f-c6147f3c9ffa | FALSE | $tokens = Invoke-Auth -ClientID 'fca5a20d-55aa-4395-9c2f-c6147f3c9ffa' -RedirectUrl 'http://localhost:13824' |
| ProcessSimpleGCC | 38a893b6-d74c-4786-8fe7-bc3b4318e881 | FALSE | $tokens = Invoke-Auth -ClientID '38a893b6-d74c-4786-8fe7-bc3b4318e881' -RedirectUrl 'https://make.gov.powerautomate.us/auth-redirect.html' -Origin 'https://doesnotmatter' |
| WindowsShareExperienceProd | a8759234-4b8b-4d94-8c0a-ee1ab73af270 | FALSE | $tokens = Invoke-Auth -ClientID 'a8759234-4b8b-4d94-8c0a-ee1ab73af270' -RedirectUrl 'ms-appx-web://Microsoft.AAD.BrokerPlugin/a8759234-4b8b-4d94-8c0a-ee1ab73af270' |
| Office voice transcript generator AAD | d2eb9fef-f34c-40ec-b6a3-4bf524065158 | FALSE | $tokens = Invoke-Auth -ClientID 'd2eb9fef-f34c-40ec-b6a3-4bf524065158' -RedirectUrl 'msauth.com.microsoft.Office.TestVoice.TestVoice2://auth' |
| Azure OpenAI Studio | dc807dec-d211-4b3f-bc8a-43b3443c4874 | FALSE | $tokens = Invoke-Auth -ClientID 'dc807dec-d211-4b3f-bc8a-43b3443c4874' -RedirectUrl 'https://dev.oai.azure.com' -Origin 'https://doesnotmatter' |
| Azure AI Studio App | cb2ff863-7f30-4ced-ab89-a00194bcf6d9 | FALSE | $tokens = Invoke-Auth -ClientID 'cb2ff863-7f30-4ced-ab89-a00194bcf6d9' -RedirectUrl 'https://int.ai.azure.com/agents' -Origin 'https://doesnotmatter' |
| Azure Machine Learning Workbench Web App | d7304df8-741f-47d3-9bc2-df0e24e2071f | FALSE | $tokens = Invoke-Auth -ClientID 'd7304df8-741f-47d3-9bc2-df0e24e2071f' -RedirectUrl 'https://dev.ml.azure.com/redirect' -Origin 'https://doesnotmatter' |
| M365ChatClient | c0ab8ce9-e9a0-42e7-b064-33d422df41f1 | FALSE | $tokens = Invoke-Auth -ClientID 'c0ab8ce9-e9a0-42e7-b064-33d422df41f1' -RedirectUrl 'https://fa000000128.resources.office.net/f7024bdc-7caf-4ca8-807d-2908f09640d6/1.0.2412.19011/en-us_web/login.html' -Origin 'https://doesnotmatter' |
| Microsoft Loop App | a187e399-0c36-4b98-8f04-1edc167a0996 | FALSE | $tokens = Invoke-Auth -ClientID 'a187e399-0c36-4b98-8f04-1edc167a0996' -RedirectUrl 'https://hosted.loop.cloud.dev.microsoft/authLanding.html' -Origin 'https://doesnotmatter' |
| Viva Goals | c8423563-e8f6-49f2-924b-90d9f664378a | FALSE | $tokens = Invoke-Auth -ClientID 'c8423563-e8f6-49f2-924b-90d9f664378a' -RedirectUrl 'https://goals-ppe.microsoft.com/aad/consume' -Origin 'https://doesnotmatter' |
| Microsoft Mesh | eea619ad-603a-4b03-a386-860fcc7410d1 | FALSE | $tokens = Invoke-Auth -ClientID 'eea619ad-603a-4b03-a386-860fcc7410d1' -RedirectUrl 'http://localhost:13824' |
| المعامل | إلزامي | النوع | الوصف |
|---|
AccessToken | نعم | String | رمز وصول OAuth2. لا يتم إجراء أي مصادقة داخل الأداة. |
OutputFolder | لا | String | دليل التفريغ. الافتراضي: ".". في وضع -Resume، يجب أن يشير إلى مجلد تفريغ سابق موجود. |
UserAgent | لا | String | User-Agent مخصص لجميع طلبات HTTP. الافتراضي: SharePointDumper |
Proxy | لا | String | وكيل HTTP اختياري (مثل http://127.0.0.1:8080). |
IncludeExtensions | لا | String[] | تنزيل هذه الامتدادات فقط. |
ExcludeExtensions | لا | String[] | تخطي هذه الامتدادات (يتم تجاهلها إذا تم استخدام IncludeExtensions). |
IncludeSites | لا | String[] | معالجة المواقع المطابقة لأي من هذه القيم فقط. |
ExcludeSites | لا | String[] | تخطي المواقع المطابقة لأي من هذه القيم. |
DisableIpLookup | لا | Switch | لا تقم بالاستعلام عن ifconfig.me للحصول على IP العام. |
RequestDelaySeconds | لا | Double | التأخير الأساسي قبل كل طلب HTTP. |
Variation | لا | Double | تذبذب عشوائي يضاف إلى التأخير الأساسي. |
MaxFiles | لا | Int | الحد الأقصى لعدد الملفات التي سيتم تنزيلها. الافتراضي: بدون حد. |
MaxTotalSizeMB | لا | Double | الحد الأقصى لحجم التنزيل الإجمالي. الافتراضي: بدون حد. |
Resume | لا | Switch | تخطي الملفات التي تم تنزيلها بالفعل. يتطلب -OutputFolder. |
ApiLogFormat | لا | String | Csv (افتراضي)، Json، أو None. |
ApiLogPath | لا | String | مسار إخراج مخصص لملف سجل API. |
FileLogFormat | لا | String | Csv (افتراضي)، Json، أو None. |
FileLogPath | لا | String | مسار إخراج مخصص لملف سجل الملفات. |
LogDownloadTokens | لا | Switch | تسجيل روابط تنزيل SharePoint الكاملة بما في ذلك رموز tempauth (غير آمن). الافتراضي: الرموز مخفية. |
RefreshToken | لا | String | رمز تحديث OAuth2 المستخدم للتجديد التلقائي لرمز الوصول عند HTTP 401. |
RefreshClientId | لا | String | معرف العميل المستخدم مع -RefreshToken. |
RefreshTenant | لا | String | سلطة المستأجر لنقطة نهاية التحديث (الافتراضي: common). |