Skip to content

Commit

Permalink
fix: unsafe request params
Browse files Browse the repository at this point in the history
  • Loading branch information
lelinhtinh committed Nov 29, 2022
1 parent 681161c commit b21059c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 53 deletions.
25 changes: 15 additions & 10 deletions admin/class-coupon-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ public function options_admin()
public function create_coupon()
{
check_ajax_referer($this->plugin_prefix . $this->plugin_name . '_create_nonce');
if (!$_POST['action'] || $_POST['action'] !== 'oms_coupon_create' || !current_user_can('administrator')) {
if (get_request_parameter('action') !== 'oms_coupon_create' || !current_user_can('administrator')) {
header('Status: 403 Forbidden', true, 403);
wp_die();
}

$user_id = get_current_user_id();
$code = sanitize_key($_POST['code']);
$code = sanitize_key(get_request_parameter('code'));

global $wpdb;
$findOne = $wpdb->get_row($wpdb->prepare(
Expand All @@ -137,14 +137,19 @@ public function create_coupon()
], 400);
}

$type = in_array($_POST['type'], ['percentage', 'numeric']) ? $_POST['type'] : 'percentage';
$value = !empty($_POST['value']) ? intval($_POST['value']) : null;
$limit = !empty($_POST['limit']) ? intval($_POST['limit']) : null;
$activated_at = !empty($_POST['activated_at']) ? tz_strtodate($_POST['activated_at']) : null;
$expired_at = !empty($_POST['expired_at']) ? tz_strtodate($_POST['expired_at']) : null;
$type = get_request_parameter('type', 'percentage');
$type = in_array($type, ['percentage', 'numeric'], true) ? $type : 'percentage';
$value = get_request_parameter('value');
$value = !$value ? null : intval($value);
$limit = get_request_parameter('limit');
$limit = !$limit ? null : intval($limit);
$activated_at = get_request_parameter('activated_at');
$activated_date = !$activated_at ? null : tz_strtodate($activated_at);
$expired_at = get_request_parameter('expired_at');
$expired_date = !$expired_at ? null : tz_strtodate($expired_at);
if (
!is_null($activated_at) && !is_null($expired_at)
&& tz_strtodate($_POST['activated_at'], true) > tz_strtodate($_POST['expired_at'], true)
&& tz_strtodate($activated_at, true) > tz_strtodate($expired_at, true)
) {
wp_send_json([
'status' => 'error',
Expand All @@ -157,8 +162,8 @@ public function create_coupon()
'type' => $type,
'value' => $value,
'limit' => $limit,
'activated_at' => $activated_at,
'expired_at' => $expired_at,
'activated_at' => $activated_date,
'expired_at' => $expired_date,
'created_by' => $user_id,
];
$wpdb->insert(
Expand Down
28 changes: 16 additions & 12 deletions admin/partials/coupon-admin-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ protected function column_cb($item)
*/
protected function column_code($item)
{
$page = wp_unslash($_REQUEST['page']);
$page = get_request_parameter('page', 1);

// Build hide row action.
$hide_query_args = [
Expand Down Expand Up @@ -297,9 +297,13 @@ protected function get_bulk_actions()
protected function process_bulk_action()
{
global $wpdb;
if (isset($_GET[$this->_args['singular']])) {
$coupon_params = wp_unslash($_GET[$this->_args['singular']]);
$ids = is_array($coupon_params) ? implode(',', $coupon_params) : $coupon_params;

if (isset($_REQUEST[$this->_args['singular']])) {
$coupon_params = get_request_parameter($this->_args['singular']);
$ids = is_array($coupon_params)
? implode(',', array_map('intval', $coupon_params))
: intval($coupon_params);

switch ($this->current_action()) {
case 'hide':
$wpdb->query($wpdb->prepare(
Expand Down Expand Up @@ -382,27 +386,27 @@ public function prepare_items()
$this->process_bulk_action();

// If no sort, default to ID.
$orderby = !empty($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], $sortable, true) ? $_REQUEST['orderby'] : 'ID';
$order = !empty($_REQUEST['order']) && 'ASC' === strtoupper($_REQUEST['order']) ? 'ASC' : 'DESC';
$orderby = get_request_parameter('orderby', 'ID');
if (!in_array($orderby, array_keys($sortable), true)) {
$orderby = 'ID';
}
$order = 'ASC' === strtoupper(get_request_parameter('order')) ? 'ASC' : 'DESC';
$orderby_sql = 'c.' . sanitize_sql_orderby("{$orderby} {$order}");

/*
* GET THE DATA!
*/
$data = $wpdb->get_results($wpdb->prepare(
"
SELECT
"SELECT
c.ID, c.code, c.type, c.value, c.limit, c.activated_at, c.expired_at,
GROUP_CONCAT(u.display_name SEPARATOR ', ') AS used_by, COUNT(u.ID) AS number_of_uses
FROM {$wpdb->prefix}oms_coupons AS c
LEFT JOIN {$wpdb->prefix}oms_coupons_user AS cu ON cu.oms_coupon_id = c.ID
LEFT JOIN {$wpdb->prefix}users AS u ON cu.user_id = u.ID
WHERE c.active = 1
GROUP BY c.ID, c.code, c.type, c.value, c.limit, c.activated_at, c.expired_at
ORDER BY %s
LIMIT %d OFFSET %d
",
$orderby_sql,
ORDER BY {$orderby_sql}
LIMIT %1\$d OFFSET %2\$d",
$per_page,
$offset_page,
), ARRAY_A);
Expand Down
14 changes: 8 additions & 6 deletions public/class-coupon-public.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,13 @@ public function oms_shortcode_func($atts = [], $content = null, $tag = '')

global $wpdb;
$findOne = $wpdb->get_row($wpdb->prepare(
"
SELECT
"SELECT
c.ID, c.code, c.type, c.value, c.limit, c.activated_at, c.expired_at,
COUNT(cu.user_id) AS number_of_uses, GROUP_CONCAT(cu.user_id SEPARATOR ',') AS used_by_id
FROM {$wpdb->prefix}oms_coupons AS c
LEFT JOIN {$wpdb->prefix}oms_coupons_user AS cu ON cu.oms_coupon_id = c.ID
WHERE c.ID = %d AND c.active = 1
GROUP BY c.ID, c.code, c.type, c.value, c.limit, c.activated_at, c.expired_at
",
GROUP BY c.ID, c.code, c.type, c.value, c.limit, c.activated_at, c.expired_at",
$coupon_id,
), OBJECT);

Expand Down Expand Up @@ -218,13 +216,17 @@ public function options_user()
public function save_coupon()
{
check_ajax_referer($this->plugin_prefix . $this->plugin_name . '_save_nonce');
if (!$_POST['action'] || $_POST['action'] !== 'oms_coupon_save') {
if (get_request_parameter('action') !== 'oms_coupon_save') {
header('Status: 403 Forbidden', true, 403);
wp_die();
}

$user_id = get_current_user_id();
$coupon_id = intval($_POST['id']);
$coupon_id = intval(get_request_parameter('id'));
if (!$coupon_id) {
header('Status: 400 Bad Request', true, 400);
wp_die();
}
$now = tz_strtodate('now');

global $wpdb;
Expand Down
53 changes: 28 additions & 25 deletions public/partials/coupon-public-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ protected function column_cb($item)
protected function column_code($item)
{
$user_id = get_current_user_id();
$page = wp_unslash($_REQUEST['page']);
$page = get_request_parameter('page', 1);

if ($item['user_id'] == $user_id) {
// Build hide row action.
Expand Down Expand Up @@ -287,21 +287,25 @@ protected function process_bulk_action()
global $wpdb;
$user_id = get_current_user_id();

if (isset($_GET[$this->_args['singular']])) {
$coupon_params = wp_unslash($_GET[$this->_args['singular']]);
$ids = is_array($coupon_params) ? implode(',', $coupon_params) : $coupon_params;
if (isset($_REQUEST[$this->_args['singular']])) {
$coupon_params = get_request_parameter($this->_args['singular']);
$ids = is_array($coupon_params)
? implode(',', array_map('intval', $coupon_params))
: intval($coupon_params);

if ($this->current_action() === 'hide') {
$wpdb->query($wpdb->prepare(
"UPDATE {$wpdb->prefix}oms_coupons_user SET active = 0 WHERE oms_coupon_id IN(%s) AND user_id = %d",
"UPDATE {$wpdb->prefix}oms_coupons_user SET active = 0
WHERE oms_coupon_id IN(%s) AND user_id = %d",
$ids,
$user_id,
));
}

if ($this->current_action() === 'delete' && current_user_can('administrator')) {
$wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->prefix}oms_coupons_user WHERE oms_coupon_id IN(%s)",
"DELETE FROM {$wpdb->prefix}oms_coupons_user
WHERE oms_coupon_id IN(%s)",
$ids,
));
}
Expand Down Expand Up @@ -342,7 +346,9 @@ public function prepare_items()
*/
$total_items = $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->prefix}oms_coupons_user WHERE active = 1"
. current_user_can('administrator') ? '' : $wpdb->prepare(" AND user_id = %d", $user_id)
. current_user_can('administrator')
? ''
: $wpdb->prepare(" AND user_id = %d", $user_id)
);

/*
Expand Down Expand Up @@ -371,46 +377,43 @@ public function prepare_items()
$this->process_bulk_action();

// If no sort, default to user_id.
$orderby = !empty($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], $sortable, true) ? $_REQUEST['orderby'] : 'user_id';
$orderby = ($orderby === 'saved_at' || $orderby === 'user_id'
$orderby = get_request_parameter('orderby', 'user_id');
if (!in_array($orderby, array_keys($sortable), true)) {
$orderby = 'user_id';
}
$alias = ($orderby === 'saved_at' || $orderby === 'user_id'
? 'cu.'
: ($orderby === 'display_name' ? 'u.' : 'c.')
) . $orderby;
$order = !empty($_REQUEST['order']) && 'DESC' === strtoupper($_REQUEST['order']) ? 'DESC' : 'ASC';
$orderby_sql = sanitize_sql_orderby("{$orderby} {$order}");
);
$order = 'DESC' === strtoupper(get_request_parameter('order')) ? 'DESC' : 'ASC';
$orderby_sql = $alias . sanitize_sql_orderby("{$orderby} {$order}");

/*
* GET THE DATA!
*/
if (current_user_can('administrator')) {
$data = $wpdb->get_results($wpdb->prepare(
"
SELECT
"SELECT
c.ID, c.code, c.type, c.value, c.expired_at, cu.saved_at, cu.user_id, u.display_name
FROM {$wpdb->prefix}oms_coupons AS c
LEFT JOIN {$wpdb->prefix}oms_coupons_user AS cu ON cu.oms_coupon_id = c.ID
LEFT JOIN {$wpdb->prefix}users AS u ON cu.user_id = u.ID
WHERE cu.active = 1
ORDER BY %s
LIMIT %d OFFSET %d
",
$orderby_sql,
ORDER BY {$orderby_sql}
LIMIT %1\$d OFFSET %2\$d",
$per_page,
$offset_page,
), ARRAY_A);
} else {
$data = $wpdb->get_results($wpdb->prepare(
"
SELECT
"SELECT
c.ID, c.code, c.type, c.value, c.expired_at, cu.saved_at, cu.user_id
FROM {$wpdb->prefix}oms_coupons AS c
LEFT JOIN {$wpdb->prefix}oms_coupons_user AS cu ON cu.oms_coupon_id = c.ID
WHERE cu.active = 1 AND user_id = %d
ORDER BY %s
LIMIT %d OFFSET %d
",
WHERE cu.active = 1 AND user_id = %1\$d
ORDER BY {$orderby_sql}
LIMIT %2\$d OFFSET %3\$d",
$user_id,
$orderby_sql,
$per_page,
$offset_page,
), ARRAY_A);
Expand Down

0 comments on commit b21059c

Please sign in to comment.