Tag: woody snippets

  • WordPress Content Security Policy

    WordPress Content Security Policy

    1. CSP สำหรับ WordPress ค่อนข้างยุ่งยาก ปรับโน่นนิดปิดนี่หน่อย เว็บเพี้ยน
    2. เมื่อลองค้นไป ก็เจอปลักอินอยู่ตัวนึง ที่ช่วยสร้าง CSP ให้อัตโนมัติ นั่นคือ CSP-ANTS&STP แต่เนื่องจากปลักอินตัวนี้ไม่ได้รับการปรับปรุงมาตั้งแต่ 2022 ซึ่งนานเกินไป แล้ว แต่จริงๆ มันยังใช้ได้อยู่
    3. แต่ปลั๊กอินก็ยังมีบักเมื่อไปตรวจกับเว็บ https://securityheaders.com แล้วจะมีข้อความเตือนดังภาพ
    1. เพื่อแก้ปัญหานี้เลยต้องเขียนปลักอินตัวนี้ลงในปลักอินอีกตัวที่ชื่อ Woody snippets
    2. คลิก Add ใน Woody snippets เพิ่มข้อความต่อไปนี้ ส่วนนี้ได้แก้ไข Error บน https://securityheaders.com แล้วด้วย
    /**
    * 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;
    
    }
    });
    1. และใน code นี้มีส่วนของโค้ดที่ใช้ระบุหน้าที่ไม่ต้องการให้ CSP-ANTS&STP ทำงานด้วย เนื่องจากการกำหนด CSP บ้างครั้งอาจทำให้เว็บไม่สามารถทำงานได้อย่างที่ต้องการ ต้องปรับลดความปลอดภัยลงให้เหลือ upgrade-insecure-requests แทนโค้ดดังกล่าวคือ
    if (is_page(['cd-key'])){
        header("Content-Security-Policy: upgrade-insecure-requests");
        return;
    } 
    
    1. แล้วเลื่อนลงมาในส่วนของ Base options เลือกเป็น Run everywhere
    1. กด Save
    2. และมาตรวจสอบในหน้า Woody snippets ว่าเปิดใช้งานดังภาพแล้วหรือยัง
    1. ทดสอบด้วยการไปเช็คด้วย https://securityheaders.com/ ก็จะได้ A+ เย่..
    1. แถม https://developer.mozilla.org/en-US/observatory/ อีกเว็บนึง เมื่อติดตั้งโค้ดของ CSP ก็สามารถทำคะแนนที่ดีขึ้นทันตาเห็น
    1. สุดท้ายก็สามารถ ถอนปลักอิน CSP-ANTS&STP ออกจากเว็บไซต์ได้เลย ต้องขอบคุณคนเขียนปลักอินตัวนี้จากใจจริง
    2. จบ.
    3. ขอให้สนุก..