ป้องกันคนกลางที่เป็นอันตรายด้วย HTTPS และ HTTP Strict Transport Security

เมื่อพิจารณาจากปริมาณข้อมูลส่วนตัวที่ไหลผ่านเครือข่ายอินเทอร์เน็ตอันกว้างใหญ่ การเข้ารหัสจึงไม่ใช่สิ่งที่เราจะมองข้ามได้ เบราว์เซอร์ที่ทันสมัยมีกลไกหลายอย่างที่คุณใช้เพื่อรักษาความปลอดภัยของข้อมูลผู้ใช้ขณะส่งได้ โดยคุกกี้ที่ปลอดภัยและ Strict Transport Security เป็น 2 กลไกที่สำคัญที่สุด ซึ่งช่วยให้คุณปกป้องผู้ใช้ได้อย่างราบรื่น อัปเกรดการเชื่อมต่อเป็น HTTPS และรับประกันว่าจะไม่มีการส่งข้อมูลผู้ใช้ในรูปแบบข้อความธรรมดา

สาเหตุที่ไม่ควรพลาดผลิตภัณฑ์นี้ ลองพิจารณาตัวอย่างต่อไปนี้

การแสดงหน้าเว็บผ่านการเชื่อมต่อ HTTP ที่ไม่ได้เข้ารหัสก็เหมือนกับการยื่นซองจดหมายที่ไม่ได้ปิดผนึกให้คนแรกที่คุณเห็นบนท้องถนนซึ่งดูเหมือนว่ากำลังเดินไปทางที่ทำการไปรษณีย์ หากโชคดี เธออาจนำจดหมายไปส่งให้ถึงที่ด้วยตัวเอง หรืออาจส่งต่อให้คนถัดไปที่เธอเห็นว่ากำลังมุ่งหน้าไปในทิศทางที่ถูกต้อง บุคคลนั้นอาจทำแบบเดียวกัน และเป็นเช่นนี้ต่อไปเรื่อยๆ

คนแปลกหน้าส่วนใหญ่ในเครือข่ายที่เกิดขึ้นเองนี้เชื่อถือได้ และจะไม่แอบดูจดหมายที่เปิดอยู่หรือแก้ไขจดหมายนั้น อย่างไรก็ตาม ยิ่งจดหมายเปลี่ยนมือหลายครั้ง จำนวนผู้ที่มีสิทธิ์เข้าถึงจดหมายที่คุณส่งอย่างสมบูรณ์ก็จะยิ่งมากขึ้น ท้ายที่สุดแล้ว มีความเป็นไปได้สูงที่ผู้รับจดหมายของคุณจะได้รับบางสิ่งทางไปรษณีย์ แต่สิ่งนั้นจะเหมือนกับสิ่งที่คุณส่งไปในตอนแรกหรือไม่นั้นก็ยังเป็นคำถามที่ไม่มีคำตอบ คุณน่าจะปิดผนึกซองจดหมายนั้นนะ…

คนกลาง

ไม่ว่าจะดีหรือร้าย อินเทอร์เน็ตส่วนใหญ่ก็ต้องอาศัยความน่าเชื่อถือของคนแปลกหน้า เซิร์ฟเวอร์ไม่ได้เชื่อมต่อกันโดยตรง แต่จะส่งคำขอและการตอบกลับจากเราเตอร์หนึ่งไปยังอีกเราเตอร์หนึ่งในเกมโทรศัพท์ขนาดใหญ่

คุณสามารถดูฮ็อปเหล่านี้ได้โดยใช้ Traceroute เส้นทางจากคอมพิวเตอร์ของฉันไปยัง HTML5Rocks จะมีลักษณะดังนี้

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 ฮอปก็ไม่แย่เท่าไหร่ อย่างไรก็ตาม หากฉันส่งคำขอผ่าน HTTP เราเตอร์ระดับกลางแต่ละตัวจะมีสิทธิ์เข้าถึงคำขอของฉันและการตอบกลับของเซิร์ฟเวอร์อย่างสมบูรณ์ ข้อมูลทั้งหมดจะถูกโอนเป็นข้อความธรรมดาที่ไม่ได้เข้ารหัส และตัวกลางเหล่านั้นอาจทำหน้าที่เป็นบุคคลที่สามที่อ่านข้อมูลของฉัน หรือแม้แต่จัดการข้อมูลระหว่างการส่ง

