Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-24851: Changeset 2614442 for insert-pages – WordPress Plugin Repository

The Insert Pages WordPress plugin before 3.7.0 allows users with a role as low as Contributor to access content and metadata from arbitrary posts/pages regardless of their author and status (ie private), using a shortcode. Password protected posts/pages are not affected by such issue.

CVE
#sql#xss#wordpress#php#auth

insert-pages/trunk/insert-pages.php

r2539194

r2614442

8

8

* Domain Path: /languages

9

9

* License: GPL2

10

* Version: 3.6.1

10

* Requires at least: 3.0.1

11

* Version: 3.7.0

11

12

*

12

13

* @package insert-pages

423

424

        }

424

425

426

        // Prevent unprivileged users from inserting private posts from others.

427

        if ( is\_object( $inserted\_page ) && 'publish' !== $inserted\_page->post\_status ) {

428

            $post\_type = get\_post\_type\_object( $inserted\_page->post\_type );

429

            $parent\_post\_author\_id = intval( get\_the\_author\_meta( 'ID' ) );

430

            if ( ! user\_can( $parent\_post\_author\_id, $post\_type->cap->read\_post, $inserted\_page->ID ) ) {

431

                $inserted\_page = null;

432

            }

433

        }

434

425

435

        // If inserted page's status is private, don't show to anonymous users

426

436

        // unless 'public' option is set.

649

659

                    }

650

660

                    echo $content;

651

                    /\*\*

652

                     \* Meta.

653

                     \*

654

                     \* @see https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post-template.php#L968

655

                     \*/

656

                    $keys = get\_post\_custom\_keys( $inserted\_page->ID );

657

                    if ( $keys ) {

658

                        echo "<ul class='post-meta'>\\n";

659

                        foreach ( (array) $keys as $key ) {

660

                            $keyt = trim( $key );

661

                            if ( is\_protected\_meta( $keyt, 'post' ) ) {

662

                                continue;

663

                            }

664

                            $value = get\_post\_custom\_values( $key, $inserted\_page->ID );

665

                            if ( is\_array( $value ) ) {

666

                                $values = array\_map( 'trim', $value );

667

                                $value = implode( $values, ', ' );

668

                            }

669

670

                            /\*\*

671

                             \* Filter the HTML output of the li element in the post custom fields list.

672

                             \*

673

                             \* @since 2.2.0

674

                             \*

675

                             \* @param string $html  The HTML output for the li element.

676

                             \* @param string $key   Meta key.

677

                             \* @param string $value Meta value.

678

                             \*/

679

                            echo apply\_filters( 'the\_meta\_key', "<li><span class='post-meta-key'>$key:</span> $value</li>\\n", $key, $value );

680

                        }

681

                        echo "</ul>\\n";

682

                    }

661

                    $this->the\_meta( $inserted\_page->ID );

683

662

                    break;

684

663

756

735

                );

757

736

            }

737

758

738

            // We save the previous query state here instead of using

759

739

            // wp\_reset\_query() because wp\_reset\_query() only has a single stack

762

742

            $old\_query = $GLOBALS\['wp\_query'\];

763

743

            $posts = query\_posts( $args );

744

745

            // Prevent unprivileged users from inserting private posts from others.

746

            if ( have\_posts() ) {

747

                $can\_read = true;

748

                $parent\_post\_author\_id = intval( get\_the\_author\_meta( 'ID' ) );

749

                foreach ( $posts as $post ) {

750

                    $post\_type = get\_post\_type\_object( $post->post\_type );

751

                    if ( ! user\_can( $parent\_post\_author\_id, $post\_type->cap->read\_post, $post->ID ) ) {

752

                        $can\_read = false;

753

                    }

754

                }

755

                if ( ! $can\_read ) {

756

                    // Force an empty query so we don't show any posts.

757

                    $posts = query\_posts( array( 'post\_\_in' => array( 0 ) ) );

758

                }

759

            }

760

764

