Wall of Text #14: Information security for dev

อยากเขียนเรื่อง security บ้าง หลังๆ ทำงานกับ security team เยอะขึ้น แล้วรู้สึกว่าจริงๆ มันไม่ยากอย่างที่คิด

Threat

ตอนที่เรียน information security ชอบรูปนี้มาก รู้สึกว่าอธิบายได้ดี เคยเจอรูปต้นฉบับในเน็ต แต่เข้าใจว่าหนังสือมีลิขสิทธิ์เลยหายาก ก็เลยวาดให้ใหม่ใน Paint

Security มีองค์ประกอบอยู่ 3 อย่าง

  1. Threat (ภัยอันตราย) ในรูปก็คือน้ำจะท่วมแล้ว
  2. Vulnerability (จุดอ่อน) ในรูปก็คือ กำแพงกันน้ำมีรอยรั่ว
  3. Control (การควบคุม) ในรูปก็คือเอามือปิดรอยรั่วไว้

ถ้ากำแพงรั่วแล้วเอามือปิดไว้ ผลคือน้ำไม่ท่วม เท่ากับว่าบรรลุเป้าหมาย แปลว่ามี security แต่ถ้าเกิดน้ำสูงกว่ากำแพงก็สร้างปัญหาได้อยู่ดี

CIA Triad

Security จริงๆ แล้วมีสมบัติ 3 อย่างหลักๆ ซึ่งอาจจะซอยข้อย่อยได้อีก 3 อย่างหลักๆ นี้คือ

  1. Confidentiality (ลับ) คือคนที่จะเห็นข้อมูลได้ต้องเป็นคนที่ตั้งใจจะให้เห็นเท่านั้น
  2. Integrity (สมบูรณ์) คือข้อมูลถูกต้องครบถ้วน เช่น ถ้ามี hacker เข้ามาเปลี่ยนหน้าเว็บเป็น rickroll ถือว่าเสีย Integrity
  3. Availability (ใช้งานได้) เช่น โดนยิง DDoS คนเข้าใช้งานไม่ได้เลย ถึงจะไม่ทำให้ข้อมูลหลุดหรือโดนแก้ไขข้อมูลก็เป็นปัญหา security เหมือนกัน

ซึ่งก็มีมาตรการต่างๆ ที่ช่วยรักษาสมบัติพวกนี้ เช่น

  1. Confidentiality
    • Access control ไม่ให้คนที่ไม่อนุญาตเข้าถึงได้ เช่นระบบ user account, firewall
    • Encryption เข้าถึงได้แต่เปิดอ่านไม่ได้
    • Contract เซ็นสัญญาไม่เปิดเผยความลับ ก็ใช้ควบคุมได้ถ้าไม่ได้อยู่ในระบบคอมพิวเตอร์
    • Monitoring ตรวจจับว่ามีผู้บุกรุก
  2. Integrity
    • Checksum คือสามารถยืนยันได้ว่าข้อมูลถูกต้องครบถ้วน
    • Signing คือจำกัดให้ checksum สร้างได้จำกัดคน ป้องกัน hacker สร้าง checksum ใหม่
    • Backup
    • Access control จำกัดคนที่แก้ไขข้อมูลได้ก็ช่วยได้เช่นกัน
    • Monitoring ก็ช่วยได้อีกเช่นกัน
  3. Availability
    • Spare มีระบบสำรองกรณีระบบหลักมีปัญหา
    • Scale out มีหลายๆ ระบบทำงานพร้อมกันเพื่อลดคอขวดจากจุดเดียว
    • Monitoring ว่าระบบยังทำงานได้ปกติ ไม่มีการใช้งานผิดปกติ

Security assessment

