- CSP สำหรับ WordPress ค่อนข้างยุ่งยาก ปรับโน่นนิดปิดนี่หน่อย เว็บเพี้ยน
- เมื่อลองค้นไป ก็เจอปลักอินอยู่ตัวนึง ที่ช่วยสร้าง CSP ให้อัตโนมัติ นั่นคือ CSP-ANTS&STP แต่เนื่องจากปลักอินตัวนี้ไม่ได้รับการปรับปรุงมาตั้งแต่ 2022 ซึ่งนานเกินไป แล้ว แต่จริงๆ มันยังใช้ได้อยู่
- แต่ปลั๊กอินก็ยังมีบักเมื่อไปตรวจกับเว็บ https://securityheaders.com แล้วจะมีข้อความเตือนดังภาพ

- เพื่อแก้ปัญหานี้เลยต้องเขียนปลักอินตัวนี้ลงในปลักอินอีกตัวที่ชื่อ Woody snippets
- คลิก Add ใน Woody snippets เพิ่มข้อความต่อไปนี้ ส่วนนี้ได้แก้ไข Error บน https://securityheaders.com แล้วด้วย
CSP-ANTS&STP
/**
* Plugin Name: CSP-ANTS&ST
* Description: Add a nonce to each script and style tags, and set those nonces in CSP header
* Version: 1.1.1
* Requires at least: 5.9
* Requires PHP: 7.3
* Author: Pascal CESCATO
* Author URI: https://pascalcescato.gdn/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
add_action('send_headers', function () {
if (is_admin()){
header("Content-Security-Policy: upgrade-insecure-requests");
return;
}
//เลือก page ที่ไม่ต้องการให้ CSP ทำงาน
if (is_page(['cd-key'])){
header("Content-Security-Policy: upgrade-insecure-requests");
return;
}
if (function_exists('litespeed_autoload')):
// lscache version
function cspantsst_cspantsst_lscwp_check ( $content ) {
$uris = implode ( ' ', cspantsst_search_for_sources ( $content ) );
$sha256_csp = cspantsst_search_for_events ( $content );
$nonces = [];
$content = preg_replace_callback ( '#<script.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<script', "<script nonce='{$nonce}'", $matches[ 0 ] );
}, $content );
$content = preg_replace_callback ( '#<style.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<style', "<style nonce='{$nonce}'", $matches[ 0 ] );
}, $content );
$nonces_csp = array_reduce ( $nonces, function ( $header, $nonce ) {
return "{$header} 'nonce-{$nonce}'";
}, '' );
header ( sprintf ( "Content-Security-Policy: base-uri 'self' %1s data:; object-src 'none'; script-src https:%2s %3s 'strict-dynamic'; frame-ancestors 'none'; ", $uris, $nonces_csp, $sha256_csp ));
return $content;
}
add_filter ( 'litespeed_buffer_after', 'cspantsst_cspantsst_lscwp_check', 0 );
else:
// otherwise
add_action ( 'template_redirect', function () {
ob_start ( function ( $output ) {
$uris = implode ( ' ', cspantsst_search_for_sources ( $output ) );
$sha256_csp = cspantsst_search_for_events ( $output );
$nonces = [];
$output = preg_replace_callback ( '#<script.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<script', "<script nonce='{$nonce}'", $matches[ 0 ] );
}, $output );
$output = preg_replace_callback ( '#<style.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<style', "<style nonce='{$nonce}'", $matches[ 0 ] );
}, $output );
$header = '';
$nonces_csp = array_reduce ( $nonces, function ( $header, $nonce ) {
return "{$header} 'nonce-{$nonce}'";
}, '' );
header ( sprintf ( "Content-Security-Policy: base-uri 'self' %1s data:; object-src 'none'; script-src https:%2s %3s 'strict-dynamic'; frame-ancestors 'none';", $uris, $nonces_csp, $sha256_csp ) );
return $output;
} );
} );
endif;
function cspantsst_search_for_events ( $output ) {
$sha256 = array ();
preg_match_all ( '/onload="(?<onload>[^"]+)"|onclick="(?<onclick>[^"]+)"/', $output, $matches );
foreach ( $matches[ 'onload' ] as $match ):
if ( !empty ( $match ) )
$sha256[] = base64_encode ( hash ( 'sha256', $match, true ) );
endforeach;
foreach ( $matches[ 'onclick' ] as $match ):
if ( !empty ( $match ) )
$sha256[] = base64_encode ( hash ( 'sha256', $match, true ) );
endforeach;
if ( class_exists ( 'autoptimizeConfig' ) ):
$sha256[] = base64_encode ( hash ( 'sha256', "this.onload=null;this.media='all';", true ) );
endif;
$header_sha256 = "'unsafe-hashes'";
$sha256_csp = array_reduce ( $sha256, function ( $header, $sha256_item ) {
return "{$header} 'sha256-{$sha256_item}'";
}, '' );
if ( !empty ( $sha256_csp ) )
$sha256_csp = $header_sha256 . $sha256_csp;
return $sha256_csp;
}
function cspantsst_search_for_sources ( $string ) {
$result = array ();
if ( strpos ( $string, 'https://secure.gravatar.com/avatar/' ) ):
$result[] = 'https://secure.gravatar.com/avatar/';
endif;
if ( strpos ( $string, 'https://fonts.googleapis.com/' ) ):
$result[] = 'https://fonts.googleapis.com/';
endif;
if ( strpos ( $string, 'https://maxcdn.bootstrapcdn.com/' ) ):
$result[] = 'https://maxcdn.bootstrapcdn.com/';
endif;
return $result;
}
});
- และใน code นี้มีส่วนของโค้ดที่ใช้ระบุหน้าที่ไม่ต้องการให้ CSP-ANTS&STP ทำงานด้วย เนื่องจากการกำหนด CSP บ้างครั้งอาจทำให้เว็บไม่สามารถทำงานได้อย่างที่ต้องการ ต้องปรับลดความปลอดภัยลงให้เหลือ upgrade-insecure-requests แทนโค้ดดังกล่าวคือ
if (is_page(['cd-key'])){
header("Content-Security-Policy: upgrade-insecure-requests");
return;
}
- แล้วเลื่อนลงมาในส่วนของ Base options เลือกเป็น Run everywhere

- กด Save
- และมาตรวจสอบในหน้า Woody snippets ว่าเปิดใช้งานดังภาพแล้วหรือยัง

- ทดสอบด้วยการไปเช็คด้วย https://securityheaders.com/ ก็จะได้ A+ เย่..

- แถม https://developer.mozilla.org/en-US/observatory/ อีกเว็บนึง เมื่อติดตั้งโค้ดของ CSP ก็สามารถทำคะแนนที่ดีขึ้นทันตาเห็น

- สุดท้ายก็สามารถ ถอนปลักอิน CSP-ANTS&STP ออกจากเว็บไซต์ได้เลย ต้องขอบคุณคนเขียนปลักอินตัวนี้จากใจจริง
- จบ.
- ขอให้สนุก..