761

            if ( have\_posts() ) {

765

762

                // Start output buffering so we can save the output to string.

948

945

                            echo get\_the\_content();

949

946

                        }

950

                        the\_meta();

947

                        $this->the\_meta();

951

948

                        // Render any <!--nextpage--> pagination links.

952

949

                        wp\_link\_pages( array(

1035

1032

            }

1036

1033

        }

1037

1038

1034

1039

1035

        return $content;

1427

1423

        );

1428

1424

1425

        // Show non-admins only their own posts if the option is enabled.

1426

        $options = get\_option( 'wpip\_settings' );

1427

        if (

1428

            ! empty( $options\['wpip\_classic\_editor\_hide\_others\_posts'\] ) &&

1429

            'enabled' === $options\['wpip\_classic\_editor\_hide\_others\_posts'\] &&

1430

            ! current\_user\_can( 'edit\_others\_posts' )

1431

        ) {

1432

            $query\['author'\] = get\_current\_user\_id();

1433

        }

1434

1429

1435

        $args\['pagenum'\] = isset( $args\['pagenum'\] ) ? absint( $args\['pagenum'\] ) : 1;

1430

1436

        $query\['offset'\] = $args\['pagenum'\] > 1 ? $query\['posts\_per\_page'\] \* ( $args\['pagenum'\] - 1 ) : 0;

1456

1462

        $results = array();

1457

1463

        foreach ( $posts as $post ) {

1464

            // Prevent unprivileged users (e.g., Contributors) from seeing and

1465

            // inserting other user's private posts.

1466

            $post\_type = get\_post\_type\_object( $post->post\_type );

1467

            if ( 'publish' !== $post->post\_status && ! current\_user\_can( $post\_type->cap->read\_post, $post->ID ) ) {

1468

                continue;

1469

            }

1470

1458

1471

            if ( 'post' === $post->post\_type ) {

1459

1472

                $info = mysql2date( 'Y/m/d', $post->post\_date );

1566

1579

    }

1567

1580

1581

    /\*\*

1582

     \* Render post meta as an unordered list.

1583

     \*

1584

     \* Note: This function sanitizes postmeta value via wp\_kses\_post(); the

1585

     \* core WordPress function the\_meta() does not.

1586

     \*

1587

     \* @see https://developer.wordpress.org/reference/functions/the\_meta/

1588

     \*

1589

     \* @param  int $post\_id Post ID.

1590

     \*/

1591

    public function the\_meta( $post\_id = 0 ) {

1592

        if ( empty( $post\_id ) ) {

1593

            $post\_id = get\_the\_ID();

1594

        }

1595

1596

        $keys = get\_post\_custom\_keys( $post\_id );

1597

        if ( $keys ) {

1598

            $li\_html = '';

1599

            foreach ( (array) $keys as $key ) {

1600

                $keyt = trim( $key );

1601

                if ( is\_protected\_meta( $keyt, 'post' ) ) {

1602

                    continue;

1603

                }

1604

1605

                $values = array\_map( 'trim', get\_post\_custom\_values( $key, $post\_id ) );

1606

                $value  = implode( ', ', $values );

1607

1608

                // Sanitize post meta values.

1609

                $value = wp\_kses\_post( $value );

1610

1611

                $html = sprintf(

1612

                    "<li><span class='post-meta-key'>%s</span> %s</li>\\n",

1613

                    /\* translators: %s: Post custom field name. \*/

1614

                    sprintf( \_x( '%s:', 'Post custom field name' ), $key ),

1615

                    $value

1616

                );

1617

1618

                /\*\*

1619

                 \* Filters the HTML output of the li element in the post custom fields list.

1620

                 \*

1621

                 \* @since 2.2.0

1622

                 \*

1623

                 \* @param string $html  The HTML output for the li element.

1624

                 \* @param string $key   Meta key.

1625

                 \* @param string $value Meta value.

1626

                 \*/

1627

                $li\_html .= apply\_filters( 'the\_meta\_key', $html, $key, $value );

1628

            }

1629

1630

            if ( $li\_html ) {

1631

                echo "<ul class='post-meta'>\\n{$li\_html}</ul>\\n";

1632

            }

1633

        }

1634

    }

1635

1568

1636

}

