Support

Account

Home Forums Bug Reports ACF_Form() Security Issues

Solving

ACF_Form() Security Issues

  • I have been experimenting with the acf_form() function to allow the usage of ACF fields on the front-end to create new posts in a custom post type.

    I have it configured to create a draft post in a custom post type I’ve created so that I can review the posts and then publish them when they are approved.

    When ACF creates the front-end form, it adds a hidden field called ‘_acf_form’ with a base64 encoded array of form options (example: https://cloudup.com/canI01cuYng)

    Which decodes to something like this: (added some spaces to prevent breaking the forum layout)

    {"id":"acf-form","post_id":"new_post","new_post":{"post_type":"page", "post_status":"publish", "post_author":1}, "field_groups":false, "fields":false, "post_title":true, "post_content":false, "form":true, "form_attributes":{"id":"post", "class":" acf-form", "action":"", "method":"post"}, "return":"http:\/\/domain.com\/path\/action\/29a44c3854", "html_before_fields":"", "html_after_fields":"", "submit_value":"Next (preview)", "updated_message":"Post updated", "label_placement":"top", "instruction_placement":"label", "field_el":"div"}

    Using the browsers inspector, you can easily modify this array to turn any acf_form() into a tool for creating posts in any registered post type, as any user.

    I was able to alter the form in my example to create published pages assigned to another user as the author.

    To secure these forms, the settings should be configured in the admin area, and stored in the database.

  • After reading what mkeys wrote, I would say that if you want to store the values in a hidden field then something like JWT would really help.

    https://github.com/firebase/php-jwt
    http://jwt.io/

  • In the meantime while this vulnerability is addressed officially, I have found a solid workaround for myself.

    I made a duplicate of the acf_form_head() (renamed of course) and put it into my plugin.

    I kept everything the same, except that instead of reading the values of the ‘_acf_form’ field from the $_POST data, I rely on my own hard coded values in my version of the function.

    This allows me to still utilize the great ACF field types and functionality, without allowing people to modify the functionality of the form beyond the scope I defined.

  • I realize this is an old thread, but not sure if there’s a better place to post. The behavior described by mkeys is still present, and while I understand it is a fundamental part of the functionality of acf_form, it is difficult to use acf_form in good conscience with this vulnerability. In addition to manipulating post authors, etc, it is possible to edit the data of other users in this manner using the user_$current_user->ID.

    Is there is a practical solution to mitigate this issue? Or is there a reason I am missing that we shouldn’t be concerned with this?

    I would love to use the acf_form functionality rather than implement a separate form plugin or writing a separate plugin from scratch.

  • I can tell you how I worked around this issue.

    The docs for acf_form have you add a function called acf_form_head() right before the get_header() function on pages where you want to use acf_form().

    Instead of adding that function, I added my own variant of acf_form_head(). In my variant, it doesn’t use that base_64 encoded string to figure out the settings. Instead I have a hard-coded array with the setting that I want to enforce with this form.

    Here is some example code that might get you started:

    https://gist.github.com/mattkeys/ad9c068fd8176d3dd7b78808828911a1

    I hope this helps you in the meantime while this hopefully gets resolved more officially in a future ACF update.

  • Thank you for the quick and thoughtful response. I had seen your suggestion for the modified acf_form_head() function in the original thread, but hadn’t attempted to work through the solution yet myself. This example code should get me going. Thanks!

  • I don’t know if the developer knew about this and I have brought it to his attention.

  • Hi guys

    Thanks for the topic.

    I’ve been thinking about this issue for a while now and am starting to think that the acf_form() $args need to be registered before the acf_form_head() function.

    What do you think of a new function called acf_register_form( $args ) which could be run from your functions.php file (or on the page template)? The acf_form() function could then accept a single string param to identify the form id.

    This would allow the acf_form_head() function to load the form $args without the need of posting them.

  • I think that is a much better and more secure way of handling this, and less complicated than trying to do anything in wp-admin area that stores to the DB. Great idea.

  • This seems like a welcome solution, and I agree probably more practical than getting stored admin stetting involved. Thanks!

  • Hey, I have a project where I’m thinking of using a front end ACF form and security is a primary concern. I’m following this thread and curious how close you are to implementing this new security in an update? Basically should I wait of the fix or implement one of the recommended work arounds?

  • Hi, I’m also thinking of utilising front end forms but can’t do so with this security issue. Is it going to be resolved?

    I can see acf_form() still outputs a hidden field called ‘_acf_form’ with a base64 encoded array of form options.

Viewing 12 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic.