WP List Table数据清理不规范及SQL调用不安全问题求助
WordPress数据清理与SQL注入防护修正方案
原代码存在的核心问题
- 数据清理不完整:部分数据库内容直接输出未转义,存在XSS风险;固定HTML标签被错误转义导致功能失效。
- 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
相关产品推荐
相关产品推荐