ไม่แน่ใจว่าตำรา security จะเขียนแตกต่างจากนี้ไหม แต่โดยทั่วๆ ไปแล้วเวลาผมประเมินความเสี่ยงจาก security จะทำตามขั้นตอนนี้ ซึ่งจริงๆ ผมว่ามันจะคล้ายๆ กับการทำ Persona ของ UX

  1. Threat modeling พูดง่ายๆ คือ กลัวอะไรอยู่ หลักๆ ก็อาจจะเป็น
    • กลัวคนนอก (hacker)
    • กลัวคนใน (insider attack, data loss)
    • กลัว user อื่น (spammer)
    • กลัวแอพพลิเคชั่นอื่น (lateral movement)
    • กลัวโปรแกรมเมอร์คนอื่น (defensive coding)
    • ซึ่งเราอาจจะไม่ต้องกลัวทุกอย่างก็ได้ เช่นเว็บเล็กๆ มีทีมงานเห็นๆ กันอยู่ 2-3 คน โอกาสที่คนในจะเป็นหนอนอาจจะน้อยก็ไม่จำเป็นต้องทำเรื่อง insider attack
  2. Vulnerability – ลอง list ออกมาว่าเขาจะทำอะไรมิดีมิร้ายได้บ้าง ผมคิดว่า list ทั้งหมดน่าจะยาวมากไม่สามารถเขียนมาได้ ต้องใช้ประสบการณ์ที่จะเห็นแล้วพอนึกออกว่ามีข้อไหนบ้างที่ apply เช่น
    • คนนอกอาจจะ port scan, เอาช่องโหว่มา scan, ทำ SQL injection หรือ XSS, เดารหัสผ่าน หรือ credential stuffing
    • คนในที่มี admin อาจจะใช้อำนาจในทางที่ผิด เช่น โกรธแฟนเลยแอบดูข้อมูลการใช้งานของแฟน (insider attack) โดนหลอกให้ทำ (phishing) หรือขโมยข้อมูลไปให้คู่แข่ง (data loss)
    • user อาจจะส่ง spam หากันเอง
    • คนใน หรือ application ใน network โดนฝัง shell แล้ว scan หา application ภายในเพื่อ hack ต่อ (lateral movement)
    • โปรแกรมเมอร์คนอื่นที่มาเรียกฟังค์ชั่นนี้อาจจะส่ง parameter มาผิดวิธีแล้วทำให้เกิดช่องโหว่ เช่นเรียก sql query แต่ไม่ได้ escape quote
  3. Control เป็นส่วนสำคัญที่สุด ถ้าเรามี control เพียงพอจะ run Ubuntu 8.04 ใน production ก็ได้ ตัวอย่างของ control เช่น
    • ทำ input validation ถ้าเป็นค่าที่ไม่ถูกต้องไม่ให้ประมวลผล
    • อัพเดต Application ให้ล่าสุดเพื่อไม่ให้โดน hack จาก library ที่ไม่อัพเดต เช่น Log4shell, Apache Struts
    • แต่บางที vendor อาจจะยังออก patch ไม่ทัน ก็ต้องกันจากด้านนอกเช่นใช้ WAF SaaS เพื่อตรวจจับการยิง
    • แต่ WAF ก็ bypass ได้ อาจจะเพิ่ม firewall ไปอีกเพื่อจำกัด IP ที่เข้าใช้งานได้กรณีที่เป็นระบบปิด
    • เพิ่ม firewall ขาออกด้านในด้วยเพื่อที่ว่ายิงเข้ามาได้ก็อาจจะส่งข้อมูลออกไป internet ยาก และเข้าไปโจมตี application อื่นๆ ยาก
    • สุดท้ายเพิ่ม access log เพื่อที่ว่าถ้ามีคนทะลุทุกอย่างมาได้จริงยังสามารถจับมือคนดมได้

“Control ที่เพียงพอ” เป็นคำถามที่ตอบยากมากๆ เพราะระบบที่ปลอดภัย 100% ไม่มีจริง ยิ่งทำมากยิ่งเสียเวลา (diminishing return) และทำให้ใช้งานลำบากด้วย อีกส่วนหนึ่งคือมูลค่าของระบบที่จะปกป้องกับระบบรักษาความปลอดภัยควรจะเหมาะสมกัน เช่นถ้าเป็นเว็บ company profile ธรรมดาๆ การซื้อ WAF, L7 firewall มาติดตั้งอาจจะมูลค่าหลักแสนหรือหลักล้าน แต่ความเสียหายคือแค่ restore จาก backup ก็กลับมาใช้งานได้แล้ว แบบนี้ก็ถือว่า backup เป็น control ที่เพียงพอแล้ว

