Make WordPress Core

Opened 6 months ago

Closed 3 months ago

Last modified 3 weeks ago

#59795 closed defect (bug) (fixed)

Private Information Exposure via redirect_guess_404_permalink()

Reported by: francescocarlucci's profile FrancescoCarlucci Owned by: peterwilsoncc's profile peterwilsoncc
Milestone: 6.5 Priority: normal
Severity: minor Version:
Component: Canonical Keywords: has-patch has-unit-tests
Focuses: privacy Cc:

Description

When guessing the proper URL to redirect a 404, WordPress only considers the post statuses and not the proper post type privacy settings, leading to potential information disclosure. More specifically, this happens when a post type is set to public => true but publicly_queryable => false, which is supposed to be private.

### Steps to replicate

  1. register a custom post type with the following settings
  • public => true
  • publicly_queryable => false
  1. create an entry in the new custom post type, for example I used as title "info@…"
  2. access a 404 page similar to content, eg. example.com/info and in the redirect it will disclose the private slug

_

Note: the ticket has been discussed with the Security team and there is already a patch available, planned to be released.

Attachments (1)

59795.diff (1.4 KB) - added by peterwilsoncc 6 months ago.

Download all attachments as: .zip

Change History (17)

@peterwilsoncc
6 months ago

#1 @peterwilsoncc
6 months ago

  • Component changed from General to Canonical
  • Milestone changed from Awaiting Review to 6.5
  • Owner set to peterwilsoncc
  • Status changed from new to assigned

I've put this on the 6.5 milestone to include it in the next release.

59795.diff modifies the SQL query for recovering from 404 errors. I'll convert it to a pull request to include tests and any tidy-up that is required. I don't expect I'll get to this prior to the 6.4 release.

Thanks for the report @FrancescoCarlucci and getting in touch with the team prior to posting publicly.

#2 @FrancescoCarlucci
6 months ago

You're welcome ;)

This ticket was mentioned in PR #5673 on WordPress/wordpress-develop by @rajinsharwar.


6 months ago
#3

  • Keywords has-patch has-unit-tests added

Adding the proper SQL code using wpdb:prepare, and unit tests.

Trac ticket: https://core.trac.wordpress.org/ticket/59795

#4 @rajinsharwar
6 months ago

Hi @peterwilsoncc, I tried to test your patch, but it seems that in MySQL 8.0.16, the following error shows up on the 404 page: https://prnt.sc/UM-8i_df528e

So, I sent a new patch with the unit tests.

#6 follow-ups: @peterwilsoncc
4 months ago

I've revised my original patch in the linked pull request

  • Redirects are limited to publicly queryable and searchable post types
  • Unlike my original patch the post type WHERE clause is modified in the get_query_var( 'post_type' ) block to avoid SQL errors
  • Added a unit test for a post type registered with ['public'=>true,'publicly_queryable'=>false]

Testing notes:

  1. Add this mini-plugin to wp-content/mu-plugins
  2. Go to the WordPress Dashboard > Private Posts > Add new Post
  3. Publish a post with the title "59795 Private Post"
  4. In a private/incognito browser window, visit http://localhost/59795 (replacing localhost as appropriate for your test environment)
  5. On this branch you should see a 404 error, on trunk you should be redirected to http://localhost/pwcc_private_post/59795-private-post/

@FrancescoCarlucci If you have bandwidth, are you able to assist by testing the pull request? A copy of WordPress built from the PR can be found by visiting the PR's checks tab, clicking on "Test Build Processes" in the navigation and downloading the wordpress-build-??? artifact.

@peterwilsoncc commented on PR #5673:


4 months ago
#7

@Rajinsharwar I've created a follow up PR https://github.com/WordPress/wordpress-develop/pull/5867 which incorporates your fix to my original, flawed, patch.

Rather than modify assertCanonical, it uses a different test to ensure that private posts are not redirected to.