ที่แย่ไปกว่านั้นคือการดักจับข้อมูลประเภทนี้แทบจะตรวจจับไม่ได้เลย การตอบกลับ HTTP ที่มีการแก้ไขโดยมีเจตนาร้ายจะมีลักษณะเหมือนกับการตอบกลับที่ถูกต้องทุกประการ เนื่องจากไม่มีกลไกที่ช่วยให้คุณมั่นใจได้ว่าข้อมูลที่ได้รับคือข้อมูลที่ส่งมา_จริงๆ_ หากมีคนตัดสินใจทำให้ชีวิตออนไลน์ของฉันวุ่นวายเพื่อความสนุก ฉันก็คงจะโชคร้ายไม่มากก็น้อย

นี่เป็นสายที่ปลอดภัยไหม

การเปลี่ยนจาก HTTP แบบข้อความธรรมดาไปเป็นการเชื่อมต่อ HTTPS ที่ปลอดภัยจะช่วยป้องกันคนกลางได้ดีที่สุด การเชื่อมต่อ HTTPS จะเข้ารหัสทั้งช่องทางแบบต้นทางถึงปลายทางก่อนที่จะส่งข้อมูล ทำให้เครื่องที่อยู่ระหว่างคุณกับปลายทางไม่สามารถอ่านหรือแก้ไขข้อมูลที่อยู่ระหว่างการส่งได้

แถบอเนกประสงค์ของ Chrome จะแสดงรายละเอียดเกี่ยวกับสถานะการเชื่อมต่อค่อนข้างมาก
แถบอเนกประสงค์ของ Chrome ให้รายละเอียดเกี่ยวกับสถานะการเชื่อมต่อค่อนข้างมาก

ความปลอดภัยที่ HTTPS มอบให้นั้นมีรากฐานมาจากแนวคิดเรื่องคีย์การเข้ารหัสลับแบบสาธารณะและแบบส่วนตัว การพูดคุยเกี่ยวกับรายละเอียดเชิงลึกนั้น (โชคดีที่) อยู่นอกเหนือขอบเขตของบทความนี้ แต่หลักการสำคัญนั้นค่อนข้างตรงไปตรงมา นั่นคือข้อมูลที่เข้ารหัสด้วยคีย์สาธารณะที่ระบุจะถอดรหัสได้ด้วยคีย์ส่วนตัวที่ตรงกันเท่านั้น เมื่อเบราว์เซอร์เริ่มแฮนด์เชค HTTPS เพื่อสร้างช่องทางที่ปลอดภัย เซิร์ฟเวอร์จะให้ใบรับรองซึ่งให้ข้อมูลทั้งหมดที่จำเป็นแก่เบราว์เซอร์เพื่อยืนยันตัวตนโดยการตรวจสอบว่าเซิร์ฟเวอร์มีคีย์ส่วนตัวที่เหมาะสม การสื่อสารทั้งหมดนับจากจุดนั้นเป็นต้นไปจะได้รับการเข้ารหัสในลักษณะที่พิสูจน์ได้ว่าคำขอได้รับการส่งไปยังและได้รับการตอบกลับจากเซิร์ฟเวอร์การตรวจสอบสิทธิ์

