ข้อผิดพลาดในตัวแก้ไข Substack ที่เกิดจากการเขียนไฟล์ "/etc/hosts"
(scalewithlee.substack.com)- ในตัวแก้ไขของ Substack จะเกิด ข้อผิดพลาดเครือข่าย เมื่อป้อนพาธระบบบางรายการ
- Web Application Firewall (WAF) บล็อกพาธเหล่านี้เพื่อป้องกัน การโจมตีแบบ path traversal และ การโจมตีแบบ command injection
- ประเด็นเรื่องการหาสมดุลระหว่าง ความปลอดภัย และ การใช้งาน จึงเด่นชัดขึ้น
- จำเป็นต้องมีทางออกที่ดีกว่าสำหรับ นักเขียนสายเทคนิค
- สามารถแก้ปัญหาได้ด้วยการใช้ พาธทางเลือก
เมื่อ /etc/h*sts รบกวนตัวแก้ไข Substack: การผจญภัยของการกรองเนื้อหาบนเว็บ
ข้อผิดพลาดเครือข่ายอันน่าพิศวง
- ระหว่างเขียนโพสต์เชิงเทคนิคเกี่ยวกับการแปลงชื่อ DNS เกิด ข้อผิดพลาดที่ไม่คาดคิด
- เมื่อพิมพ์พาธ
/etc/h*stsจะเกิด ข้อผิดพลาดเครือข่าย และบันทึกอัตโนมัติล้มเหลว - หน้าสถานะของ Substack แสดงว่า ระบบทำงานปกติ
เริ่มต้นการสืบค้น
- พบว่า ข้อผิดพลาด เกิดขึ้นเมื่อป้อนพาธไฟล์บางรายการ แต่ถ้าดัดแปลงพาธจะ ใช้งานได้ปกติ
- พาธอย่าง
/etc/h*stsทำให้เกิดข้อผิดพลาด แต่พาธที่ดัดแปลงแล้วไม่มีปัญหา
มีอะไรเกิดขึ้นอยู่ภายใน?
- ตรวจพบการตอบกลับ 403 Forbidden ในเครื่องมือนักพัฒนาของเบราว์เซอร์
- มี Cloudflare เข้ามาเกี่ยวข้อง
ทำความเข้าใจตัวกรองความปลอดภัยของเว็บแอปพลิเคชัน
อธิบาย WAF แบบสั้น ๆ
- Web Application Firewall (WAF) ทำหน้าที่เป็น ยามรักษาความปลอดภัย ของเว็บไซต์
- คอย บล็อก คำขอที่น่าสงสัย
การโจมตีแบบ path traversal: ทำไมจึงต้องระวัง
- การโจมตีแบบ path traversal คือความพยายามเข้าถึงไฟล์ระบบที่มีความอ่อนไหว
- พาธอย่าง
/etc/h*stsอาจตกเป็น เป้าหมายของการโจมตี ได้
Command injection: ปัญหาด้านความปลอดภัยอีกแบบหนึ่ง
- การโจมตีแบบ command injection มุ่งให้มีการรันคำสั่งของระบบ
- เมื่อมีการกล่าวถึงพาธระบบ ตัวกรองอาจ บล็อก ได้
ปริศนายิ่งลึกขึ้น: ตัวอย่างในอดีต
- พบกรณีการใช้พาธคล้ายกันในโพสต์ Substack อื่น ๆ
- เป็นไปได้ว่าพฤติกรรมการกรองอาจ เปลี่ยนไป ตั้งแต่ช่วงเวลาหนึ่ง
ความปลอดภัยเทียบกับการใช้งาน: สมดุลที่ละเอียดอ่อน
- ตัวกรองของ Substack มีไว้เพื่อ ปกป้อง แต่กลับกลายเป็น อุปสรรค สำหรับ นักเขียนสายเทคนิค
- ยังมี ช่องว่างให้ปรับปรุง เช่น ข้อความผิดพลาดที่ชัดเจนขึ้น การรับรู้เนื้อหาเชิงเทคนิค และการให้วิธีแก้ที่มีการจัดทำเอกสาร
มองดูการตอบสนอง HTTP
- ยืนยันสถานะ 403 Forbidden ได้ในระดับ API
ทางออกที่ดีกว่าสำหรับแพลตฟอร์มเนื้อหาเชิงเทคนิค
- การกรองตามบริบท: รับรู้พาธระบบใน code block หรือการสนทนาเชิงเทคนิค
- ข้อความผิดพลาดที่ชัดเจน: อธิบายว่าโดนบล็อกจากตัวกรองความปลอดภัย แทนคำว่า "ข้อผิดพลาดเครือข่าย"
- วิธีแก้ที่มีเอกสารรองรับ: แนะนำวิธีพูดถึงพาธที่อ่อนไหว
บทสรุป: จุดตัดกันของความปลอดภัยและงานเขียนเชิงเทคนิค
-
ปัญหาในตัวแก้ไขของ Substack เผยให้เห็นความท้าทายที่ซับซ้อนของ ความปลอดภัย และ การเขียนเชิงเทคนิค
-
สิ่งที่ตัวกรองความปลอดภัยอาจมองว่าเป็นรูปแบบการโจมตี แท้จริงแล้วอาจเป็น เนื้อหาที่ชอบด้วยเหตุผล
-
สามารถแก้ปัญหาได้ด้วยการใช้ พาธทางเลือก
-
ขอให้ผู้อ่านแชร์ประสบการณ์ในคอมเมนต์ หากเคยเจอปัญหาการกรองลักษณะคล้ายกันบนแพลตฟอร์มอื่น
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
คนที่ตั้งค่า กฎ WAF บน CDN มักไม่เข้าใจเว็บไซต์และบริการที่จัดการคอนเทนต์เชิงเทคนิคอย่างถ่องแท้ ไม่ใช่ปัญหาเฉพาะ Cloudflare เท่านั้น Akamai ก็คล้ายกัน
ถ้าเปิดกฎป้องกัน SQL injection พื้นฐานบนเว็บไซต์ที่พูดคุยเรื่องฐานข้อมูล เว็บไซต์ก็พัง และ ruleset สำหรับ file inclusion ก็จะบล็อกสตริงอย่าง
/etc/hosts,/etc/passwdแน่นอนว่ามีประเด็นเรื่องสมดุลระหว่างความปลอดภัยกับการใช้งานอยู่ด้วย เพราะเราไม่รู้ว่าบริการไหนถูกพัฒนาอย่างเปราะบาง การใส่กฎ WAF ทั้งหมดเข้าไปจึงมีด้านที่ทำให้ปลอดภัยขึ้น แต่เมื่อบริการที่พัฒนาอย่างปลอดภัยจำเป็นต้องพูดคุยแนวคิดทางเทคนิค ruleset เดียวกันนี้ก็จะน่ารำคาญมาก
การปรับกฎให้ละเอียดใช้เวลามาก พอแก้ปัญหาที่หน้าไม่ขึ้นเพราะ query parameter มี
/etc/hostsแล้ว ต่อไป XHR resource ก็ไม่ขึ้นเพราะ referer มี/etc/hostsจากนั้นไลบรารี JS สำหรับ analytics ก็ใส่ URL ที่เข้าชมไว้ในคุกกี้จนพังอีก สุดท้ายก็อยากปิดกฎทิ้งไปเลยถ้าบริษัทประกันบอกว่า “ถ้าไม่บังคับให้พนักงานเปลี่ยนรหัสผ่านทุก 90 วัน จะขึ้นเบี้ยประกัน 20%” ต่อให้พูดถูกแค่ไหนว่า NIST เปลี่ยนคำแนะนำไม่ให้เปลี่ยนรหัสผ่านตามรอบมานานกว่าสิบปีแล้ว และนั่นเป็นแนวปฏิบัติที่แย่ เบี้ยประกันก็ยังขึ้นอยู่ดี
ดังนั้นก็ได้แต่ถอนหายใจแล้ว implement นโยบายรหัสผ่านหมดอายุ และต้องฟังพนักงานบ่นว่าไร้ความสามารถ พอ log4shell โด่งดังมาก ตอนนี้ถ้าบริษัทประกันจะเรียกร้องให้เซิร์ฟเวอร์ปฏิเสธ “สตริงแฮ็ก” ที่พบบ่อยอย่าง
/etc/hosts,/etc/passwd,jndi:ก็คงไม่น่าแปลกใจถ้าถาม CIO ว่าสิ่งนี้ป้องกันภัยคุกคามจริง ๆ อะไรได้บ้าง ก็จะได้แต่สีหน้าเหม่อลอยกลับมา
ในมุมวิศวกร จึงไม่มีแรงจูงใจที่จะพยายามทำความเข้าใจว่า input form แต่ละอันไปที่ไหน และ sanitize อย่างมีความหมาย งานที่ได้เงินคือการติ๊กช่องแล้วข้ามไป เด็กใหม่ก็เรียนรู้เรื่องนี้ได้อย่างรวดเร็ว องค์กรแบบนี้ไม่ได้โฟกัสที่การปรับปรุงความปลอดภัย แต่โฟกัสที่การหลบเลี่ยงความรับผิดหลังเกิดเหตุละเมิด
การใช้ตัวกรองกับ “สิ่งอื่น ๆ” ที่เข้าออกเซิร์ฟเวอร์หรือส่งต่อระหว่างเซิร์ฟเวอร์อาจพอสมเหตุสมผล แต่ไม่เห็นประโยชน์ด้านความปลอดภัยจากการกรองข้อความเนื้อหาจริงที่จะถูกแสดงเป็นคอนเทนต์บล็อก ดูเหมือนเป็นบั๊กที่ค่อนข้างชัดเจนมากกว่า
https://en.wikipedia.org/wiki/Scunthorpe_problem
backend ควรจัดการเนื้อหาแบบ byte ใด ๆ ใน input field ได้ และไม่ควรเปราะบางต่อ SQL injection เพียงเพราะไม่มีการกรองล่วงหน้าที่ชั้น CDN
"/etc/hosts"อยู่ตรงไหนสักแห่งในคอนเทนต์ของ resource ที่ร้องขอมาแบบตรง ๆ ก็ดูเหมือนว่ามันพังอย่างค่อนข้างชัดเจนนึกถึงเกร็ดเรื่องแพลตฟอร์มอีคอมเมิร์ซหนึ่งขึ้นมา มีคนทำเว็บช็อปที่มี memory leak และตั้ง workaround ให้รีสตาร์ตแอปเมื่อสตริง
"OutOfMemoryException"ปรากฏใน logต่อมานักพัฒนาอีกคนอยากบันทึกคำค้นหาของลูกค้าลง log แล้วถ้ามีใครพิมพ์
"OutOfMemoryException"ในช่องค้นหา…"system(...)"ไว้ แล้ว WAF ตัดสินว่าเป็น PHP injection จึงบล็อก IPสงสัยว่า
/etc//hostsหรือ/etc/./hostsก็ถูกบล็อกด้วยไหม การตีตัวตุ่นแบบนี้ล้มเหลวแน่นอนคนที่ทำสิ่งแบบนี้ควรรู้ว่าผู้โจมตีฉลาดและดื้อกว่าพวกเขา และควรพึ่งพาเฉพาะวิธีรักษาความปลอดภัยที่พิสูจน์แล้ว เช่น ไม่ execute input ที่ไม่น่าเชื่อถือ
ครั้งหนึ่งเคยมีคนบอกว่าต้องใช้ WAF เพื่อป้องกันการโจมตี SQL injection กับแอปพลิเคชันที่ไม่ได้ใช้ฐานข้อมูล SQL ด้วยซ้ำ
พอโต้แย้งก็จะได้ฟังบรรยายเรื่อง “defense in depth” เสมอ และถ้าบอกว่าการเคาะโต๊ะหนึ่งครั้งทุกเช้าวันพฤหัสบดีแล้วหมุนตัวอยู่กับที่สามรอบน่าจะได้ผลกว่า เขาก็มองเหมือนเราเป็นบ้าจริง ๆ ผมทำอย่างนั้นทุกสัปดาห์และไม่เคยถูกแฮ็กเลย งั้นก็เป็น defense in depth ไม่ใช่เหรอ ไม่เห็นจะเสียหายอะไร
การตีความ wildcard ยุ่งยากกว่า แต่ถ้ามีรายการไฟล์ต้องห้ามก็ทำได้เพียงพอ
https://nodejs.org/api/path.html#pathresolvepaths
แก้ไข:
realpathของ C ทำงานต่างออกไปเล็กน้อย โดยจะเปลี่ยนลิงก์ถ้าถามว่า Substack จะปรับปรุงสถานการณ์นี้เพื่อคนเขียนสายเทคนิคได้อย่างไร?
ก็แค่ไม่เอา ไฟร์วอลล์เว็บแอปพลิเคชัน ที่โง่เหมือนก้อนหินไปแปะไว้กับเอนด์พอยต์แก้ไขบทความ ซึ่งควรรองรับได้ทุกหัวข้อ แม้แต่สตริงที่จะไปทริกเกอร์ WAF โง่ ๆ ก็ตาม
เหมือนกับเว็บบอร์ดนักพัฒนาเว็บที่ติดฟิลเตอร์ XSS จนสมาชิกพูดเรื่อง XSS กันไม่ได้ ควรเรียนรู้วิธี escape เนื้อหาให้ถูกต้อง
พวกนี้โง่ และก็แค่ใช้กองขยะอ่านยากของ OWASP ที่ชื่อ
corerulesetผมไม่ค่อยเห็นด้วยกับคำกล่าวที่ว่ากรณีนี้แสดงให้เห็นความตึงเครียดที่น่าสนใจระหว่างการป้องกันกับความใช้งานง่ายในความปลอดภัยเว็บ นี่มันก็แค่บั๊ก แถมเป็นบั๊กโง่ ๆ ด้วย แค่แสดงให้เห็นว่าคนที่ควรรู้ดีกว่านี้กลับไม่รู้
ความตึงเครียดระหว่างความปลอดภัยกับความใช้งานง่ายมีอยู่จริง แต่กรณีนี้ไม่ใช่ ปกติมันคือการประนีประนอมแบบทำความปลอดภัยที่ดีแล้วทำให้ผู้ใช้ลำบากขึ้น เช่น การยืนยันตัวตนสองขั้นตอน การล็อกหลังล้มเหลว 3 ครั้ง หรือการจำกัดอัตราเพื่อกัน DoS คือความปลอดภัยสูงขึ้นแล้วประสบการณ์ผู้ใช้แย่ลง หรือประสบการณ์ผู้ใช้ดีขึ้นแล้วความปลอดภัยลดลง
แต่นี่ไม่ใช่ทั้งสองอย่าง มันคือ ความปลอดภัยที่แย่ พร้อมกับ ประสบการณ์ผู้ใช้ที่แย่ ไม่รู้ว่าความตึงเครียดอยู่ตรงไหน
แน่นอนว่าคนเขียนเว็บ PHP ก็รู้ทันอย่างรวดเร็ว และมีเทคนิคเลี่ยงสารพัด โดยรวมแล้วเป็นไปได้สูงว่าการ “ทำความสะอาด” แบบนั้นให้ผลแย่กว่าตอนที่ไม่มีมันเสียอีก
หลังจากเคยโดนมาแล้วครั้งหนึ่ง พอเห็นคำว่า “ข้อผิดพลาดเครือข่าย” สาเหตุก็ผุดขึ้นมาในหัวทันที
ตอนสอนทีมแข่งเขียนโปรแกรม นักเรียนครึ่งห้องส่งคำตอบแล้วได้หน้าว่าง หลังดีบักไปหนึ่งชั่วโมงก็จำกัดวงได้ว่าเป็นชนิดข้อมูลและคีย์เวิร์ด C++ บางตัวที่ถ้าปรากฏในโค้ดจะทำให้เกิด 403 ซึ่งทั้งหมดก็มีความหมายใน JavaScript ด้วย
ตอนทำงานที่ธนาคารก็มี API ที่ต้องส่งไฟล์ Python และไฟล์ Python ส่วนใหญ่เจอ 403 ส่วนไฟล์สั้น ๆ ผ่าน หลังดีบักหลายชั่วโมงก็จำกัดวงได้ว่าเป็นคีย์เวิร์ดหนึ่งที่โผล่ในโค้ดเป็นครั้งคราว
หลายเดือนต่อมาในสภาพแวดล้อมคลาวด์ใหม่ก็เจอแบบเดิมอีก และเสียเวลาไปอีกหลายชั่วโมง หลังจากครั้งที่สอง เพื่อนร่วมงานเลยทำให้สคริปต์ deploy พิมพ์
"HAHAHA YOU'VE BEEN WAFFED"เมื่อเจอ 403 ซึ่งผมยังซึ้งใจอยู่ เพราะเห็นข้อผิดพลาดนั้นบ่อยกว่าที่คิดมากในแอปพลิเคชันของเราก็เคยเจอเรื่องคล้ายกัน เรดทีม ภายในกำลังโพสต์ข้อมูลที่มีความพยายามโจมตี XSS และ injection แบบอื่น ๆ
ตัวการโจมตีเองไม่สำเร็จ แต่เพียงเพราะรายการเหล่านั้นมีอยู่ ไฟร์วอลล์ของบริษัทก็บล็อกคำขอเครือข่ายที่มีเพย์โหลดนั้น ทำให้หน้าแอดมินภายในโหลดไม่ได้ สุดท้ายการโจมตี XSS ที่ล้มเหลวจึงกลายเป็นการโจมตี DoS ที่ได้ผล
ของเก่ากลับมาใหม่อีกครั้ง สมัยก่อนเราเรียกเรื่องแบบนี้ว่า ปัญหา Scunthorpe
https://en.m.wikipedia.org/wiki/Scunthorpe_problem
cockpitมักถูกเปลี่ยนเป็นc***pitเสมอ ค่อนข้างตลกดีถ้ากำลังเขียนเรื่องชีววิทยา การเงิน หรือธรณีวิทยาอยู่ล่ะ? ก็ถือว่าซวยไป
การกรองแบบโง่ ๆ แย่ได้มากพออยู่แล้ว แม้คนฉลาดและมีเจตนาดีจะเป็นคนเขียนก็ตาม
เมื่อคืนก็เจอปัญหาคล้ายกันใน OpenRouter OpenRouter เป็นบริการแนว “สวิตช์บอร์ด” ที่ยอดเยี่ยม เพราะทำให้ใช้ LLM หลายตัวผ่านเอนด์พอยต์เดียวได้ แต่เมื่อคืนผมเริ่มทดสอบว่ารุ่นไหนเก่งกับการจัดการ HTML ดิบหลาย ๆ แบบ
แต่ API ของ OpenRouter ถูกป้องกันด้วย Cloudflare ดังนั้นถ้าเนื้อหาในคำขอ POST มี HTML ดิบและชิ้นส่วน JavaScript บางอย่างอยู่ คำขอจำนวนมาก แม้ไม่ใช่ทั้งหมด ก็จะถูกบล็อก ส่งพรอมป์เดียวกันไปหา OpenAI หรือ Anthropic โดยตรงกลับไม่มีปัญหา
ถ้าเป็นโมเดลฟรี ผมยังเข้าใจได้ว่าต้องกันการใช้งานในทางที่ผิดอย่างเข้มงวด แต่นี่เป็นคำขอที่คิดเงินกับโมเดลเชิงพาณิชย์ เลยยิ่งน่าหงุดหงิด
ผมเคยเจอปัญหานี้มาก่อนและหงุดหงิดสุด ๆ เพราะ
"Network error"ทำให้ผมอัปเดตบทความที่เขียนค้างไว้หลายเดือนไม่ได้ ตอนนั้นนึกว่าเพราะแก้แล้วบทความยาวขึ้น เลยหาสาเหตุไม่เจอการติดต่อทีมซัพพอร์ตก็ยากเพราะมีแชตบอต AI และพอในที่สุดก็ถึงคนจริง “ฝ่ายซัพพอร์ตเทคนิค” ของพวกเขาก็ดูไม่มีทีท่าว่าจะตรวจสอบในเวลาที่สมเหตุสมผล
จนมีคนหนึ่งใน Twitter เสนอความเป็นไปได้ว่าอาจมี สตริงวิเศษ บางอย่างไปสะกิดลอจิกความปลอดภัยโง่ ๆ นั่นแหละ ผมถึงพบปัญหาและแก้บทความได้ในที่สุด