1569

1637

}

insert-pages/trunk/options.php

r2187208

r2614442

64

64

    'wpip\_section'

65

65

);

66

add\_settings\_field(

67

    'wpip\_classic\_editor\_hide\_others\_posts',

68

    \_\_( 'TinyMCE capabilities', 'insert-pages' ),

69

    'wpip\_classic\_editor\_hide\_others\_posts\_render',

70

    'wpipSettings',

71

    'wpip\_section'

72

);

66

73

}

67

74

add_action( 'admin_init’, ‘wpip_settings_init’ );

103

110

if ( ! array\_key\_exists( 'wpip\_gutenberg\_block', $options ) ) {

104

111

    $options\['wpip\_gutenberg\_block'\] = 'enabled';

112

}

113

114

if ( empty( $options\['wpip\_classic\_editor\_hide\_others\_posts'\] ) ) {

115

    $options\['wpip\_classic\_editor\_hide\_others\_posts'\] = 'disabled';

105

116

}

106

117

220

231

<?php

221

232

}

233

234

/**

235

* Print ‘TinyMCE capabilities’ setting.

236

*

237

* @return void

238

*/

239

function wpip_classic_editor_hide_others_posts_render() {

240

$options = get\_option( 'wpip\_settings' );

241

if ( false === $options || ! is\_array( $options ) || empty( $options\['wpip\_classic\_editor\_hide\_others\_posts'\] ) ) {

242

    $options = wpip\_set\_defaults();

243

}

244

?>

245

<input type='radio' name='wpip\_settings\[wpip\_classic\_editor\_hide\_others\_posts\]' <?php checked( $options\['wpip\_classic\_editor\_hide\_others\_posts'\], 'enabled' ); ?> id="wpip\_classic\_editor\_hide\_others\_posts\_enabled" value='enabled'><label for="wpip\_classic\_editor\_hide\_others\_posts\_enabled">Authors and Contributors only see their own content to insert.</label><br />

246

<input type='radio' name='wpip\_settings\[wpip\_classic\_editor\_hide\_others\_posts\]' <?php checked( $options\['wpip\_classic\_editor\_hide\_others\_posts'\], 'disabled' ); ?> id="wpip\_classic\_editor\_hide\_others\_posts\_disabled" value='disabled'><label for="wpip\_classic\_editor\_hide\_others\_posts\_disabled">Authors and Contributors see all published content to insert.</label><br />

247

<small><em>Note: this option only restricts Contributors and Authors (i.e., the roles without the <code>edit\_others\_posts</code> capability) from seeing other's content in the TinyMCE Insert Page popup; they can still insert any published content if they know the page slug.</em></small>

248

<?php

249

}

insert-pages/trunk/readme.txt

r2539194

r2614442

2

2

Contributors: figureone, the_magician

3

3

Tags: insert, pages, shortcode, embed

4

Requires at least: 3.0.1

5

Tested up to: 5.7

4

Tested up to: 5.8.1

6

5

Stable tag: trunk

7

6

License: GPLv2 or later

111

110

112

111

== Changelog ==

112

113

= 3.7.0 =

114

* Security: Prevent unprivileged users from inserting private posts by others.

115

* Security: Filter out possible XSS in post meta using wp_kses_post() when using display=all.

116

* New Setting: Only show Authors and Contributors their own content in the TinyMCE Insert Pages popup.

113

117

114

118

= 3.6.1 =

461

465

= 1.0 =

462

466

Upgrade to v1.0 to get the first stable version.

467

468

== Upgrade Notice ==

469

470

= 3.7.0 =

471

Note: if you insert private pages/posts, please review the post authors of the pages containing the inserted page and confirm they have the capability to read the private content. This upgrade enforces private page visibility based on the role of the author of the page that inserts any private content.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907