Leveraging Microsoft Word Macros
Microsoft Office applications like Word and Excel allow users to embed macros,
which are a series of commands and instructions grouped together
to programmatically accomplish a task.
Organizations often use macros to manage dynamic content
and link documents with external content.
In this section, we’ll use an embedded macro in Microsoft Word
to launch a reverse shell when the document is opened.
Macros are one of the oldest and best-known client-side attack vectors.
They still work well today, assuming we take the considerations from the last
section into account and can convince the victim to enable them.
Let’s dive in and create a macro in Word.
We’ll create a blank Word document
with mymacro as the file name and save it in the .doc format.
This is important because the newer .docx file type
cannot save macros without attaching a containing template.
This means that we can run macros within .docx files
but we can’t embed or save the macro in the document.
In other words, the macro is not persistent.
After we save the document, we can begin creating our first macro.
To get to the macro menu, we’ll click on the View tab from the menu bar
where we will find and click the Macros element:
Let’s enter MyMacro as the name in the Macro Name section,
then select the mymacro document in the Macros in drop-down menu.
This is the document that the macro will be saved to.
Finally, we’ll click Create to insert a simple macro framework into our document.
This presents a window where we can develop our macro from scratch
or use the inserted macro skeleton.
Let’s review the provided macro skeleton.
The main sub procedure used in our VBA macro
begins with the Sub keyword and ends with End Sub.
This essentially marks the body of our macro.
At this point, our new macro is simply an empty sub procedure
containing several lines beginning with an apostrophe,
which marks the start of a single-line comment in VBA.
In this example, we’ll leverage ActiveX Objects,
which provide access to underlying operating system commands.
This can be achieved through the Windows Script Host functionality
or WScript through the Windows Script Host Shell object.
Once we instantiate a Windows Script Host Shell object with CreateObject,
we can invoke the Run method
in order to launch an application on the target client machine.
For our first macro, we’ll start a PowerShell window.
Since Office macros are not executed automatically,
we must use the predefined AutoOpen macro and Document_Open event.
These procedures can call our custom procedure
and run our code when a Word document is opened.
Next, we’ll click Save and close the document.
After we re-open it,
we are presented with a security warning indicating that macros have been disabled.
To run our macro, we’ll click on Enable Content.
After we click on Enable Content, a PowerShell window appears.
Very nice!
In a real-world assessment, our victim must click on Enable Content
to run our macros, otherwise our attack will fail.
In enterprise environments, we can also face a situation where macros are disabled
for Office documents in general.
Fortunately for us, macros are commonly used, and allowed, in most enterprises.
Let’s wrap this section up by extending the code execution of our current macro
to a reverse shell with the help of PowerCat.
We’ll use a base64-encoded PowerShell download cradle to download PowerCat
and start the reverse shell.
The encoded PowerShell command will be declared as a String in VBA.
We should note that VBA has a 255-character limit for literal strings
and therefore, we can’t just embed the base64-encoded PowerShell commands
as a single string.
This restriction does not apply to strings stored in variables,
so we can split the commands into multiple lines and concatenate them.
To do this, we’ll click on the Macros element in the View tab,
select MyMacro in the list and click on Edit to get back to the macro editor.
We’ll declare a string variable,
which we’ll use to store our PowerShell download cradle
and the command to create a reverse shell with PowerCat.
Next, we’ll employ a PowerShell command to download PowerCat
and execute the reverse shell.
We’ll encode the command with base64 to avoid issues with special characters.
We can use a Python script to split the base64-encoded string
into smaller chunks of 50 characters
and concatenate them into the variable.
To do this, we store the PowerShell command in a variable,
and the number of characters for a chunk in another variable.
A for-loop iterates over the PowerShell command
and prints each chunk in the correct format for our macro.
Having split the base64-encoded string into smaller chunks,
we can update our macro:
After we modify our macro, we can save and close the document.
Before re-opening it, let’s start a Python3 web server
in the directory where the PowerCat script is located.
We’ll also start a Netcat listener on port 4444.
After double-clicking the document,
the macro is automatically executed.
Note that the macro security warning regarding the Enable Content button
is not appearing again.
It will only appear again if the name of the document changes.
After the macro is executed,
we receive a GET request for the PowerCat script in our Python3 web server,
and an incoming reverse shell in our Netcat listener.
Opening the document ran the macro and sent us a reverse shell.
Excellent!
Let’s briefly summarize what we did in this section.
First, we created a VBA macro in a Word document
to execute a single command when the document is opened.
Then, we replaced the single command with a base64-encoded PowerShell command
downloading PowerCat and starting a reverse shell on the local system.