เวลาเขียนโค้ด โค้ดทุกบรรทัดต้องทำ security assessment แบบนี้เสมอ ซึ่งคนส่วนมากน่าจะคิดว่าโอเวอร์เกินไปแล้วไม่ทำเลย แต่ผมคิดว่าถ้ามีประสบการณ์ security มาบ้างจะเริ่มจับทางได้เหมือนเป็น code smell ประเภทหนึ่งว่าในจุดนี้ต้องเริ่มวิเคราะห์ threat modeling อย่างละเอียดแล้ว ทำให้ทำงานได้เร็วขึ้น เช่น

  • ทุกจุดที่ใช้ตัวแปรที่ user ป้อนเข้ามา (โดนแฮคได้หลายแบบ ตามด้านล่างนี้)
  • โค้ดเกี่ยวกับ password (ตรวจดูว่า hash รหัสด้วยอัลกอริธึมและพารามิเตอร์ที่เหมาะสม และเปรียบเทียบรหัสผ่านโดยใช้เวลาคงที่ (constant time comparison))
  • โค้ดที่เกี่ยวกับวิทยาการรหัสลับ (ไม่แนะนำให้ใช้ algorithm โดยตรง ควรจะใช้ use case based library)
  • โค้ดที่ยิง URL แล้ว user กำหนดค่าเองได้ (อาจสุ่มเสี่ยง SSRF หรือ logic ในการ parse กับ validate ไม่ตรงกัน)
  • โค้ดที่รันสคริปต์ที่ user ส่งเข้ามา (ควรจะทำ sandbox ให้เหมาะสม)
  • โค้ดที่ใช้ตรวจสอบข้อมูล (data validation)
  • โค้ดที่จัดการข้อมูลขนาดใหญ่ในครั้งเดียว (ระวังไม่ให้ user ใช้งาน memory หรือ disk ใหญ่เกินไป)

Defense in Depth

ในอุตสาหกรรมการบินจะมีการใช้ Swiss cheese model

By BenAveling – Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=91881875

โมเดลนี้ใช้แนวคิดว่าเราไม่สามารถป้องกันความเสี่ยงได้ 100% ถ้าไม่อยากให้ชีสมีรูทะลุไปอีกฝั่ง การมีชีสเรียงกันหลายๆ ชั้นก็ลดโอกาสที่ชีสทุกแผ่นจะมีรูเดียวกันหมดได้ ในฝั่ง security มักจะเรียกว่า defense in depth

Not security

บางอย่างไม่ทำให้เกิด security

Security theater

เล่นละครไม่ทำให้เกิด security

เช่น นโยบายบอกว่าต้องตรวจสัมภาระก่อนเข้าสู่สถานที่ แต่คนตรวจเปิดอยู่ช่องเดียวแล้วส่องไฟผ่านๆ แบบนี้ไม่เกิดความปลอดภัย

Security is not a product

คนที่ไม่เข้าใจ security มักจะโดนเซลเป่าหูให้ซื้อ security product แต่ไม่ทำให้เกิด security จริง เปรียบเสมือนเช่ายันต์และห้อยพระเครื่องไว้ที่ server ให้อึด ถึก ทน ยิงไม่เข้า (ถ้า product มันเหนียวจริง ซื้อมาแล้วโดนแฮคควรจะฟ้องร้อง vendor ให้ใช้ค่าเสียหายได้)

การซื้อ product อาจจะช่วยเพิ่ม security ได้จริง แต่ก็ต้องกลับไปมองที่ security assessment ว่าสิ่งที่ซื้อมา ซื้อเพราะกลัวอะไร ซื้อแล้วมันได้ผลจริงกี่ % ซึ่งมันไม่ใช่ 100% แน่ๆ ต้องมีแผนให้ชัดเจนว่า control ต้องเพิ่มอะไรอีกบ้างจึงจะเพียงพอ

Security is not a feature

Project manager ที่ไม่เข้าใจ security อาจคิดว่า security เป็น feature หนึ่งแล้วก็แยกเป็น ticket low priority ทำทีหลัง

ผ่านไป 1 ปีก็ยังไม่ได้ทำจนกระทั่งโดน hack แล้วบอกว่าลูกค้าด่าต้องทำให้เสร็จภายใน 1 สัปดาห์

ในความเป็นจริงแล้ว security เป็นส่วนหนึ่งของทุกๆ feature การ “เติม” security เข้าไปภายหลังสร้าง technical debt ได้รวดเร็วมากเพราะมันมักจะส่งผลต่อ design และการแก้ design flaw เป็นเรื่องยาก ใช้เวลานาน

Security by obscurity

Security ที่แท้จริงถ้าเฉลยกลให้ทั้งหมดแต่ไม่บอกรหัสลับก็ไม่สามารถผ่านเข้ามาได้ เช่นวิธีเข้ารหัส AES นั้นเป็นข้อมูลเปิดเผยหาอ่านได้ทั่วไป ถึงอย่างนั้นถ้าไม่บอกกุญแจเข้ารหัสปัจจุบันยังไม่มีใครถอดรหัสข้อความใดๆ ได้

