WordPress 高風險項目:SQL
Injection 防範指南
為什麼 WordPress
容易成為 SQL Injection 攻擊目標?
WordPress 表單預設透過 $_POST 取得使用者輸入,若未進行妥善過濾與驗證,極易遭受 SQL Injection
攻擊。以下為建議的防範措施:
一、輸入資料過濾
WordPress 提供許多 資料清洗(Sanitization) 函式,用以過濾使用者輸入:
二、安全執行 SQL 查詢
請避免直接拼接 SQL 字串,應使用 $wpdb->prepare() 處理參數:
參考:wpdb::prepare() 官方文件
三、使用 WordPress 內建 API 處理資料
若資料與文章、使用者、評論等實體有關,建議直接使用內建函式:
wp_insert_post():新增文章
wp_update_post():更新文章
wp_insert_comment():新增評論
這些函式會自動處理資料過濾與轉義。
四、表單與參數驗證實例
1. 使用 parse_request 驗證 GET
參數
2. Elementor 表單欄位驗證
3. Elementor AJAX 提交驗證
五、常見鉤子與資料處理實作
sanitize_post:過濾文章資料
woocommerce_checkout_fields:自訂 WooCommerce 結帳欄位
六、結論
防止 SQL Injection 攻擊的關鍵在於「永遠不要相信來自使用者的輸入」,並善用 WordPress
內建的過濾與轉義函式、資料庫查詢工具(如 $wpdb->prepare())與 API 函式,搭配嚴謹的驗證流程,才能降低網站遭入侵的風險。
WordPress 高風險項目:SQL Injection 防範指南
為什麼 WordPress 容易成為 SQL Injection 攻擊目標?
WordPress 表單預設透過
$_POST取得使用者輸入,若未進行妥善過濾與驗證,極易遭受 SQL Injection 攻擊。以下為建議的防範措施:一、輸入資料過濾
WordPress 提供許多 資料清洗(Sanitization) 函式,用以過濾使用者輸入:
$name = sanitize_text_field($_POST['name']); $email = sanitize_email($_POST['email']); $url = esc_url_raw($_POST['url']);二、安全執行 SQL 查詢
請避免直接拼接 SQL 字串,應使用
$wpdb->prepare()處理參數:global $wpdb; $name = sanitize_text_field($_POST['name']); $email = sanitize_email($_POST['email']); $sql = $wpdb->prepare( "INSERT INTO {$wpdb->prefix}mytable (name, email) VALUES (%s, %s)", $name, $email ); $wpdb->query($sql);%s:代表字串%d:代表整數%f:代表浮點數參考:wpdb::prepare() 官方文件
三、使用 WordPress 內建 API 處理資料
若資料與文章、使用者、評論等實體有關,建議直接使用內建函式:
wp_insert_post():新增文章wp_update_post():更新文章wp_insert_comment():新增評論這些函式會自動處理資料過濾與轉義。
四、表單與參數驗證實例
1. 使用 parse_request 驗證 GET 參數
add_action('parse_request', 'validate_get_params'); function validate_get_params($wp) { if ('GET' !== $_SERVER['REQUEST_METHOD']) return; $pattern = '/^case\srandomblob\(\d+\)\swhen\snot\snull\sthen\s\d\selse\s\d\send/i'; $rule = '/case\srandomblob/i'; foreach ($_GET as $key => $value) { $value = sanitize_text_field($value); if (($key === 'id' || $key === 'p') && !is_numeric($value)) { $wp->query_vars['error'] = 404; return; } if (preg_match($pattern, $value) || preg_match($rule, $value)) { $wp->query_vars['error'] = 404; return; } } }2. Elementor 表單欄位驗證
add_action('elementor_pro/forms/validation', 'validate_elementor_form', 10, 2); function validate_elementor_form($record, $ajax_handler) { $fields = $record->get('fields'); $regex = '/^[0-9a-zA-Z]+$/'; $pattern = '/^case\srandomblob\(\d+\)\swhen\snot\snull\sthen\s\d\selse\s\d\send/i'; $rule = '/case\srandomblob/i'; $form_fields = ['post_id', 'form_id', 'queried_id', '_wpnonce']; foreach ($fields as $key => $value) { $value = sanitize_text_field($value); if (in_array($key, $form_fields) && !preg_match($regex, $value)) { $ajax_handler->add_error('非法格式'); return; } if (preg_match($pattern, $value) || preg_match($rule, $value)) { $ajax_handler->add_error('偵測到 SQL Injection 攻擊'); return; } } }3. Elementor AJAX 提交驗證
add_action('elementor_pro/forms/new_record', 'check_elementor_ajax', 10, 2); function check_elementor_ajax($record, $handler) { $fields = $record->get('fields'); $regex = '/^[0-9a-zA-Z]+$/'; $pattern = '/^case\srandomblob\(\d+\)\swhen\snot\snull\sthen\s\d\selse\s\d\send/i'; $rule = '/case\srandomblob/i'; $form_fields = ['post_id', 'form_id', 'queried_id', '_wpnonce']; foreach ($fields as $key => $value) { $value = sanitize_text_field($value); if (in_array($key, $form_fields) && !preg_match($regex, $value)) { $handler->set_success(false); } if (preg_match($pattern, $value) || preg_match($rule, $value)) { $handler->set_success(false); } } }五、常見鉤子與資料處理實作
sanitize_post:過濾文章資料add_filter('sanitize_post', 'filter_contact_form'); function filter_contact_form($data) { if ($data['post_type'] === 'contact-us') { $data['post_title'] = sanitize_text_field($data['post_title']); } return $data; }comment_form_default_fields:自訂評論欄位add_filter('comment_form_default_fields', 'custom_comment_fields'); function custom_comment_fields($fields) { $fields['author'] = '<input id="author" name="author" type="text" />'; $fields['email'] = '<input id="email" name="email" type="email" />'; $fields['url'] = '<input id="url" name="url" type="url" />'; return $fields; }woocommerce_checkout_fields:自訂 WooCommerce 結帳欄位add_filter('woocommerce_checkout_fields', 'custom_checkout_fields'); function custom_checkout_fields($fields) { $fields['billing']['billing_first_name']['label'] = '名字'; $fields['billing']['my_custom_field'] = [ 'label' => '自定欄位', 'required' => false, 'class' => ['form-row-wide'], 'clear' => true ]; return $fields; }六、結論
防止 SQL Injection 攻擊的關鍵在於「永遠不要相信來自使用者的輸入」,並善用 WordPress 內建的過濾與轉義函式、資料庫查詢工具(如
$wpdb->prepare())與 API 函式,搭配嚴謹的驗證流程,才能降低網站遭入侵的風險。