Headline
CVE-2023-3201: Changeset 2925048 for mstore-api – WordPress Plugin Repository
The MStore API plugin for WordPress is vulnerable to Cross-Site Request Forgery due to missing nonce validation on the mstore_update_new_order_title function. This makes it possible for unauthenticated attackers to update new order title via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
mstore-api/trunk/assets/js/mstore-inspireui.js
r2610824
r2925048
22
22
$(document).on('blur', '.mstore-update-limit-product', function () {
23
23
var limit = $(this).val();
24
var nonce = $(this).data('nonce');
24
25
$.ajax({
25
26
type: 'post',
…
…
27
28
data: {
28
29
action: 'mstore\_update\_limit\_product',
29
limit: limit
30
limit: limit,
31
nonce: nonce
30
32
},
31
33
success: function (result) {
…
…
39
41
$(document).on('blur', '.mstore-update-firebase-server-key', function () {
40
42
var serverKey = $(this).val();
43
var nonce = $(this).data('nonce');
41
44
$.ajax({
42
45
type: 'post',
…
…
44
47
data: {
45
48
action: 'mstore\_update\_firebase\_server\_key',
46
serverKey: serverKey
49
serverKey: serverKey,
50
nonce: nonce
47
51
},
48
52
success: function (result) {
…
…
56
60
$(document).on('blur', '.mstore-update-new-order-title', function () {
57
61
var title = $(this).val();
62
var nonce = $(this).data('nonce');
58
63
$.ajax({
59
64
type: 'post',
…
…
61
66
data: {
62
67
action: 'mstore\_update\_new\_order\_title',
63
title: title
68
title: title,
69
nonce: nonce
64
70
},
65
71
success: function (result) {
…
…
73
79
$(document).on('blur', '.mstore-update-new-order-message', function () {
74
80
var message = $(this).val();
81
var nonce = $(this).data('nonce');
75
82
$.ajax({
76
83
type: 'post',
…
…
78
85
data: {
79
86
action: 'mstore\_update\_new\_order\_message',
80
message: message
87
message: message,
88
nonce: nonce
81
89
},
82
90
success: function (result) {
…
…
90
98
$(document).on('blur', '.mstore-update-status-order-title', function () {
91
99
var title = $(this).val();
100
var nonce = $(this).data('nonce');
92
101
$.ajax({
93
102
type: 'post',
…
…
95
104
data: {
96
105
action: 'mstore\_update\_status\_order\_title',
97
title: title
106
title: title,
107
nonce: nonce
98
108
},
99
109
success: function (result) {
…
…
107
117
$(document).on('blur', '.mstore-update-status-order-message', function () {
108
118
var message = $(this).val();
119
var nonce = $(this).data('nonce');
109
120
$.ajax({
110
121
type: 'post',
…
…
112
123
data: {
113
124
action: 'mstore\_update\_status\_order\_message',
114
message: message
125
message: message,
126
nonce: nonce
115
127
},
116
128
success: function (result) {
mstore-api/trunk/controllers/flutter-booking.php
r2924554
r2925048
188
188
global $wpdb;
189
189
$table\_name = $wpdb->prefix . "wc\_appointment\_relationships";
190
$items = $wpdb->get\_results("SELECT \* FROM $table\_name WHERE product\_id = '$product\_id'");
190
$sql = $wpdb->prepare("SELECT \* FROM $table\_name WHERE product\_id = '$product\_id'");
191
$items = $wpdb->get\_results($sql);
191
192
foreach ($items as $item) {
192
193
$user = get\_user\_by("ID", $item->staff\_id);
mstore-api/trunk/controllers/flutter-wholesale.php
r2924554
r2925048
75
75
$role = $params\["role"\];
76
76
77
if (isset($role) && in\_array($role, \['administrator','owner'\], true)) {
77
if (!class\_exists('WooCommerceWholeSalePrices')) {
78
return parent::sendError("invalid\_plugin", "You need to install WooCommerce Wholesale Prices plugin to use this api", 404);
79
}
80
global $wc\_wholesale\_prices;
81
$data = $wc\_wholesale\_prices->wwp\_wholesale\_roles->getAllRegisteredWholesaleRoles();
82
$roles = \[\];
83
$roles = array\_keys($data);
84
$roles\[\] = 'subscriber';
85
if (!isset($role) || !in\_array($role,$roles, true)) {
78
86
return parent::sendError("invalid\_role", "Role is invalid.", 400);
79
87
}
mstore-api/trunk/mstore-api.php
r2924554
r2925048
4
4
* Plugin URI: https://github.com/inspireui/mstore-api
5
5
* Description: The MStore API Plugin which is used for the MStore and FluxStore Mobile App
6
* Version: 3.9.6
6
* Version: 3.9.7
7
7
* Author: InspireUI
8
8
* Author URI: https://inspireui.com
…
…
41
41
class MstoreCheckOut
42
42
{
43
public $version = '3.9.6';
43
public $version = '3.9.7';
44
44
45
45
public function \_\_construct()
…
…
213
213
214
214
function mstore\_delete\_json\_file(){
215
if(current\_user\_can( 'edit\_posts' )){
215
if(checkIsAdmin(get\_current\_user\_id())){
216
216
$id = sanitize\_text\_field($\_REQUEST\['id'\]);
217
217
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
218
218
FlutterUtils::delete\_config\_file($id, $nonce);
219
}else{
220
wp\_send\_json\_error('No Permission',401);
219
221
}
220
222
}
…
…
222
224
function mstore\_update\_limit\_product()
223
225
{
224
if(current\_user\_can( 'edit\_posts' )){
226
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
227
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_limit\_product')){
225
228
$limit = sanitize\_text\_field($\_REQUEST\['limit'\]);
226
229
if (is\_numeric($limit)) {
227
230
update\_option("mstore\_limit\_product", intval($limit));
228
231
}
232
}else{
233
wp\_send\_json\_error('No Permission',401);
229
234
}
230
235
}
…
…
232
237
function mstore\_update\_firebase\_server\_key()
233
238
{
234
if(current\_user\_can( 'edit\_posts' )){
239
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
240
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_firebase\_server\_key')){
235
241
$serverKey = sanitize\_text\_field($\_REQUEST\['serverKey'\]);
236
242
update\_option("mstore\_firebase\_server\_key", $serverKey);
243
}else{
244
wp\_send\_json\_error('No Permission',401);
237
245
}
238
246
}
…
…
240
248
function mstore\_update\_new\_order\_title()
241
249
{
242
if(current\_user\_can( 'edit\_posts' )){
250
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
251
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_new\_order\_title')){
243
252
$title = sanitize\_text\_field($\_REQUEST\['title'\]);
244
253
update\_option("mstore\_new\_order\_title", $title);
254
}else{
255
wp\_send\_json\_error('No Permission',401);
245
256
}
246
257
}
…
…
248
259
function mstore\_update\_new\_order\_message()
249
260
{
250
if(current\_user\_can( 'edit\_posts' )){
261
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
262
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_new\_order\_message')){
251
263
$message = sanitize\_text\_field($\_REQUEST\['message'\]);
252
264
update\_option("mstore\_new\_order\_message", $message);
265
}else{
266
wp\_send\_json\_error('No Permission',401);
253
267
}
254
268
}
…
…
256
270
function mstore\_update\_status\_order\_title()
257
271
{
258
if(current\_user\_can( 'edit\_posts' )){
272
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
273
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_status\_order\_title')){
259
274
$title = sanitize\_text\_field($\_REQUEST\['title'\]);
260
275
update\_option("mstore\_status\_order\_title", $title);
276
}else{
277
wp\_send\_json\_error('No Permission',401);
261
278
}
262
279
}
…
…
264
281
function mstore\_update\_status\_order\_message()
265
282
{
266
if(current\_user\_can( 'edit\_posts' )){
283
$nonce = sanitize\_text\_field($\_REQUEST\['nonce'\]);
284
if(checkIsAdmin(get\_current\_user\_id()) && wp\_verify\_nonce($nonce, 'update\_status\_order\_message')){
267
285
$message = sanitize\_text\_field($\_REQUEST\['message'\]);
268
286
update\_option("mstore\_status\_order\_message", $message);
287
}else{
288
wp\_send\_json\_error('No Permission',401);
269
289
}
270
290
}
mstore-api/trunk/readme.txt
r2924554
r2925048
4
4
Requires at least: 4.4
5
5
Tested up to: 6.0.0
6
Stable tag: 3.9.6
6
Stable tag: 3.9.7
7
7
License: GPL-2.0
8
8
License URI: https://www.gnu.org/licenses/gpl-2.0.html
…
…
44
44
45
45
== Changelog ==
46
= 3.9.7 =
47
* Fix security issues
48
46
49
= 3.9.6 =
47
50
* Fix security issues
mstore-api/trunk/templates/admin/mstore-api-admin-dashboard.php
r2924554
r2925048
74
74
?>
75
75
<div class="form-group" style="margin-top:10px;margin-bottom:40px">
76
<input type="number" value="<?php echo (!isset($limit) || $limit == false) ? 10 : esc\_attr($limit) ?>"
76
<input type="number" data-nonce="<?php echo wp\_create\_nonce('update\_limit\_product'); ?>" value="<?php echo (!isset($limit) || $limit == false) ? 10 : esc\_attr($limit) ?>"
77
77
class="mstore-update-limit-product">
78
78
</div>
…
…
88
88
?>
89
89
<div class="form-group" style="margin-top:10px;margin-bottom:40px">
90
<textarea class="mstore-update-firebase-server-key mstore\_input"
90
<textarea data-nonce="<?php echo wp\_create\_nonce('update\_firebase\_server\_key'); ?>" class="mstore-update-firebase-server-key mstore\_input"
91
91
style="height: 120px"><?php echo esc\_attr($serverKey) ?></textarea>
92
92
</div>
…
…
108
108
?>
109
109
<div class="form-group" style="margin-top:10px;">
110
<input type="text" placeholder="Title" value="<?php echo esc\_attr($newOrderTitle); ?>"
110
<input type="text" placeholder="Title" data-nonce="<?php echo wp\_create\_nonce('update\_new\_order\_title'); ?>" value="<?php echo esc\_attr($newOrderTitle); ?>"
111
111
class="mstore-update-new-order-title mstore\_input">
112
112
</div>
113
113
<div class="form-group" style="margin-top:10px;margin-bottom:40px">
114
<textarea placeholder="Message" class="mstore-update-new-order-message mstore\_input"
114
<textarea placeholder="Message" data-nonce="<?php echo wp\_create\_nonce('update\_new\_order\_message'); ?>" class="mstore-update-new-order-message mstore\_input"
115
115
style="height: 120px"><?php echo esc\_attr($newOrderMsg); ?></textarea>
116
116
</div>
…
…
132
132
?>
133
133
<div class="form-group" style="margin-top:10px;">
134
<input type="text" placeholder="Title" value="<?php echo esc\_attr($statusOrderTitle); ?>"
134
<input type="text" placeholder="Title" data-nonce="<?php echo wp\_create\_nonce('update\_status\_order\_title'); ?>" value="<?php echo esc\_attr($statusOrderTitle); ?>"
135
135
class="mstore-update-status-order-title mstore\_input">
136
136
</div>
137
137
<div class="form-group" style="margin-top:10px;margin-bottom:40px">
138
<textarea placeholder="Message" class="mstore-update-status-order-message mstore\_input"
138
<textarea placeholder="Message" data-nonce="<?php echo wp\_create\_nonce('update\_status\_order\_message'); ?>" class="mstore-update-status-order-message mstore\_input"
139
139
style="height: 120px"><?php echo esc\_attr($statusOrderMsg); ?></textarea>
140
140
</div>