โบราณว่า ทองแท้ไม่แพ้ไฟ

มีบางคนคิดว่า AES เป็นข้อมูลเปิดเผย มี paper มากมายที่ลดความปลอดภัยของ AES ถ้าอย่างนั้นเราออกแบบ algorithm ขึ้นมาเองเฉพาะภายในบริษัทแล้วก็เป็น algorithm ที่มีความปลอดภัยสูงสุด ไม่เคยมีผู้ใดในโลกถอดรหัสได้โดยไม่ต้องรู้กุญแจ

ผ่านไป 6 เดือน hacker reverse engineer โปรแกรมมาดูแล้วพบว่าเป็น XOR กับ hardcode key ธรรมดาๆ แล้วก็เอา key ไปแจกในเน็ต

People is the weakest link

xkcd 538

Cargo cult security

“อาจารย์บอกมา” ไม่ใช่ security ที่ดีเสมอไป เช่น

  • อาจารย์ให้ config มา ตั้งตามแบบนี้แล้วเหนียว ยิงไม่เข้า แต่พอใช้แล้ว CEO โดนบล็อกทำงานไม่ได้
  • อาจารย์สอนให้ต้องมี CSP header แล้วจะป้องกันการแฮคได้ แต่เปิด unsafe-eval ไว้เพราะ marketing จะใช้ Google Tag Manager
  • อาจารย์สอนวิธี encrypt รหัสผ่านด้วย MD5 แล้วทำให้รหัสผ่านปลอดภัย แฮคไม่ได้
  • ซื้อ Tool scan มา scan เจอ 500 ข้อ พอแก้ตามที่ tool แนะนำแล้ว application ใช้งานไม่ได้
  • ซื้อ Tool scan มา scan ก่อน release application ปรากฏว่าจะแก้ให้ผ่านเป็น breaking change ส่งมอบงานไม่ทันเวลา
  • ซื้อ Tool scan ช่องโหว่ 10 อันดับยอดนิยมมา scan แล้วไม่เจอสักรายการที่ต้องแก้ไขแสดงว่าปลอดภัย แต่โดน hack ด้วยช่องโหว่ยอดนิยมอันดับที่ 11

เขาว่ายอด consult จะบอกว่า It depends ซึ่ง security ก็เช่นกัน “อาจารย์บอกมา” อาจจะไม่ได้ผิด แต่ไม่สามารถคำนึงถึง It depends ได้ ต้องมีความเข้าใจที่ถูกต้องว่าทำไมอาจารย์ถึงบอกมา

เก็บไฟล์บัตรประชาชนยังไงดี?

ช่วงต้นปีที่ผ่านมามีข่าวครึกโครมอันหนึ่งที่บริษัทชื่อดัง ทำ bucket ที่เก็บบัตรประชาชนลูกค้าเป็นสาธารณะ และมีผู้ไปพบเข้า

หลายเดือนต่อมาผมก็ไม่คิดว่าที่ TipMe ก็จะต้องเก็บรูปบัตรประชาชนไว้เช่นกัน ก็เลยคิดว่าจะต้องเก็บให้ปลอดภัยแบบที่อ่านแล้วรู้สึกว่าแน่นหนา

Threat Model

ก่อนจะทำอะไรก็ต้องนึกถึง threat model ก่อน เพราะถ้า regulation ต้องการว่าไฟล์ถูก encrypt นั้น เนื่องจากเราใช้ Google Cloud Storage ก็จะทำ Encryption ให้อยู่แล้วโดยไม่สามารถปิดได้ (ต่างจาก AWS ที่ค่า default คือปิด)

แต่ข้อกังวลสำหรับผมไม่ใช่ regulation เพราะเรายังไม่มีใครมาตรวจส่วนนี้ สำหรับเคสนี้ผมคิดว่าปัญหาจะอยู่ที่

  1. เผลอทำ bucket หลุดไป ข้อมูลไม่ควรจะสามารถอ่านได้
  2. Application server ถูก hack แล้วใช้สิทธิ์ของ app มาอ่านได้ (เพราะ app มันต้องอ่านได้ด้วย ตอนที่ admin เข้าไปตรวจสอบ)
  3. เนื่องจากเราจะใช้ signed url มีความเสี่ยงที่ signed url จะหลุดไป
  4. admin แอบเซฟรูปไป อันนี้คิดว่าคงไม่น่าจะเป็นปัญหาในตอนนี้ เนื่องจากทีมเรามีจำกัด

