Headline
CVE-2021-24979: Changeset 2632369 for paid-memberships-pro/tags/2.6.6/adminpages/discountcodes.php – WordPress Plugin Repository
The Paid Memberships Pro WordPress plugin before 2.6.6 does not escape the s parameter before outputting it back in an attribute in an admin page, leading to a Reflected Cross-Site Scripting
paid-memberships-pro/tags/2.6.6/adminpages/discountcodes.php
r2600585
r2632369
439
439
?>
440
440
<form action="" method="post">
441
<input name="saveid" type="hidden" value="<?php echo $edit?>" />
441
<input name="saveid" type="hidden" value="<?php echo esc\_attr( $edit ); ?>" />
442
442
<?php wp\_nonce\_field('save', 'pmpro\_discountcodes\_nonce');?>
443
443
<table class="form-table">
…
…
445
445
<tr>
446
446
<th scope="row" valign="top"><label><?php \_e('ID', 'paid-memberships-pro' );?>:</label></th>
447
<td><p class="description"><?php if(!empty($code->id)) echo $code->id; else echo \_\_("This will be generated when you save.", 'paid-memberships-pro' );?></p></td>
447
<td><p class="description"><?php if(!empty($code->id)) echo esc\_html( $code->id ); else echo \_\_("This will be generated when you save.", 'paid-memberships-pro' );?></p></td>
448
448
</tr>
449
449
450
450
<tr>
451
451
<th scope="row" valign="top"><label for="code"><?php \_e('Code', 'paid-memberships-pro' );?>:</label></th>
452
<td><input name="code" type="text" size="20" value="<?php echo str\_replace("\\"", """, stripslashes($code->code))?>" /></td>
452
<td><input name="code" type="text" size="20" value="<?php echo esc\_attr( $code->code ); ?>" /></td>
453
453
</tr>
454
454
…
…
499
499
?>
500
500
</select>
501
<input name="starts\_day" type="text" size="2" value="<?php echo $selected\_starts\_day?>" />
502
<input name="starts\_year" type="text" size="4" value="<?php echo $selected\_starts\_year?>" />
501
<input name="starts\_day" type="text" size="2" value="<?php echo esc\_attr( $selected\_starts\_day ); ?>" />
502
<input name="starts\_year" type="text" size="4" value="<?php echo esc\_attr( $selected\_starts\_year ); ?>" />
503
503
</td>
504
504
</tr>
…
…
517
517
?>
518
518
</select>
519
<input name="expires\_day" type="text" size="2" value="<?php echo $selected\_expires\_day?>" />
520
<input name="expires\_year" type="text" size="4" value="<?php echo $selected\_expires\_year?>" />
519
<input name="expires\_day" type="text" size="2" value="<?php echo esc\_attr( $selected\_expires\_day ); ?>" />
520
<input name="expires\_year" type="text" size="4" value="<?php echo esc\_attr( $selected\_expires\_year ); ?>" />
521
521
</td>
522
522
</tr>
…
…
525
525
<th scope="row" valign="top"><label for="uses"><?php \_e('Uses', 'paid-memberships-pro' );?>:</label></th>
526
526
<td>
527
<input name="uses" type="text" size="10" value="<?php if(!empty($code->uses)) echo str\_replace("\\"", """, stripslashes($code->uses));?>" />
527
<input name="uses" type="text" size="10" value="<?php if ( ! empty( $code->uses ) ) echo esc\_attr( $code->uses ); ?>" />
528
528
<p class="description"><?php \_e('Leave blank for unlimited uses.', 'paid-memberships-pro' );?></p>
529
529
</td>
…
…
567
567
?>
568
568
<div class="pmpro\_discount\_level <?php if ( ! pmpro\_check\_discount\_code\_level\_for\_gateway\_compatibility( $level ) ) { ?>pmpro\_error<?php } ?>">
569
<input type="hidden" name="all\_levels\[\]" value="<?php echo $level->id?>" />
570
<input type="checkbox" id="levels\_<?php echo $level->id;?>" name="levels\[\]" value="<?php echo $level->id?>" <?php if(!empty($level->checked)) { ?>checked="checked"<?php } ?> onclick="if(jQuery(this).is(':checked')) jQuery(this).next().next().show(); else jQuery(this).next().next().hide();" />
571
<label for="levels\_<?php echo $level->id;?>"><?php echo $level->name?></label>
572
<div class="pmpro\_discount\_levels\_pricing level\_<?php echo $level->id?>" <?php if(empty($level->checked)) { ?>style="display: none;"<?php } ?>>
569
<input type="hidden" name="all\_levels\[\]" value="<?php echo esc\_attr( $level->id ); ?>" />
570
<input type="checkbox" id="levels\_<?php echo esc\_attr( $level->id ); ?>" name="levels\[\]" value="<?php echo esc\_attr( $level->id ); ?>" <?php if(!empty($level->checked)) { ?>checked="checked"<?php } ?> onclick="if(jQuery(this).is(':checked')) jQuery(this).next().next().show(); else jQuery(this).next().next().hide();" />
571
<label for="levels\_<?php echo esc\_attr( $level->id ); ?>"><?php echo $level->name?></label>
572
<div class="pmpro\_discount\_levels\_pricing level\_<?php echo esc\_attr( $level->id ); ?>" <?php if(empty($level->checked)) { ?>style="display: none;"<?php } ?>>
573
573
<table class="form-table">
574
574
<tbody>
…
…
591
591
<tr>
592
592
<th scope="row" valign="top"><label><?php \_e('Recurring Subscription', 'paid-memberships-pro' );?>:</label></th>
593
<td><input class="recurring\_checkbox" id="recurring\_<?php echo $level->id;?>" name="recurring\[\]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro\_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).prop('checked')) { jQuery(this).parent().parent().siblings('.recurring\_info').show(); if(!jQuery('#custom\_trial\_<?php echo $level->id?>').is(':checked')) jQuery(this).parent().parent().siblings('.trial\_info').hide();} else jQuery(this).parent().parent().siblings('.recurring\_info').hide();" /> <label for="recurring\_<?php echo $level->id;?>"><?php \_e('Check if this level has a recurring subscription payment.', 'paid-memberships-pro' );?></label></td>
593
<td><input class="recurring\_checkbox" id="recurring\_<?php echo esc\_attr( $level->id );?>" name="recurring\[\]" type="checkbox" value="<?php echo esc\_attr( $level->id ); ?>" <?php if(pmpro\_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).prop('checked')) { jQuery(this).parent().parent().siblings('.recurring\_info').show(); if(!jQuery('#custom\_trial\_<?php echo esc\_attr( $level->id ); ?>').is(':checked')) jQuery(this).parent().parent().siblings('.trial\_info').hide();} else jQuery(this).parent().parent().siblings('.recurring\_info').hide();" /> <label for="recurring\_<?php echo esc\_attr( $level->id ); ?>"><?php \_e('Check if this level has a recurring subscription payment.', 'paid-memberships-pro' );?></label></td>
594
594
</tr>
595
595
…
…
607
607
?>
608
608
<?php \_e('per', 'paid-memberships-pro' ); ?>
609
<input name="cycle\_number\[\]" type="text" size="10" value="<?php echo str\_replace("\\"", """, stripslashes($level->cycle\_number))?>" />
609
<input name="cycle\_number\[\]" type="text" size="10" value="<?php echo esc\_attr( $level->cycle\_number ); ?>" />
610
610
<select name="cycle\_period\[\]">
611
611
<?php
…
…
630
630
<th scope="row" valign="top"><label for="billing\_limit"><?php \_e('Billing Cycle Limit', 'paid-memberships-pro' );?>:</label></th>
631
631
<td>
632
<input name="billing\_limit\[\]" type="text" size="20" value="<?php echo $level->billing\_limit?>" />
632
<input name="billing\_limit\[\]" type="text" size="20" value="<?php echo esc\_attr( $level->billing\_limit ); ?>" />
633
633
<p class="description">
634
634
<?php \_e('The <strong>total</strong> number of recurring billing cycles for this level, including the trial period (if applicable) but not including the initial payment. Set to zero if membership is indefinite.', 'paid-memberships-pro' );?>
…
…
653
653
<th scope="row" valign="top"><label><?php \_e('Custom Trial', 'paid-memberships-pro' );?>:</label></th>
654
654
<td>
655
<input id="custom\_trial\_<?php echo $level->id?>" id="custom\_trial\_<?php echo $level->id;?>" name="custom\_trial\[\]" type="checkbox" value="<?php echo $level->id?>" <?php if ( pmpro\_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).prop('checked')) jQuery(this).parent().parent().siblings('.trial\_info').show(); else jQuery(this).parent().parent().siblings('.trial\_info').hide();" /> <label for="custom\_trial\_<?php echo $level->id;?>"><?php \_e('Check to add a custom trial period.', 'paid-memberships-pro' );?></label>
655
<input id="custom\_trial\_<?php echo esc\_attr( $level->id ); ?>" id="custom\_trial\_<?php echo esc\_attr( $level->id ); ?>" name="custom\_trial\[\]" type="checkbox" value="<?php echo esc\_attr( $level->id ); ?>" <?php if ( pmpro\_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).prop('checked')) jQuery(this).parent().parent().siblings('.trial\_info').show(); else jQuery(this).parent().parent().siblings('.trial\_info').hide();" /> <label for="custom\_trial\_<?php echo esc\_attr( $level->id );?>"><?php \_e('Check to add a custom trial period.', 'paid-memberships-pro' );?></label>
656
656
<?php if($gateway == "twocheckout") { ?>
657
657
<p class="description"><strong <?php if(!empty($pmpro\_twocheckout\_error)) { ?>class="pmpro\_red"<?php } ?>><?php \_e('2Checkout integration does not support custom trials. You can do one period trials by setting an initial payment different from the billing amount.', 'paid-memberships-pro' );?></strong></p>
…
…
673
673
?>
674
674
<?php \_e('for the first', 'paid-memberships-pro' );?>
675
<input name="trial\_limit\[\]" type="text" size="10" value="<?php echo str\_replace("\\"", """, stripslashes($level->trial\_limit))?>" />
675
<input name="trial\_limit\[\]" type="text" size="10" value="<?php echo esc\_attr( $level->trial\_limit ); ?>" />
676
676
<?php \_e('subscription payments', 'paid-memberships-pro' );?>.
677
677
<?php if($gateway == "stripe") { ?>
…
…
687
687
<tr>
688
688
<th scope="row" valign="top"><label><?php \_e('Membership Expiration', 'paid-memberships-pro' );?>:</label></th>
689
<td><input id="expiration\_<?php echo $level->id;?>" name="expiration\[\]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro\_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).is(':checked')) { jQuery(this).parent().parent().siblings('.expiration\_info').show(); } else { jQuery(this).parent().parent().siblings('.expiration\_info').hide();}" /> <label for="expiration\_<?php echo $level->id;?>"><?php \_e('Check this to set when membership access expires.', 'paid-memberships-pro' );?></label></td>
689
<td><input id="expiration\_<?php echo esc\_attr( $level->id ); ?>" name="expiration\[\]" type="checkbox" value="<?php echo esc\_attr( $level->id ); ?>" <?php if(pmpro\_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).is(':checked')) { jQuery(this).parent().parent().siblings('.expiration\_info').show(); } else { jQuery(this).parent().parent().siblings('.expiration\_info').hide();}" /> <label for="expiration\_<?php echo esc\_attr( $level->id ); ?>"><?php \_e('Check this to set when membership access expires.', 'paid-memberships-pro' );?></label></td>
690
690
</tr>
691
691
…
…
693
693
<th scope="row" valign="top"><label for="billing\_amount"><?php \_e('Expires In', 'paid-memberships-pro' );?>:</label></th>
694
694
<td>
695
<input id="expiration\_number" name="expiration\_number\[\]" type="text" size="10" value="<?php echo str\_replace("\\"", """, stripslashes($level->expiration\_number))?>" />
695
<input id="expiration\_number" name="expiration\_number\[\]" type="text" size="10" value="<?php echo esc\_attr( $level->expiration\_number ); ?>" />
696
696
<select id="expiration\_period" name="expiration\_period\[\]">
697
697
<?php
…
…
773
773
<label class="screen-reader-text" for="post-search-input"><?php \_e('Search Discount Codes', 'paid-memberships-pro' );?>:</label>
774
774
<input type="hidden" name="page" value="pmpro-discountcodes" />
775
<input id="post-search-input" type="text" value="<?php if(!empty($s)) echo $s;?>" name="s" size="30" />
776
<input class="button" type="submit" value="<?php \_e('Search', 'paid-memberships-pro' );?>" id="search-submit "/>
775
<input id="post-search-input" type="text" value="<?php echo esc\_attr( wp\_unslash( $s ) ); ?>" name="s" size="30" />
776
<input class="button" type="submit" value="<?php esc\_attr\_e('Search', 'paid-memberships-pro' );?>" id="search-submit "/>
777
777
</p>
778
778
</form>
…
…
807
807
<td><?php echo $code->id?></td>
808
808
<td class="has-row-actions">
809
<a title="<?php echo sprintf( \_\_( 'Edit Code: %s', 'paid-memberships-pro' ), $code->code ); ?>" href="<?php echo add\_query\_arg( array( 'page' => 'pmpro-discountcodes', 'edit' => $code->id ), admin\_url('admin.php' ) ); ?>"><?php echo $code->code?></a>
809
<a title="<?php echo esc\_attr( sprintf( \_\_( 'Edit Code: %s', 'paid-memberships-pro' ), $code->code ) ); ?>" href="<?php echo esc\_url( add\_query\_arg( array( 'page' => 'pmpro-discountcodes', 'edit' => $code->id ), admin\_url('admin.php' ) ) ); ?>"><?php echo $code->code?></a>
810
810
<div class="row-actions">
811
811
<?php