มาในวันนี้เราจะมาพูดถึงเรื่อง HTTP Security Header ที่มีอยู่หลากหลายและมีประโยชน์มากมายมาดูกันว่ามีอะไรบ้างครับ
1. X-XSS-Protection
X-XSS-Protection ใช้ในการ filter XSS ต่างๆที่ถูกใส่ไว้ในเว็บเพจที่ได้รับ โดย X-XSS-Protection มี 2 mode คือ
- 0 คือ disable
- 1 คือ enable โดย Browser จะเป็นตัวกรองการแสดงผลของเพจที่ได้รับ
- 1 คือการ filter XSS ออก แต่ยัง render page ปกติ
- 1; mode=block คือการ filter XSS เมื่อพบแล้วจะทำการหยุดการ render page
- 1; report=http://target.com/url คือการ filter XSS แล้วจะทำการแจ้งเตือนไปยัง page ที่เรากำหนด
หากต้องการใส่ X-XSS-Protection ใน Nginx ให้เขียนในส่วน configuration เป็น
1 |
add_header X-XSS-Protection "1;mode=block"; |
จากนั้น restart nginx
code ตัวอย่างที่รับ parameter ผ่านตัวแปล payload นำไปแสดงผล
<?php echo “XSS Page: “; echo $_GET[‘payload’]; ?>
จากภาพด้านล่างจะเห็นว่าการแสดงผลของ console ในบรรทัดแรก จะพบว่าสามารถรับ payload=<script>alert(1)</script> ไปแสดงผลได้ปกติ แต่เมื่อ enable X-XSS-Protection จะทำให้ไม่สามารถแสดงผลได้
โดย Browser ที่รองรับการทำงานของ X-XSS-Protection Header จะมี
- Microsoft Edge
- Google Chrome
- Opera
- Safari
- Microsoft Internet Explorer 8.0 เป็นต้นมา
2. X-Frame-Option
X-Frame-Option เอาไว้กันการนำ page ไป render อยู่ภายใต้ iframe ซึ่งทำให้การโจมตีอย่าง Clickjacking ไม่เวิร์คด้วย
ยกตัวอย่างการ Clickjacking คือการนำ page ไปใส่ไว้ใน iframe แล้วทำเป็นโปร่งใสแปะไว้ในเพจของการใช้งานปกติ เมื่อมีการ click หรือใช้งานใดๆในเพจที่ถูกซ้อน ก็จะกลายเป็นการกระทำของการเพจที่ซ้อนนั้นแทน
ยกตัวอย่างเพจที่จะเอามาซ้อน
1 2 3 |
<?php echo "<input type='button' onclick=javascript:alert(1); value='hit me'>"; ?> |
เพจที่ถูกซ้อน
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<html> <head> <title>Clickjack test page</title> </head> <style> iframe { /* iframe from facebook.com */ width:300px; height:100px; position:absolute; top:30; left:0; filter:alpha(opacity=50); /* in real life opacity=0 */ opacity:0.5; } </style> <body> <p>Website is vulnerable to clickjacking!</p> <p>hit me</p> <iframe src="http://10.211.55.17:8000/click.php" width="120" height="30"></iframe> </body> </html> |
หากไม่มีการใช้ X-Frame-Option จะออกมาเป็น
ที่เห็นปุ่มอยู่เพราะ opacity ไม่เท่ากับ 0 นั่นเอง
X-Frame-Options สามารกำหนดได้เป็น
- deny คือไม่ยินยอมให้เว็บไซด์ใดๆนำเพจไปใส่ใน iframe
- SAMEORIGIN กำหนดให้สามารถนำเพจไป render ใน iframe ได้ หากเป็น origin เดียวกัน
- ALLOW-FROM กำหนดไปเป็น URL ใดๆที่อนุญาตให้เราอนุญาตให้นำเพจไปเป็น iframe ได้
ทีนี้หากเรากำหนด X-Frame-Options deny จะได้ผลเป็น
1 |
add_header X-Frame-Options "deny"; |
จะพบว่าไม่สามารถ render page ได้ เนื่องจากการไม่อนุญาตให้นำเพจไปไว้อยู่ใน iframe นั่นเอง
*** เพิ่มเติมในส่วน same origin คือเว็บไซด์ที่ต้องเป็น protocol, host และ port อันเดียวกัน
โดย Browser ที่รองรับการทำงานของ X-Frame-Options Header จะมี
- Microsoft Edge
- Google Chrome (ไม่ support allow-from value)
- Firefox
- Opera (ไม่ support allow-from value)
- Safari
- Microsoft Internet Explorer 8.0 เป็นต้นมา
3. X-Content-Type-Options
เป็นการกำหนดไปเลยว่า content ที่จะให้แสดงผลเป็นข้อมูลประเภทไหน เพื่อไม่ให้ปัญหาของการคิดไปเองของ Browser เช่น
ใน HTTP Response มีการกำหนด Content-Type: text/html แม้จะเป็นไฟล์แบบ gif , Browser ก็จะแสดงผลเป็น gif โดยไม่สนใจ Content-Type ที่มีการกำหนดไว้เลย โดยปัญหานี้เรียกว่า “MIME Sniffing”
โดย X-Content-Type-Options จะมาบังคับให้ Browser ไม่คิดไปเอง ให้ทำการ render page ตามที่เรากำหนดเท่านั้นแทน
หากเราต้องการกำหนดใน Nginx จะใช้เป็น
1 |
add_header X-Content-Type-Options nosniff; |
โดย Browser ที่รองรับการทำงานของ X-Content-Type-Options Header จะมี
- Microsoft Edge
- Google Chrome
- Firefox
- Opera
- Microsoft Internet Explorer 8.0 เป็นต้นมา
4. Content Security Policy
Header ตัวนี้เป็นตัวกำหนดการนำ content ใดๆที่จะมาแสดงผลในเว็บเพจของเรา ซึ่งทำให้เราสามารถลดผลกระทบของการโจมตีแบบ XSS ได้อย่างดี
หากเราต้องการกำหนดใน Nginx จะใช้เป็น
1 |
add_header Content-Security-Policy "<policy>"; |
โดย Policy ที่ว่าจะเป็นการกำหนด source ต่างๆที่จะนำมาแสดงผลไม่ว่าจะเป็น ภาพ, script, frame และอื่นๆ เช่น
1 2 3 4 5 6 7 8 |
default-src 'self' - เป็นการอนุญาตให้สามารถนำ content ใดๆมาแสดงผลได้หากเป็น origin เดียวกัน script-src 'self' www.google-analytics.com ajax.googleapis.com - เป็นการอนุญาตให้สามารถนำ content ใดๆมาแสดงผลได้หากเป็น origin เดียวกัน, www.google-analytics.com, ajax.googleapis.com default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; อนุญาตให้นำภาพ, scripts, AJAX, และ CSS มาจาก origin เดียวกัน, หากนอกเหนือจากนั้นจะไม่อนุญาตให้โหลดมาใช้ frame-ancestors 'none' จะมีค่าเท่ากับ X-Frame-Options: deny นั่นหมายความว่าไม่ยอมให้นำไปใช้เป็น iframe ได้นั่นเอง frame-ancestors 'self' จะมีค่าเท่ากับ X-Frame-Options: sameorigin นั่นหมายความว่ายอมให้นำไปใช้เป็น iframe ได้เฉพาะ origin เดียวกันนั่นเอง frame-ancestors localhost:4321 จะมีค่าเท่ากับ X-Frame-Options: allow-from http://localhost:4321 นั่นหมายความว่ายอมให้นำไปใช้เป็น iframe ได้เฉพาะ localhost:4321 เท่านั้น script-src 'self' โดยไม่มี 'unsafe-inline' มีค่าเท่ากับ X-XSS-Protection: 1 |
เช่น
1 |
add_header Content-Security-Policy "default-src 'none'"; |
จากตัวอย่างตอนแรกที่เราใช้ใน (X-XSS-Protection) header จะพบว่าไม่สามารถใช้งาน payload=<script>alert(1)</script> ได้ เนื่องจาก set default-src เป็น none นั่นหมายความว่าไม่ยอมให้ object ใดๆที่จะมาแสดงผลได้นั่นเอง
ทีนี้หากเปลี่ยนใหม่เป็น อนุญาตให้ใช้ script แบบ inline ได้
1 |
add_header Content-Security-Policy "default-src 'unsafe-inline'"; |
และ
1 |
add_header X-XSS-Protection "0"; |
จะพบว่า script กลับมาใช้งานได้ดังเดิม
หากกำหนด policy กลายเป็น allow เฉพาะ same origin ก็จะพบว่าไม่สามารถทำงานได้
1 |
add_header Content-Security-Policy "default-src 'self'"; |
5. Strict Transport Security (HSTS)
เป็น Header ที่จะเป็นการบอกกับ Browser ว่าจะให้เข้าใช้งานเฉพาะ HTTPS เท่านั้น ยกตัวอย่างเช่นการทดสอบเข้าใช้งาน http://www.facebook.com ซึ่งก็จะเห็นว่ามีการ redirect Browser ไปยัง HTTPS scheme
เมื่อเราเข้าไปที่ HTTPS เราจะพบว่ามีการส่ง Header HSTS มาให้
ซึ่งในนั้นจะเป็นการกำหนดการให้บริการของ HTTPS โดย HSTS สามารถกำหนดได้ดังนี้
1 2 3 |
Strict-Transport-Security: max-age=<expire-time> Strict-Transport-Security: max-age=<expire-time>; includeSubDomains Strict-Transport-Security: max-age=<expire-time>; preload |
โดย
- expire-time เป็นการบอกกับ browser ว่าเว็บไซด์นี้จะเข้าได้เฉพาะ https ไปอีกนานเท่าไหร่ หน่วยเป็นวินาที
- includeSubDomains เป็นการบอกว่า HSTS ครอบคลุมถึง sub domain ด้วย
- preload เป็นการกำหนด HSTS มาตั้งแต่ใน Browser โดย user ไม่จำเป็นต้องเข้าเว็บไซด์นั้นๆมาก่อน
หากเราต้องการ set ใน Nginx จะใช้เป็น
1 |
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; "; |
โดย Browser ที่รองรับการทำงานของ HSTS Header จะมี
- Microsoft Edge
- Google Chrome
- Firefox
- Opera
- Microsoft Internet Explorer 11.0 เป็นต้นมา
- Safari
6. Public-Key-Pins (HPKP)
HPKP เป็นการ pin Certificate หรือก็คือการกำหนดไปเลยว่าเวลาเข้าใช้งานเว็บไซด์โดยใช้ certificate ใดๆ เมื่อ browser เจอ HPKP เป็นครั้งแรก จะทำการจำ certificate นั้นๆไว้อีกทั้งจะจำวันหมดอายุของ certificate ไว้ด้วย
โดยหากเราต้องการ set ใน Nginx จะใช้เป็น
1 |
Public-Key-Pins: pin-sha256=<base64==>; max-age=<expireTime>; |
HPKP มี option ได้เป็น
- expire-time เป็นการบอกกับ browser ว่าเว็บไซด์นี้จะเข้าได้เฉพาะ https ไปอีกนานเท่าไหร่ หน่วยเป็นวินาที
- includeSubDomains เป็นการบอกว่า HSTS ครอบคลุมถึง sub domain ด้วย
- report-uri=<URI> หากมีการตรวจสอบ certificate แล้วผิดพลาดให้แจ้งไปยัง URI ใดๆ อย่างของ Facebook ก็จะมีการ report ไปยัง http://reports.fb.com/hpkp/
โดย Browser ที่รองรับการทำงานของ HPKP Header จะมี
- Google Chrome
- Firefox
- Opera
7. Cookie Options
จริงๆแล้วมันคือ header Set-Cookie ที่มีมานานแล้วนั่นเอง โดยการ set Cookie ให้มีความ secure มากขึ้นเราสามารถ set option เพิ่มเติมได้ดังนี้
- secure เป็นการกำหนดให้ใช้งาน Cookie ผ่าน HTTPS เท่านั้น
- HttpOnly เป็นการกำหนดให้ Cookie ไม่สามารถเข้าถึงได้ผ่าน Javascript
- SameSite เป็นการกำหนดให้ไม่มีการส่ง Cookie ไปยัง Site อื่นๆ นอกเหนือจาก Site ของตัวเองเท่านั้น
- Expires เป็นการกำหนดว่าให้ Cookie นั้นหมดอายุเมื่อไหร่
- Domain เป็นการกำหนด domain ที่เราจะสามารถใช้ Cookie นี้ได้ โดยหากเรากำหนดเป็น domain=example.com จะรวมถึง sub.domain.com ด้วย
- Path เป็นการกำหนด path ของการใช้งาน Cookie
จริงๆแล้วมันยังมีอีกหลาย HTTP Header ที่น่าใช้งานได้นะครับ เอาไว้วันหลังจะมาเพิ่มเติมอีกทีครับ
Reference::
- https://en.wikipedia.org/wiki/Same-origin_policy
- https://peteris.rocks/blog/exotic-http-headers/
- https://blog.appcanary.com/2017/http-security-headers.html
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers