Tag: Subresource Integrity

  • Subresource Integrity

    Subresource Integrity

    เมื่อต้องการเพิ่มคะแนนของ HTTP Observatory Report เลื่อนไปๆ จะเจอว่าคะแนนของ Subresource integrity (SRI) ยังเป็น -5 ทำไงได้บ้างสำหรับ WordPress


    SRI คืออะไร

    SRI หรือ Subresource Integrity คือฟีเจอร์ด้านความปลอดภัยที่ช่วยให้ Browser ตรวจสอบว่าไฟล์ที่ถูกดึงมาจากภายนอก (เช่น JS หรือ CSS จาก CDN) ไม่ถูกแก้ไขหรือแอบฝังมัลแวร์มาโดยผู้ไม่หวังดี

    สิ่งที่ต้องมี

    1. ปลักอิน Woody snippets
    2. code สร้าง SRI ซึ่ง code นี้ได้จาก ai 2 ตัวช่วยกันคิด (กรั่ก ๆ) คือ z.ai และ gemini.google.com
    PHP
    // 1. Hook เพื่อแทรก SRI ให้ Script และ Style
    add_filter( 'script_loader_tag', 'auto_add_sri', 10, 2 );
    add_filter( 'style_loader_tag', 'auto_add_sri', 10, 2 );
    
    function auto_add_sri( $tag, $handle ) {
        if ( ! preg_match( '/\s(src|href)=[\x27\x22]([^\x27\x22]+)[\x27\x22]/i', $tag, $matches ) ) {
            return $tag;
        }
        
        $attr = $matches[1]; 
        $url  = $matches[2];
    
        $site_url = site_url();
        if ( strpos( $url, 'http' ) !== 0 || strpos( $url, $site_url ) === 0 ) {
            return $tag;
        }
    
        $hash_key = 'sri_hash_' . md5( $url );
        $hash = get_transient( $hash_key );
    
        if ( false === $hash ) {
            $response = wp_remote_get( $url, array( 'timeout' => 5 ) ); 
            
            if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) {
                set_transient( $hash_key, 'failed', HOUR_IN_SECONDS );
                return $tag;
            }
    
            $content = wp_remote_retrieve_body( $response );
            $hash = 'sha384-' . base64_encode( hash( 'sha384', $content, true ) );
            
            set_transient( $hash_key, $hash, 12 * HOUR_IN_SECONDS );
        }
    
        if ( $hash && $hash !== 'failed' ) {
            $replace_target = ' ' . $attr . '=';
            $replace_with = ' integrity="' . $hash . '" crossorigin="anonymous" ' . $attr . '=';
            return str_replace( $replace_target, $replace_with, $tag );
        }
    
        return $tag;
    }
    1. เปิดใช้งาน code ให้เป็น run everywhere
    2. ลองไปทดสอบที่เว็บ https://developer.mozilla.org/en-US/observatory
    3. ได้ผลดังภาพ
    1. ยังมีคะแนนที่ต้องมีการปรับตาม recomendation เพิ่มเติม
    2. สคริปต์นี้จะเก็บ cache ของ integrity ของสคริปต์ภายนอกไว้ 12 ชั่วโมง ถ้ามีผู้ใช้เข้าเว็บในช่วงเวลานี้แล้ว สคริปต์ไม่มีการเปลี่ยนแปลงก็จะไม่มีปัญหา แต่ถ้ามีการเปลี่ยนแปลงแล้วค่า Hash ไม่ตรงก็จะโดนบล็อคทันที ซึ่งต้องดูว่าเวลาเท่าไหร่จึงจะเหมาะสม
    3. จบ…ข้อให้สนุก