ดังนั้น HTTPS จึงช่วยให้คุณมั่นใจได้ว่าคุณกำลังสื่อสารกับเซิร์ฟเวอร์ที่คุณคิดว่ากำลังสื่อสารอยู่ และไม่มีใครแอบฟังหรือดัดแปลงข้อมูลระหว่างทาง การเข้ารหัสประเภทนี้เป็นข้อกำหนดเบื้องต้นที่สำคัญอย่างยิ่งสำหรับการรักษาความปลอดภัยบนเว็บ หากแอปพลิเคชันของคุณไม่ได้แสดงผลผ่าน HTTPS ในปัจจุบัน ก็อาจเสี่ยงต่อการถูกโจมตี แก้ไข Ars Technica มีคู่มือการขอรับและติดตั้งใบรับรอง (ฟรี) ที่ยอดเยี่ยม ซึ่งเราขอแนะนำให้คุณดูรายละเอียดทางเทคนิค การกำหนดค่าจะแตกต่างกันไปตามผู้ให้บริการและเซิร์ฟเวอร์ แต่กระบวนการขอใบรับรองจะเหมือนกันทุกที่

มีความปลอดภัยโดยค่าเริ่มต้น

เมื่อขอและติดตั้งใบรับรองแล้ว ให้ตรวจสอบว่าผู้ใช้ได้รับประโยชน์จากความพยายามของคุณ โดยย้ายข้อมูลผู้ใช้ที่มีอยู่ไปยังการเชื่อมต่อ HTTPS อย่างโปร่งใสผ่านการเปลี่ยนเส้นทาง HTTP และตรวจสอบว่ามีการส่งคุกกี้ผ่านการเชื่อมต่อที่ปลอดภัยเท่านั้น

เชิญทางนี้

เมื่อผู้ใช้เข้าชม http://example.com/ ให้เปลี่ยนเส้นทางไปยัง https://example.com/ โดยส่งการตอบกลับ 301 Moved Permanently พร้อมส่วนหัว Location ที่เหมาะสม ดังนี้

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

คุณตั้งค่าการเปลี่ยนเส้นทางประเภทนี้ได้ง่ายๆ ในเซิร์ฟเวอร์ เช่น Apache หรือ Nginx ตัวอย่างเช่น การกำหนดค่า Nginx ที่เปลี่ยนเส้นทางจาก http://example.com/ ไปยัง https://example.com/ จะมีลักษณะดังนี้

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

คุกกี้ช่วยให้เรามอบประสบการณ์การเข้าสู่ระบบที่ราบรื่นแก่ผู้ใช้ผ่านโปรโตคอล HTTP แบบไม่เก็บสถานะได้ ข้อมูลที่จัดเก็บไว้ในคุกกี้ รวมถึงข้อมูลที่ละเอียดอ่อน เช่น รหัสเซสชัน จะถูกส่งไปพร้อมกับคำขอทุกรายการ เพื่อให้เซิร์ฟเวอร์เข้าใจว่ากำลังตอบสนองต่อผู้ใช้รายใดอยู่ในขณะนั้น เมื่อเรามั่นใจว่าผู้ใช้เข้าถึงเว็บไซต์ของเราผ่าน HTTPS แล้ว เราควรตรวจสอบด้วยว่าข้อมูลที่ละเอียดอ่อนซึ่งจัดเก็บไว้ในคุกกี้จะได้รับการโอนผ่านการเชื่อมต่อที่ปลอดภัยเท่านั้น และจะไม่ส่งในรูปแบบข้อความธรรมดา

โดยทั่วไปแล้ว การตั้งค่าคุกกี้จะเกี่ยวข้องกับส่วนหัว HTTP ที่มีลักษณะดังนี้

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

คุณสามารถสั่งให้เบราว์เซอร์จำกัดการใช้คุกกี้เพื่อรักษาความปลอดภัยของเซสชันได้โดยการเพิ่มคีย์เวิร์ดเดียว ดังนี้

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

ระบบจะไม่ส่งคุกกี้ที่ตั้งค่าด้วยคีย์เวิร์ด secure ผ่าน HTTP โดยเด็ดขาด

กำลังปิดหน้าต่างที่เปิดอยู่

