渗透基础——Exchange 用户邮箱中的隐藏文件夹
0x00 前言
对于 Exchange 用户邮箱,可通过设置文件夹属性创建隐藏文件夹,用户使用 owa 网页登录和使用 Outlook 均无法查看隐藏文件夹中的内容。
站在渗透测试的角度,我们可以利用隐藏文件夹存储重要的信息,作为 C2 通信的数据通道。
本文将要介绍隐藏文件夹的使用方法,通过程序实现创建、访问和删除隐藏文件夹,结合利用思路给出防御建议。
0x01 简介
本文将要介绍以下内容:
- 隐藏文件夹的创建原理
- 隐藏文件夹的常用操作
- 使用 EWS Managed API 的实现代码
- 使用 EWS SOAP XML message 的实现代码
- 开源代码
- 防御检测
0x02 隐藏文件夹的创建原理
对于 Exchange 用户邮箱,将文件夹的扩展属性 PidTagAttributeHidden
(0x10F4000B) 设置为 true 时,该文件夹对于用户不可见
默认配置下,Exchange 用户邮箱包括多个常用文件夹,例如收件箱、发件箱和草稿等,详细列表可参考: https://docs.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.wellknownfoldername?view=exchange-ews-api
我们可以在根目录或者任一文件夹(例如收件箱) 下创建一个文件夹,将其扩展属性 PidTagAttributeHidden
(0x10F4000B) 设置为 true,那么这个文件夹就是隐藏文件夹,对于用户不可见。同时,隐藏文件夹下的所有邮件对用户也是不可见的。更进一步,隐藏文件夹下的邮件内容和附件内容对用户同样不可见。但是我们只要知道了隐藏文件夹的 Id,就能够通过程序进行数据交互。
通过程序进行数据交互时,需要考虑以下操作: (这里以在 Inbox 下创建隐藏文件夹为例)
- 在 Inbox 下创建文件夹
- 查看 Inbox 下的文件夹列表
- 在 Inbox 下创建隐藏文件夹
- 查看 Inbox 下的隐藏文件夹列表
- 查看指定文件夹(无论是否具有隐藏属性) 下的邮件列表
- 在指定文件夹(无论是否具有隐藏属性) 下创建邮件
- 删除指定文件夹
- 为指定邮件添加附件
0x03 使用 EWS Managed API 的实现代码
1.在 Inbox 下创建文件夹
private static void CreateFolderofInbox(ExchangeService service)
{
Folder folder = new Folder(service);
folder.DisplayName = "Custom Folder";
folder.Save(WellKnownFolderName.Inbox);
Console.WriteLine("[*] FolderId:" + folder.Id);
}
2.查看 Inbox 下的文件夹列表
private static void ListFolderofInbox(ExchangeService service)
{
FindFoldersResults findResults = null;
FolderView view = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep };
findResults = service.FindFolders(WellKnownFolderName.Inbox, view);
foreach (Folder folder in findResults.Folders)
{
Console.WriteLine("\r\n");
Console.WriteLine("[*]DisplayName:{0}", folder.DisplayName);
Console.WriteLine("[*]Id:{0}", folder.Id);
Console.WriteLine("[*]TotalCount:{0}", folder.TotalCount);
}
}
3.在 Inbox 下创建隐藏文件夹
private static void CreateHiddenFolderofInbox(ExchangeService service)
{
Folder folder = new Folder(service);
folder.DisplayName = "Custom Hidden Folder";
folder.Save(WellKnownFolderName.Inbox);
Console.WriteLine("[*] Hidden FolderId:" + folder.Id);
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
PropertySet propSet = new PropertySet(isHiddenProp);
// Bind to a folder and retrieve the PidTagAttributeHidden property.
Folder folderhidden = Folder.Bind(service, folder.Id, propSet);
// Set the PidTagAttributeHidden property to true.
folderhidden.SetExtendedProperty(isHiddenProp, true);
// Save the changes.
folderhidden.Update();
}
4.查看 Inbox 下的隐藏文件夹列表
private static void ListHiddenFolderofInbox(ExchangeService service)
{
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
// Create a folder view to retrieve up to 100 folders and
// retrieve only the PidTagAttributeHidden and the display name.
FolderView folderView = new FolderView(100);
folderView.PropertySet = new PropertySet(isHiddenProp, FolderSchema.DisplayName);
// Indicate a Traversal value of Deep, so that all subfolders are retrieved.
folderView.Traversal = FolderTraversal.Deep;
// Find all hidden folders under the MsgFolderRoot.
// This call results in a FindFolder call to EWS.
FindFoldersResults findFolder = service.FindFolders(WellKnownFolderName.Inbox,
new SearchFilter.IsEqualTo(isHiddenProp, true), folderView);
// Display the folder ID and display name of each hidden folder.
foreach (Folder folder in findFolder)
{
Console.WriteLine("[*] DisplayName: {0}", folder.DisplayName);
Console.WriteLine("[*] FolderId: {0}", folder.Id);
Console.WriteLine("\r\n");
}
}
5.查看指定文件夹(无论是否具有隐藏属性) 下的邮件列表
private static void ListMailofFolder(FolderId folderId, ExchangeService service)
{
IdString = folderId;
Folder Folders = Folder.Bind(service, IdString);
FindItemsResults<Item> findResults = null;
ItemView view = new ItemView(int.MaxValue);
PropertySet itempropertyset = new PropertySet(BasePropertySet.FirstClassProperties);
itempropertyset.RequestedBodyType = BodyType.Text;
view.PropertySet = itempropertyset;
findResults = Folders.FindItems(view);
foreach (Item item in findResults.Items)
{
Console.WriteLine("\r\n");
if (item.Subject != null)
{
Console.WriteLine("[*]Subject:{0}", item.Subject);
}
else
{
Console.WriteLine("[*]Subject:<null>");
}
Console.WriteLine("[*]HasAttachments:{0}", item.HasAttachments);
if (item.HasAttachments)
{
EmailMessage message = EmailMessage.Bind(service, item.Id, new PropertySet(ItemSchema.Attachments));
foreach (Attachment attachment in message.Attachments)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
Console.WriteLine(" - Attachments:{0}", fileAttachment.Name);
}
}
Console.WriteLine("[*]ItemId:{0}", item.Id);
Console.WriteLine("[*]DateTimeCreated:{0}", item.DateTimeCreated);
Console.WriteLine("[*]DateTimeReceived:{0}", item.DateTimeReceived);
Console.WriteLine("[*]DateTimeSent:{0}", item.DateTimeSent);
Console.WriteLine("[*]DisplayCc:{0}", item.DisplayCc);
Console.WriteLine("[*]DisplayTo:{0}", item.DisplayTo);
Console.WriteLine("[*]InReplyTo:{0}", item.InReplyTo);
Console.WriteLine("[*]Size:{0}", item.Size);
item.Load(itempropertyset);
if (item.Body.ToString().Length > 100)
{
item.Body = item.Body.ToString().Substring(0, 100);
Console.WriteLine("[*]MessageBody(too big,only output 100):{0}", item.Body);
}
else
{
Console.WriteLine("[*]MessageBody:{0}", item.Body);
}
}
}
6.在指定文件夹(无论是否具有隐藏属性) 下创建邮件
private static void CreateMail(FolderId folderId, ExchangeService service)
{
EmailMessage msg = new EmailMessage(service);
msg.Subject = "test mail";
msg.Save(folderId);
}
7.为指定邮件添加附件
private static void AddFileAttachment(ItemId id, string fileName, ExchangeService service)
{
EmailMessage message = EmailMessage.Bind(service, id);
message.Attachments.AddFileAttachment(fileName);
message.Update(ConflictResolutionMode.AlwaysOverwrite);
Console.WriteLine("\r\n[+]AddAttachment success");
}
8.删除指定文件夹
EWS Managed API 不支持直接删除,需要构造 XML 格式的 SOAP 包
0x04 使用 EWS SOAP XML message 的实现代码
为了节省篇幅,只介绍 <soap:Body>
中的内容
1.在 Inbox 下创建文件夹
<m:CreateFolder>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderId>
<m:Folders>
<t:Folder>
<t:DisplayName>{name}</t:DisplayName>
</t:Folder>
</m:Folders>
</m:CreateFolder>
2.查看 Inbox 下的文件夹列表
<m:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="2147483647" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderIds>
</m:FindFolder>
3.在 Inbox 下创建隐藏文件夹
这里需要发送三个数据包,依次为创建文件夹,添加隐藏属性和更新隐藏属性
创建文件夹:
<m:CreateFolder>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderId>
<m:Folders>
<t:Folder>
<t:DisplayName>{name}</t:DisplayName>
</t:Folder>
</m:Folders>
</m:CreateFolder>
添加隐藏属性:
<m:GetFolder>
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
</t:AdditionalProperties>
</m:FolderShape>
<m:FolderIds>
<t:FolderId Id="{id}" ChangeKey="{key}" />
</m:FolderIds>
</m:GetFolder>
更新隐藏属性:
<m:UpdateFolder>
<m:FolderChanges>
<t:FolderChange>
<t:FolderId Id="{id}" ChangeKey="{key}" />
<t:Updates>
<t:SetFolderField>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:Folder>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:Folder>
</t:SetFolderField>
</t:Updates>
</t:FolderChange>
</m:FolderChanges>
</m:UpdateFolder>
4.查看 Inbox 下的隐藏文件夹列表
<m:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:FieldURI FieldURI="folder:DisplayName" />
</t:AdditionalProperties>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="100" Offset="0" BasePoint="Beginning" />
<m:Restriction>
<t:IsEqualTo>
<t:ExtendedFieldURI PropertyTag="4340" PropertyType="Boolean" />
<t:FieldURIOrConstant>
<t:Constant Value="true" />
</t:FieldURIOrConstant>
</t:IsEqualTo>
</m:Restriction>
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderIds>
</m:FindFolder>
5.查看指定文件夹(无论是否具有隐藏属性) 下的邮件列表
<m:FindItem Traversal="Shallow">
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
<t:BodyType>Text</t:BodyType>
</m:ItemShape>
<m:IndexedPageItemView MaxEntriesReturned="2147483647" Offset="0" BasePoint="Beginning" />
<m:ParentFolderIds>
<t:FolderId Id="{id}" />
</m:ParentFolderIds>
</m:FindItem>
6.在指定文件夹(无论是否具有隐藏属性) 下创建邮件
<m:CreateItem MessageDisposition="SaveOnly">
<m:SavedItemFolderId>
<t:FolderId Id="{id}" />
</m:SavedItemFolderId>
<m:Items>
<t:Message>
<t:Subject>test mail</t:Subject>
</t:Message>
</m:Items>
</m:CreateItem>
7.为指定邮件添加附件
<m:CreateAttachment>
<m:ParentItemId Id="{id}" ChangeKey="{key}"/>
<m:Attachments>
<t:FileAttachment>
<t:Name>{name}</t:Name>
<t:Content>{data}</t:Content>
</t:FileAttachment>
</m:Attachments>
</m:CreateAttachment>
8.删除指定文件夹
<m:DeleteItem DeleteType="HardDelete" xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">
<m:ItemIds>
<t:ItemId Id="{id}"/>
</m:ItemIds>
</m:DeleteItem>
0x05 开源代码
1.使用 EWS Managed API
https://github.com/3gstudent/ewsManage
使用示例
(1) 在 Inbox 下创建隐藏文件夹 test1
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode CreateHiddenFolderofInbox -Name test1
获得文件夹对应的 FolderId: AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
(2) 查看 Inbox 下的隐藏文件夹
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListHiddenFolder -Folder Inbox
(3) 在隐藏文件夹 test1 下创建测试邮件
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode CreateTestMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
(4) 查看隐藏文件夹 test1 下的所有邮件
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListMailofFolder -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
获得测试邮件对应的 ItemId: AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgBGAAAAAABEBlGH6URWQp6Nlg9RxLmyBwA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA1ZCfAg9a0Sq75no2JOzsqAAAAA1FVAAA=
(5) 向测试邮件添加附件
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode AddAttachment -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA= -AttachmentFile c:\test\1.exe
(6) 读取测试邮件的内容
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ViewMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
(7) 保存测试邮件中的附件
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode SaveAttachment -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
(8) 删除测试邮件
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode DeleteMail -Id AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1FUAAA=
2.使用 EWS SOAP XML message
https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py
(1) 在 Inbox 下创建隐藏文件夹 test2
创建文件夹:
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createfolderofinbox
获得 Id: AAMkADc4YjRlNDc1LWI0YjctNDEzZi1hNTQ5LWZkYWY0ZGZhZDM0NgAuAAAAAABEBlGH6URWQp6Nlg9RxLmyAQA1ZCfAg9a0Sq75no2JOzsqAAAAA1U+AAA=,ChangeKey:AQAAABYAAAA1ZCfAg9a0Sq75no2JOzsqAAAAAGE/
添加隐藏属性:
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 SetHiddenPropertyType
更新隐藏属性:
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 UpdateHiddenPropertyType
(2) 查看 Inbox 下的隐藏文件夹
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listhiddenfolderofinbox
(3) 在隐藏文件夹 test1 下创建测试邮件
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createtestmail
(4) 查看隐藏文件夹 test1 下的所有邮件
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listmailoffolder
(5) 向测试邮件添加附件
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 createattachment
(6) 读取测试邮件的内容
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 getmail
(7) 保存测试邮件中的附件
获得附件对应的 Id:
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 getattachment
保存附件:
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 saveattachment
(8) 删除测试邮件
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 deletemail
(9) 删除测试邮件隐藏文件夹 test1
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 deletefolder
0x06 防御检测
1.通过程序查看是否存在隐藏文件夹
例如:
ewsManage.exe -CerValidation No -ExchangeVersion Exchange2013_SP1 -u test1 -p test123! -ewsPath https://test.com/ews/Exchange.asmx -Mode ListHiddenFolder -Folder Inbox
ewsManage.py 192.168.1.1 443 plaintext test.com user1 password1 listhiddenfolderofinbox
2.查看邮件用户上次登录时间
使用 Exchange Server PowerShell:
Get-MailboxDatabase | Get-MailboxStatistics |fl DisplayName,LastLogonTime
3.查看 ews 访问日志
默认位置: C:\inetpub\logs\LogFiles\W3SVC1
,搜索关键词 /EWS/Exchange.asmx
0x07 小结
本文介绍了 Exchange 用户邮箱隐藏文件夹的使用方法,分别介绍使用 EWS Managed API 和 EWS SOAP XML message 实现创建、访问和删除隐藏文件夹的方法,开源代码 ewsManage 和 ewsManage.py ,结合利用思路给出防御建议。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论