Design

ปัญหาที่ผมค่อนข้างกังวลคือข้อ 2 เนื่องจากแอพเป็น monolithic จึงการันตีได้ว่าทั้งระบบปลอดภัยได้ยาก และไม่มีแผนที่จะแยกเป็น microservice ให้ยุ่งยากด้วย เพราะคนเขียนมีคนเดียวไม่จำเป็นจะต้องพยายามทำอะไรให้รองรับทีมขนาดใหญ่ได้ในตอนนี้

ลักษณะการใช้งานของข้อมูลบัตรประชาชนคือ

  1. User submit ข้อมูลมา
  2. Admin เข้าไปดูรูปและยึนยันว่าเป็นบัตรประชาชนที่ถูกต้อง อาจจะมีการอ่านข้อความที่ต้องใช้เก็บไว้
  3. หลังจากนั้นแล้วไม่มีใครควรจะดูได้อีก
  4. หากบริษัทถูกเรียกถาม ควรจะสามารถเรียกคืนมาให้ตรวจได้

จะเห็นว่าจากข้อ 3 แล้วทำให้เราจัดได้ว่าข้อมูลนี้เป็น cold storage หลังแอดมินยึนยันข้อมูลแล้ว

ระบบที่เรา Design ออกมาก็เลยเป็นดังนี้

(ขออภัยกับ UML ด้วย ไม่ค่อยชินกับ tool ที่ใช้วาดเท่าไร)

  1. พอ admin ยึนยันบัตรประชาชนแล้ว app จะ call ไปหา secure service เราเรียกมันว่า sealerd
  2. sealerd จะถือ Google Cloud service account token อีกชุดหนึ่ง แยกไปจากของ app ปกติ
  3. sealerd ทำดังต่อไปนี้
    1. Download file มาแล้ว encrypt ด้วย public key ของบริษัท
    2. แก้ไข ACL ของไฟล์นั้นใน Google Cloud Storage ให้สามารถเข้าได้เฉพาะ service account ของ sealerd (แม้แต่ผมก็เข้าไม่ได้ ต้อง assume role เป็น sealerd เท่านั้น)
  4. app จะ mark ว่าไฟล์เข้ารหัสแล้ว เพื่อประโยชน์ในการแสดงผล UI

พูดง่ายๆ ก็คือเรามี security 2 ชั้นคือ

  1. File level access control ทั้งหมดจะถูกล้างเสมอ
  2. ถ้ามีคนเอาไฟล์ไปได้ ไฟล์ก็จะถูกเข้ารหัสด้วย key ซึ่งกุญแจถอดรหัสเราเก็บไว้ offline เว็บเราไม่สามารถถอดรหัสได้

จาก threat model แล้วก็จะพบว่า

  1. ถ้า bucket เผลอเปิดเป็น public เราจะมี encryption ป้องกันไม่ให้อ่านไฟล์ได้
  2. สิทธิ์การใช้ของ application server จะถูกยกเลิกหลังไฟล์ถูก seal (ทั้งนี้การถอนสิทธิ์ใน Google Cloud Storage เป็น eventual consistent แอพอาจจะยังอ่านได้อยู่อีกประมาณ 1 นาที)
  3. เราตั้งให้ Signed URL มีวันหมดอายุอยู่แล้ว และเนื่องจากเรายกเลิกสิทธิ์ของ Application server หลัง seal แล้ว Signed URL ที่มีจึงใช้ไม่ได้

Implementation

คำถามถัดมาคือ แล้วจะ implement อย่างไร?

ภาษา

ภาษาแรกในหัวผมที่จะใช้เขียนคือ Rust แต่หลายๆ ครั้งที่พยายามจะใช้ผมพบว่า Rust มี library ไม่ค่อยดีพอเลยยังไม่กล้าเสี่ยง

ถัดมาคือ Python กับ JavaScript ที่ใช้อยู่แล้ว แต่เนื่องจาก encryption library มักเป็น synchronous และ blocking ด้วย ทั้ง Python และ JavaScript พวกนี้มี Global Lock ก็เลยไม่น่าจะเหมาะที่จะเอามาใช้ เพราะต้องลุ้นอีกทีว่า library ที่ใช้มันไปทำข้างนอก interpreter lock หรือไม่