การเปลี่ยนเส้นทางไปยัง HTTPS อย่างโปร่งใสหมายความว่าผู้ใช้จะใช้การเชื่อมต่อที่ปลอดภัยเกือบตลอดเวลาที่อยู่ในเว็บไซต์ของคุณ อย่างไรก็ตาม การดำเนินการนี้ยังคงเปิดโอกาสให้เกิดการโจมตีได้เล็กน้อย กล่าวคือ การเชื่อมต่อ HTTP เริ่มต้นจะเปิดกว้างและเสี่ยงต่อการโจมตีแบบ SSL Stripping และการโจมตีที่เกี่ยวข้อง เนื่องจากผู้ที่แทรกกลางการสื่อสารมีสิทธิ์เข้าถึงคำขอ HTTP เริ่มต้นอย่างสมบูรณ์ จึงสามารถทำหน้าที่เป็นพร็อกซีระหว่างคุณกับเซิร์ฟเวอร์ได้ โดยจะทำให้คุณอยู่ในการเชื่อมต่อ HTTP ที่ไม่ปลอดภัยไม่ว่าเซิร์ฟเวอร์จะตั้งใจหรือไม่ก็ตาม

คุณสามารถลดความเสี่ยงของการโจมตีประเภทนี้ได้โดยขอให้เบราว์เซอร์บังคับใช้ HTTP Strict Transport Security (HSTS) การส่งส่วนหัว HTTP Strict-Transport-Security จะสั่งให้เบราว์เซอร์เปลี่ยนเส้นทาง HTTP ไปยัง HTTPS ฝั่งไคลเอ็นต์ โดยไม่ต้องแตะเครือข่าย (ซึ่งยังส่งผลดีต่อประสิทธิภาพด้วย คำขอที่ดีที่สุดคือคำขอที่คุณไม่ต้องสร้าง)

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

เบราว์เซอร์ที่รองรับส่วนหัวนี้ (ปัจจุบันคือ Firefox, Chrome และ Opera: caniuse มีรายละเอียด) จะจดบันทึกว่าเว็บไซต์นี้ขอสิทธิ์เข้าถึงเฉพาะ HTTPS ซึ่งหมายความว่าไม่ว่าผู้ใช้จะเข้าถึงเว็บไซต์ด้วยวิธีใดก็ตาม ผู้ใช้จะเข้าชมผ่าน HTTPS แม้ว่าเธอจะพิมพ์ http://example.com/ ลงในเบราว์เซอร์ แต่สุดท้ายเธอก็จะเข้าถึง HTTPS โดยไม่ต้องทำการเชื่อมต่อ HTTP เลย ยิ่งไปกว่านั้น หากเบราว์เซอร์ตรวจพบใบรับรองที่ไม่ถูกต้อง (ซึ่งอาจพยายามปลอมแปลงข้อมูลประจำตัวของเซิร์ฟเวอร์) ผู้ใช้จะไม่ได้รับอนุญาตให้ดำเนินการต่อผ่าน HTTP ซึ่งเป็นเรื่องที่ดีมาก

เบราว์เซอร์จะทำให้สถานะ HSTS ของเซิร์ฟเวอร์หมดอายุหลังจากผ่านไป max-age วินาที (ประมาณ 1 เดือนในตัวอย่างนี้) ให้ตั้งค่านี้เป็นค่าที่สูงพอสมควร

นอกจากนี้ คุณยังตรวจสอบได้ว่าโดเมนย่อยทั้งหมดของต้นทางได้รับการปกป้องโดยการเพิ่มคำสั่ง includeSubDomains ลงในส่วนหัว ดังนี้

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

ก้าวไปข้างหน้าอย่างปลอดภัย