#8 in reply to: ↑ 6 @FrancescoCarlucci
4 months ago

Sure, I'll give it a try in the next few days!

Thank you!

Replying to peterwilsoncc:

I've revised my original patch in the linked pull request

  • Redirects are limited to publicly queryable and searchable post types
  • Unlike my original patch the post type WHERE clause is modified in the get_query_var( 'post_type' ) block to avoid SQL errors
  • Added a unit test for a post type registered with ['public'=>true,'publicly_queryable'=>false]

Testing notes:

  1. Add this mini-plugin to wp-content/mu-plugins
  2. Go to the WordPress Dashboard > Private Posts > Add new Post
  3. Publish a post with the title "59795 Private Post"
  4. In a private/incognito browser window, visit http://localhost/59795 (replacing localhost as appropriate for your test environment)
  5. On this branch you should see a 404 error, on trunk you should be redirected to http://localhost/pwcc_private_post/59795-private-post/

@FrancescoCarlucci If you have bandwidth, are you able to assist by testing the pull request? A copy of WordPress built from the PR can be found by visiting the PR's checks tab, clicking on "Test Build Processes" in the navigation and downloading the wordpress-build-??? artifact.

#9 in reply to: ↑ 6 @FrancescoCarlucci
4 months ago

@peterwilsoncc Tested, it works well on my side :)

Replying to peterwilsoncc:

I've revised my original patch in the linked pull request

  • Redirects are limited to publicly queryable and searchable post types
  • Unlike my original patch the post type WHERE clause is modified in the get_query_var( 'post_type' ) block to avoid SQL errors
  • Added a unit test for a post type registered with ['public'=>true,'publicly_queryable'=>false]

Testing notes:

  1. Add this mini-plugin to wp-content/mu-plugins
  2. Go to the WordPress Dashboard > Private Posts > Add new Post
  3. Publish a post with the title "59795 Private Post"
  4. In a private/incognito browser window, visit http://localhost/59795 (replacing localhost as appropriate for your test environment)
  5. On this branch you should see a 404 error, on trunk you should be redirected to http://localhost/pwcc_private_post/59795-private-post/

@FrancescoCarlucci If you have bandwidth, are you able to assist by testing the pull request? A copy of WordPress built from the PR can be found by visiting the PR's checks tab, clicking on "Test Build Processes" in the navigation and downloading the wordpress-build-??? artifact.

francescocarlucci commented on PR #5867:


4 months ago
#10

Tested, it works on my side!

#11 @peterwilsoncc
3 months ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 57645:

Canonical: Limit post types searched by redirect_guess_404_permalink().

Limit the post types searched in redirect_guess_404_permalink() to public, searchable post types. This prevents redirects to 404 pages and the exposure of private post type slugs.

Props francescocarlucci, peterwilsoncc, rajinsharwar.
Fixes #59795.

This ticket was mentioned in Slack in #core-test by oglekler. View the logs.


8 weeks ago

#15 @juliemoynat
3 weeks ago

Hi,

I'm sorry in advance because I'm not sure that's the right way to ask this question…

Why hasn't this ticket been patched for all major WordPress versions?

To this day, this problem is referenced as a security vulnerability (as you can see here: https://patchstack.com/database/vulnerability/wordpress/wordpress-wordpress-core-plugin-6-4-3-sensitive-information-exposure-via-redirect-guess-404-permalink-vulnerability?_a_id=431) and therefore generates alerts (as with Solid Security, for example) until websites are in version 6.5.

I thought WordPress didn't require major updates to get security patches, so I'm surprised.

Thanks

#16 @knutsp
3 weeks ago

This ticket was closed on a completed milestone.
If you have a bug or enhancement to report, please open a new ticket. Be sure to mention this ticket, #59795.

You can't expect support for older versions, see https://wordpress.org/documentation/article/supported-versions/

WordPress may fix older versions as it's technically possible. A new ticket is needed, as per above.

Note: See TracTickets for help on using tickets.