อีกเหตุผลคือผมอยากจะใช้ Tink ที่ยังไม่รองรับภาษาเหล่านี้

สุดท้ายคือ Go ซึ่งผมคิดว่า Tink น่าจะรองรับ ก็เลยเลือกใช้ Go

RPC

ท่า RPC ก็เป็นเรื่องที่ต้องตัดสินใจเช่นกัน ตัวเลือกก็จะมี

  1. JSON on REST (HTTP) ง่ายๆ ใครๆ ก็ใช้
  2. gRPC
  3. Cap’nproto
  4. Flatbuffer

ส่วนตัวอยากลอง Cap’nproto/Flatbuffer แต่รู้สึกว่า RPC library มันยังไม่ค่อยดี ไว้โอกาสหน้าอาจจะ port ดูเล่นๆ

เหลือแค่ gRPC กับ REST ก็เลยเลือก gRPC

เหตุผลที่เลือกคือ

  1. มันมี type ชัดเจน ใน Go จะเขียนง่าย
  2. มันเร็วมาก ที่วงในผมเขียน integration test ให้ start gRPC server ใน python แล้วยิง test request เร็วอย่างกับยิงใน process เดียวกัน
  3. ไม่ต้องกังวลเรื่อง compatibility เพราะไม่มี clientside ยิงมาอยู่แล้ว เลยไม่จำเป็นจะต้องใช้ HTTP

Encryption

Project นี้รู้สึกว่าจะพลาดที่สุดก็ตรงนี้แหละ ผมเสียเวลาไป 3-4 วันในการ design implement ระบบที่ secure ที่สุดเท่าที่จะนึกออก พอเขียนจริงเลยไม่ได้ research ละเอียดว่าภาษาอะไรที่จะใช้ implement แล้วเหมาะสม

มารู้สึกตัวครั้งแรกคือตอนที่เขียน gRPC ให้ Go เสร็จแล้วกำลังจะเขียนส่วนที่เข้ารหัส ก็เจอกับ Surprise แรกคือ Tink ไม่มีใน Go… อ้าว!!

ก็เลยมาที่ plan B คือใช้ Sealed box เหมือนที่ผ่านๆ มา

Surprise ที่สองคือ Go มี nacl box ในตัวก็จริง แต่ไม่มี libsodium ทำให้ไม่มี sealed box…

สุดท้ายเลยต้องทำเหมือนใน JavaScript คือ implement nacl-sealed-box เสียเองเลย ซึ่งก็ไม่ยากเพราะ Go มี crypto primitive ให้หมดแล้ว แค่เอามาต่อกันให้เหมือนกับของ libsodium เป็นอันเรียบร้อย

Connect

เสร็จแล้วก็เขียนต่อจากฝั่งแอพ เนื่องจากเป็น gRPC ก็ทำให้การ implement ค่อนข้างง่าย แต่ตอน compile proto ก็อาจจะเหนื่อยหน่อย

สำหรับการ dev บนเครื่องเราก็ทำ version พิเศษที่ต่อกับ local filesystem และเพื่อความชัวร์จึงทำให้ option ในการเลือก driver นี้เป็น link time option จะได้ไม่พลาดบน production

สรุป

ในวงการ Cryptography มีกฎอยู่ข้อหนึ่งเรียกว่า Schneider’s Law บอกว่า

ใครๆ ก็สามารถคิดค้นระบบความปลอดภัยที่ที่เทพมากจนเค้าไม่สามารถคิดวิธีแหกได้
Any person can invent a security system so clever that she or he can’t think of how to break it

ผมว่าระบบอันนี้ค่อนข้าง fit กับ description นี้แล้ว คือผมคิดว่ามันแน่นหนาพอ และผมว่าถ้าไปเจอใครโม้เรื่องวิทยาการรหัสลับเสียดิบดีโดยไม่ได้มี disclaimer แบบนี้ ผมว่ามันน่ากลัวกว่านี้อีกเยอะ

จริงๆ แล้วคิดว่าในการใช้งานส่วนมากแล้วอาจจะแค่ download ไฟล์ที่อนุมัติแล้วเก็บเข้า offline cold storage ก็น่าจะปลอดภัยกว่าระบบนี้แล้ว แต่ก็จะ automate น้อยลง ความเสี่ยงในการสูญหายมากขึ้น ใน tradeoff ของระบบเราแล้ว วิธีที่อธิบายมาในบทความนี้จึงน่าจะเป็นทางเลือกที่ค่อนข้างเหมาะสม