HTTPS เป็นวิธีเดียวที่จะช่วยให้มั่นใจได้ว่าข้อมูลที่คุณส่งจะไปถึงผู้รับที่ต้องการอย่างครบถ้วน คุณควรตั้งค่าการเชื่อมต่อที่ปลอดภัยสำหรับเว็บไซต์และแอปพลิเคชันตั้งแต่วันนี้ ซึ่งเป็นกระบวนการที่ค่อนข้างตรงไปตรงมา และจะช่วยรักษาความปลอดภัยของข้อมูลลูกค้า เมื่อมีช่องทางที่เข้ารหัสแล้ว คุณควรเปลี่ยนเส้นทางผู้ใช้ไปยังการเชื่อมต่อที่ปลอดภัยนี้อย่างโปร่งใส ไม่ว่าผู้ใช้จะเข้าถึงเว็บไซต์ของคุณด้วยวิธีใดก็ตาม โดยการส่งการตอบกลับ HTTP 301 จากนั้นตรวจสอบว่าข้อมูลเซสชันที่ละเอียดอ่อนทั้งหมดของผู้ใช้ใช้การเชื่อมต่อที่ปลอดภัยเท่านั้น โดยเพิ่มคีย์เวิร์ด secure เมื่อตั้งค่าคุกกี้ เมื่อทำทั้งหมดนี้แล้ว ให้ตรวจสอบว่าผู้ใช้จะไม่พลาดการอัปเดตโดยไม่ตั้งใจ โดยปกป้องผู้ใช้ด้วยการตรวจสอบว่าเบราว์เซอร์ของผู้ใช้ดำเนินการอย่างถูกต้องด้วยการส่งส่วนหัว Strict-Transport-Security

การตั้งค่า HTTPS ไม่ยุ่งยาก และมีประโยชน์อย่างมากต่อเว็บไซต์และผู้ใช้ ซึ่งคุ้มค่ากับความพยายามอย่างแน่นอน

แหล่งข้อมูล

  • StartSSL มีใบรับรองที่ยืนยันโดเมนแล้วให้ใช้ฟรี ไม่มีอะไรดีไปกว่าของฟรี แน่นอนว่าการก้าวไปสู่การยืนยันระดับที่สูงขึ้นนั้นเป็นไปได้และมีราคาที่สมเหตุสมผล
  • การทดสอบเซิร์ฟเวอร์ SSL: เมื่อตั้งค่า HTTPS สำหรับเซิร์ฟเวอร์แล้ว ให้ตรวจสอบว่าคุณได้ดำเนินการอย่างถูกต้องโดยเรียกใช้ผ่านการทดสอบเซิร์ฟเวอร์ของ SSL Labs คุณจะได้รับรายงานที่ละเอียดและเข้าใจง่ายซึ่งจะแสดงให้เห็นว่าคุณพร้อมใช้งานจริงหรือไม่
  • บทความล่าสุดของ Ars Technica เรื่อง "การรักษาความปลอดภัยเว็บเซิร์ฟเวอร์ด้วย SSL/TLS" เป็นบทความที่น่าอ่านเพื่อทำความเข้าใจรายละเอียดเบื้องหลังเกี่ยวกับกลไกการตั้งค่าเซิร์ฟเวอร์
  • ข้อกำหนดเฉพาะของ HTTP Strict Transport Security (RFC6797) เป็นข้อมูลทางเทคนิคทั้งหมดเกี่ยวกับส่วนหัว Strict-Transport-Security ที่คุณอาจต้องการทราบ
  • เมื่อคุณทราบแน่ชัดแล้วว่ากำลังทำอะไรอยู่ ขั้นตอนถัดไปที่เป็นไปได้คือการโฆษณาว่าเว็บไซต์ของคุณควรเข้าถึงได้ผ่านชุดใบรับรองที่เฉพาะเจาะจงเท่านั้น IETF กำลังดำเนินการบางอย่างที่จะช่วยให้คุณทำเช่นนั้นได้ผ่านส่วนหัว Public-Key-Pins ซึ่งยังอยู่ในช่วงเริ่มต้น แต่น่าสนใจและน่าติดตาม