Security researcher Rafie Muhammad discovered a high-severity reflected XSS vulnerability on ‘Advanced Custom Fields’ and ‘Advanced Custom Fields Pro’ WordPress plugins, with over two million installed.
This plugin allows us to add extra content fields to our WordPress edit screens. These extra content fields are more commonly referred to as Custom Fields and can allow us to build websites faster with more available fields.
The security vulnerability in Advanced Custom Fields
This plugin suffers from reflected XSS vulnerability. This vulnerability allows any unauthenticated user from stealing sensitive information to, in this case, privilege escalation on the WordPress site by tricking privileged users to visit the crafted URL path.
The underlying vulnerability is located on admin_body_class
function handler :
includes/admin/admin-internal-post-type-list.php
public function admin_body_class( $classes ) {
$classes .= " acf-admin-page acf-internal-post-type {$this->admin_body_class}";
if ( $this->view ) {
$classes .= " view-{$this->view}";
}
return $classes;
}
The admin_body_class
configured to be an extra handler of WordPress’s own hook that is also named admin_body_class
. This hook controls and filters the CSS classes for the main body tag in the admin area.
includes/admin/admin-internal-post-type-list.php
// Add hooks.
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'admin_body_class', array( $this, 'admin_body_class' ) );
Further looking deeper at the implementation of the
on WordPress core, we could see that the outputted value of the hook is not properly sanitized and directly constructed on the HTML page :admin_body_class
https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-admin/admin-header.php#L245
$admin_body_classes = apply_filters( 'admin_body_class', '' );
$admin_body_classes = ltrim( $admin_body_classes . ' ' . $admin_body_class );
?>
<body class="wp-admin wp-core-ui no-js <?php echo $admin_body_classes; ?>">
<script type="text/javascript">
document.body.className = document.body.className.replace('no-js','js');
</script>
Because of that condition, there is a potential XSS vulnerability if the admin_body_class
hook function handler doesn’t properly sanitize the returned class string.
Let’s get back to the hook function handler, the code will directly concatenate $this->view variable to the $classes variable that will be returned as a class string. We actually could fully control the $this->view
variable from current_screen
function :
includes/admin/admin-internal-post-type-list.php
public function current_screen() {
// Bail early if not the list admin page.
if ( ! acf_is_screen( "edit-{$this->post_type}" ) ) {
return;
}
// Get the current view.
$this->view = isset( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : ''; //
-------------------------------------
Sanitization using sanitize_text_field
function is not enough to prevent XSS, since we could still use a DOM XSS payload. Combining all of that, the XSS could be achieved using this example payload :
http://<WORDPRESS_SITE>/wp-admin/edit.php?post_type=acf-field-group&post_status=xxxxxxx" onload=alert(document.domain) xxx="
The reflected HTML structure that is being shown on the front end could be something like this :
<body class="wp-admin wp-core-ui no-js acf-admin-5-3 acf-browser-chrome acf-admin-page acf-internal-post-type acf-admin-field-groups view-xxxxxxx\" onload=alert(document.domain) xxx=\" edit-php auto-fold admin-bar post-type-acf-field-group branch-6-2 version-6-2 admin-color-fresh locale-en-us no-customize-support no-svg">
Note that this vulnerability could be triggered on a default installation or configuration of the Advanced Custom Fields plugin. The XSS also could only be triggered by logged-in users that have access to the Advanced Custom Fields plugin.
The patch in Advanced Custom Fields
Since this issue is mainly because the code directly constructed a variable to the HTML without proper sanitization, implementing esc_attr
a function should be enough to patch the issue. The patch can be found below :
Conclusion
There is many WordPress hook function that used across plugin and theme codes. One of them is admin_body_class
hook. Make sure to sanitize the classes string that outputted when using the hook using sanitize function like esc_attr
.
Bijay Pokharel
Related posts
Recent Posts
Subscribe
Cybersecurity Newsletter
You have Successfully Subscribed!
Sign up for cybersecurity newsletter and get latest news updates delivered straight to your inbox. You are also consenting to our Privacy Policy and Terms of Use.