You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WP List Table数据清理不规范及SQL调用不安全问题求助

WordPress数据清理与SQL注入防护修正方案

原代码存在的核心问题

  1. 数据清理不完整:部分数据库内容直接输出未转义,存在XSS风险;固定HTML标签被错误转义导致功能失效。
  2. SQL注入风险:批量删除时直接拼接用户提交的ID到SQL语句,未使用wpdb->prepare()进行参数绑定。

修正后的完整代码

class dsvatcalculator_List_Table extends WP_List_Table
{
    function __construct()
    {
        global $status, $page;
        parent::__construct(array(
            'singular' => 'vat',
            'plural'   => 'vats',
        ));
    }

    function column_default($item, $column_name)
    {
        // 对默认列内容进行HTML转义,防止XSS
        return esc_html($item[$column_name]);
    }

    function column_country($item)
    {
        // 转义数据库内容后再包裹标签
        return '<em>' . esc_html($item['country']) . '</em>';
    }

    function column_vat($item)
    {
        $actions = array(
            'edit' => sprintf('<a href="?page=vats_form&id=%s">%s</a>', absint($item['id']), __('Edit', 'ds-vat-calculator')),
            'delete' => sprintf('<a href="?page=%s&action=delete&id=%s">%s</a>', esc_attr($_REQUEST['page']), absint($item['id']), __('Delete', 'ds-vat-calculator')),
        );
        return sprintf('%s %s',
            esc_html($item['vat']),
            $this->row_actions($actions)
        );
    }

    function column_cb($item)
    {
        return sprintf(
            '<input type="checkbox" name="id[]" value="%s" />',
            absint($item['id'])
        );
    }

    function get_columns()
    {
        $columns = array(
            'cb' => '<input type="checkbox" />', // 固定HTML无需转义,否则复选框失效
            'vat'      => esc_html__('VAT Rate', 'ds-vat-calculator'),
            'country'  => esc_html__('Country Name', 'ds-vat-calculator'),
        );
        return $columns;
    }

    function get_sortable_columns()
    {
        $sortable_columns = array(
            'vat'      => array('vat', true),
            'country'  => array('country', true),
        );
        return $sortable_columns;
    }

    function get_bulk_actions()
    {
        $actions = array(
            'delete' => 'Delete'
        );
        return $actions;
    }

    function process_bulk_action()
    {
        global $wpdb;
        $dsvatcalculator_tbl = $wpdb->prefix . 'dsvatcalculator_vat_calculator';

        if ('delete' === $this->current_action()) {
            $idsvatcalculator = isset($_REQUEST['id']) ? (array) $_REQUEST['id'] : array();
            // 强制转换为整数,过滤非数值ID
            $idsvatcalculator = array_map('absint', $idsvatcalculator);
            // 移除空值,避免无效参数
            $idsvatcalculator = array_filter($idsvatcalculator);

            if (!empty($idsvatcalculator)) {
                // 生成占位符,通过prepare绑定参数防止注入
                $placeholders = implode(',', array_fill(0, count($idsvatcalculator), '%d'));
                $wpdb->query($wpdb->prepare("DELETE FROM $dsvatcalculator_tbl WHERE id IN($placeholders)", $idsvatcalculator));
            }
        }
    }

    function prepare_items()
    {
        global $wpdb;
        $dsvatcalculator_tbl = $wpdb->prefix . 'dsvatcalculator_vat_calculator';
        $per_page = 10;

        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = array($columns, $hidden, $sortable);

        $this->process_bulk_action();

        // 使用prepare处理表名查询,符合WordPress安全规范
        $total_items = $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM %s", $dsvatcalculator_tbl));

        $paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged']) - 1) : 0;
        $orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array_keys($this->get_sortable_columns()))) ? $_REQUEST['orderby'] : 'country';
        $order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('asc', 'desc'))) ? $_REQUEST['order'] : 'asc';

        // 验证并 sanitize 排序语句,确保SQL安全
        $order_clause = sanitize_sql_orderby("$orderby $order");
        if (!$order_clause) {
            $order_clause = 'country ASC';
        }

        $this->items = $wpdb->get_results($wpdb->prepare("SELECT * FROM $dsvatcalculator_tbl ORDER BY %s LIMIT %d OFFSET %d", $order_clause, $per_page, $paged), ARRAY_A);

        $this->set_pagination_args(array(
            'total_items' => $total_items,
            'per_page' => $per_page,
            'total_pages' => ceil($total_items / $per_page)
        ));
    }
}

关键修改说明

1. 数据清理优化

  • column_default/column_country:添加esc_html()转义数据库输出内容,彻底避免XSS攻击。
  • get_columns:移除复选框标签的esc_html()转义,固定HTML无需转义,否则会导致复选框无法正常渲染。
  • 参数过滤:对URL中的ID使用absint()强制转换为整数,确保参数安全。

2. SQL注入防护

  • 批量删除逻辑:通过array_map('absint')过滤ID,生成动态占位符后用wpdb->prepare()绑定参数,杜绝直接拼接SQL的风险。
  • 排序处理:使用sanitize_sql_orderby()验证排序语句,若验证失败则使用默认值,避免恶意排序参数注入。
  • 统计查询:即使无用户输入,也使用wpdb->prepare()处理表名查询,符合WordPress安全规范。

内容的提问来源于stack exchange,提问作者Md Nazmul Haque

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:15:34