"Fly high but don't fly alone"
[Geek] พื้นฐานความปลอดภัยในการเก็บข้อมูลและรับส่งข้อมูลบนแอพฯมือถือ
28 Oct 2014 17:59   [21644 views]

วันก่อนพูดถึงการทำ API ให้ปลอดภัยขั้นพื้นฐานไปใน Blog [Geek] nonce, Signature และ https สามข้อพื้นฐานของการทำ API ฝั่ง Serverวันนี้มาพูดถึงฝั่ง Client บ้าง

เราชอบเอาแอพฯมาแกะแงะโน่นนี่เล่น ก็พบว่าแอพฯของไทยส่วนใหญ่มักจะไม่ใส่ใจเรื่อง Security เท่าไหร่เลย เก็บข้อมูลในรูปแบบที่สามารถโดนแฮคง่ายๆ เสียวแทนผู้ใช้

วันนี้เลยมาเขียนแนวทาง "พื้นฐาน" การเก็บข้อมูลภายในเครื่องและการรับส่งข้อมูลระหว่างมือถือและ Server ว่ามันมีช่องอะไรที่ให้ผู้ไม่หวังดีแฮคได้บ้าง และควรจะป้องกันอย่างไร

เก็บข้อมูลไว้ใน Application Private Area เท่านั้น

โดยปกติ Storage การเก็บข้อมูลบนมือถือ เราจะเข้าถึงได้ 2 ส่วนด้วยกันคือ

1) Public Area - ข้อมูลที่ใครก็สามารถเข้าถึงได้ ไม่ว่าจะจากแอพฯหรือจากผู้ใช้เอง ยกตัวอย่างง่ายๆก็ Gallery, Notes, Files on SD Card นั่นเอง ซึ่งพูดได้อีกอย่างว่า User สามารถเข้ามาลบไฟล์ได้ทุกเมื่อ

2) Private Area - ข้อมูลที่แอพฯนั้นๆมีโอกาสเข้าถึงได้คนเดียว ไม่สามารถเข้าถึงได้จากแอพฯอื่นๆ หรือแม้แต่ตัวผู้ใช้เองก็เข้าไปดูไม่ได้

โดยปกติ แอพฯต่างๆ หากไม่มีความจำเป็นต้องแชร์ข้อมูลให้กับแอพฯอื่น (ซึ่ง 99% ของข้อมูลมักจะเป็นแบบนั้นอยู่ละ) ก็ไม่ต้องคิดอะไรมาก เก็บไว้ใน Private Area ได้เลย ซึ่งการเก็บข้อมูลก็มีหลายวิธี ไม่ว่าจะเป็น Preferences เป็น SQLite หรือ Text Flie ก็ตาม แล้วแต่ความเหมาะสมได้เลย

ตาม Security ของ OS มือถือทุกตัวไม่ว่าจะเป็น Android, iOS หรือ Windows Phone ก็จะมีระบบ Protect แน่นหนาไม่ให้คนเข้าถึงข้อมูลส่วนนี้ ถือได้ว่ามีความปลอดภัยในการเก็บระดับหนึ่ง

อย่างไรก็ตาม ด้วยกลวิธี Jailbreak และ Root Device ที่ผู้คนทำกันอย่างแพร่หลาย ก็ทำให้ผู้ไม่หวังดีสามารถเข้าถึงข้อมูลตรงนี้ได้เช่นกัน

ดังนั้นอย่าไว้ใจ 100% ว่าการเก็บไว้ใน Application Private Area จะปลอดภัยแน่นอน

หากจำเป็นต้องแชร์ข้อมูลจากในแอพฯให้แอพฯอื่น ให้ใช้วิธีที่ถูกต้อง

บางทีแอพฯก็จำเป็นต้อง Provide ข้อมูลให้กับแอพฯตัวอื่น อย่าไปสร้าง Shared File ไว้ใน Public Area ให้ใช้วิธีที่ถูกต้องของแต่ละ OS เช่นบน Android ก็ใช้ ContentProvider ในการแชร์ข้อมูล เป็นต้น คราวนี้เราก็จะสามารถควบคุมทุกอย่างได้และไม่เกิดการผิดพลาด

Encrypt ข้อมูลสำคัญที่เก็บทุกครั้ง

อย่างที่บอกว่าถึงจะอยู่ใน Private Area แต่สุดท้ายก็มีวิธีจะเข้าถึงข้อมูลเหล่านั้นได้อยู่ และการเก็บข้อมูลพื้นฐานโดยทั่วไปจะสามารถอ่านออกจาก Hex Editor หรือถ้าเป็น SQLite ก็มี Viewer ไว้ดูอย่างเต็มตา

ดังนั้น หากมีข้อมูลที่มีความสำคัญ ยกตัวอย่างเช่น Secret Key ให้ Encrypt อยู่ในรูปแบบที่ดูไม่รู้เรื่องทุกครั้ง ให้คนที่เปิดมาดูคิดว่ามันเป็นข้อมูลที่ถูกต้อง แต่เอาไปใช้ไม่ได้

และการ Encrypt นี้ ให้หลีกเลี่ยงวิธีที่โดนแกะได้ง่าย เช่น อย่าใช้ md5 แบบดื้อๆ ถ้าจะ md5 ก็ให้หา Salt ยาวๆมาใส่ก่อน เป็นต้น

ป้องกันการแก้ข้อมูลด้วยการ Hash ข้อมูลที่เก็บไว้

เป็นวิธีป้องกันอีกทางหนึ่ง สมมติทำเกมแล้วเก็บข้อมูล "เงินในเกม" แล้วปรากฎว่าข้อมูลนี้ถูกเอาไปแก้ใน Hex Editor ได้ด้วยวิธีใดวิธีหนึ่ง

เราจะตรวจได้ยังไงว่ามีการแก้ข้อมูลโดยคนอื่นที่ไม่ใช่แอพฯเรา?

ก็ง่ายๆเลย ทุกครั้งที่มีการเปลี่ยนแปลงข้อมูล ก็ Hash ข้อมูล "ทุกอันที่เกี่ยวข้อง" แล้วเก็บไว้เป็นก้อนข้อมูลชุดหนึ่ง ตอนจะดึงข้อมูลขึ้นมาใช้ก็ Hash แล้วเช็คกับ Hash ที่เก็บไว้ว่าตรงกันรึเปล่าด้วย

รับส่งข้อมูลผ่าน https ทุกครั้งที่เป็นไปได้

เพราะว่าการใช้งาน Mobile Devices / Tablet มีผู้ใช้จำนวนหนึ่งต่อผ่าน Public WiFi ซึ่งมักจะไม่ปลอดภัย มีการแอบดักข้อมูลเก็บไว้บ่อยๆ

การรับส่งข้อมูลผ่าน https จะช่วยให้ Hotspot เหล่านี้ไม่สามารถดักข้อมูลของเราได้

แต่ https ไม่ได้แปลว่าจะมั่นใจได้ทุกอย่าง ไม่ใช่ว่าใช้แล้วโล่งอก ชั้นไม่โดนแฮคแน่ๆแล้ว ไม่จริง มันยังโดนได้อยู่ การใช้ https ต้องใช้แบบรอบคอบ ใช้แล้วจริงจังในทุกมิติ อ่านหัวข้อต่อไปเลย

หลีกเลี่ยงการข้าม SSL Certificate Validation

อย่างที่เล่าให้ฟังใน Blog ก่อนหน้านี้ว่าเรามีโอกาสที่จะ Sniff HTTPS ได้ ด้วยการลง Self Signed Certificate ไว้ในมือถือแล้วเวลาติดต่อก็ติดต่อผ่าน Proxy ซึ่งรู้จัก Certificate ตัวนั้น ผลคือ Proxy จะสามารถ Decrypt ข้อมูลออกมาเป็นข้อมูลดิบให้ดูได้ (นี่แหละ คุยกับปีศาจ)

ตรงนี้ตามกลวิธีของการติดต่อผ่าน https ถ้าเป็น Certificate ที่ Untrusted ทางคำสั่งก็จะเด้ง Exception มาทันทีอยู่แล้ว แต่ความน่ารักก็คือเราสามารถเขียนโปรแกรมเพื่อข้ามการเช็คตรงนี้ได้เช่นกัน

จากสถิติ มีแอพฯถึง 40% ที่ข้ามการเช็คตรงนี้เพราะขี้เกียจดีลกับ Exception ... จึงเปิดเป็นช่องโหว่ให้คน Sniff ได้ง่ายๆ

ขอให้หลีกเลี่ยงการกระทำเช่นนั้น เราควรจะเช็คทุกอย่างอย่างถูกต้องว่าเป็น Trusted Certificate ถึงจะทำงานต่อ ไม่งั้นก็ไม่ต้องส่งข้อมูลออกไปเลยครับ

ยังไงถ้าเจอเคสบาง Hot Spot งอแงกับ https ขอให้ท่องไว้คำนึงครับ ... "ช่างแม่ม"

อย่าไปแคร์กับสิ่งเล็กน้อย ความปลอดภัยสำคัญกว่า

ใช้ Certifcate Pinning

ถ้าระบบมี Server เป็นของตัวเองและแอพฯต้องการความ Secure มากๆ อย่างเช่น แอพฯธนาคาร การเช็ค Validity ของ Certification นั้นยังไม่พอ

วิธีหนึ่งที่จะช่วยให้เรามั่นใจได้ว่าไม่มีการปลอมแปลง Certificate เพื่อทำอะไรแผลงๆ คือเช็คว่า Cerficate ที่ใช้เป็นของ Server ที่เราจะติดต่อรึเปล่า เพราะตามปกติแล้ว ถ้าเป็น Server ของเราเอง เราก็จะรู้ว่า Certificate ที่ใช้หน้าตาเป็นยังไง ก็เช็คเลยตั้งแต่ต้นทาง

อย่างไรก็ตาม ถึงบทความนี้จะบอกว่าเป็นเรื่องพื้นฐาน แต่การทำ Certificate Pinning ต้องบอกว่าไม่ใช่เรื่องง่าย ถือว่าเป็นระดับ Advance เลยหละ ตามปกติก็จะใช้กับเฉพาะแอพฯที่ต้องการความ Secure สูงจัดๆ เช่น Mobile Banking, Stock Tradking ไรพวกนั้น

ข้อเสียอย่างนึงของ Certificate Pinning คือ ถ้ามีการเปลี่ยน Certificate บน Server ก็ต้องหาทางเปลี่ยน Cer บนแอพฯด้วย ไม่งั้นก็จะคุยกันไม่ได้นั่นเอง

หากมีการรับส่งข้อมูล Sensitive ให้ Encrypt ทุกครั้ง

ถึงจะกันแล้วกันอีก ใช้ https ก็แล้ว ก็อาจจะมีการผิดพลาดโดน Sniff ได้อยู่ (Programming Error ไรงี้) ขอให้หลีกเลี่ยงการส่งข้อมูลที่ Sensitive แบบดิบๆจากมือถือไปสู่ Server ห้ามเลย

ยกตัวอย่างเช่น การ Authenticate ที่ต้องส่ง Username และ Password ไปที่ Server ให้ Hash Password แบบ One-Way ไปที่ Server แทนการส่งแบบดิบๆไป

เพราะโดยปกติฝั่ง Server เราก็จะไม่เก็บ Password ดิบๆหรือในรูปแบบที่สามารถ Decrypt ย้อนกลับได้อยู่แล้ว (ยกเว้นองค์กรรัฐของไทยหลายองค์กร ... น่ากลัวชะมัด)

ก็ให้ใช้วิธี Hash One-Way แล้วมาเช็คว่า Hash แล้วค่าตรงกันหรือไม่แทน ก็จะช่วยให้ข้อมูล Secure ได้ ดักจับไปได้ก็ทำอะไรไม่ได้ ไรงี้ ที่เหลือการทำงานร่วมกับ nonce, Signature ตามบทความก่อนหน้านี้ จะช่วยให้แฮคเกอร์ Bruteforce ไม่ได้ เป็นความปลอดภัยหลายชั้นซ้อน

ส่วนข้อมูลที่ Sensitive กลางๆ แต่ต้อง Decrypt ย้อนกลับได้ เช่น ข้อมูลส่วนตัวบางอย่าง ก็ใช้วิธี Cipher ข้อมูลเอาครับ

ห้ามเก็บ Password ไว้ใน Client

อย่างที่บอกว่าไม่ว่ายังไง เราก็หาวิธีเข้าถึงข้อมูลใน Private Area ได้อยู่ดี

ดังนั้นห้ามเก็บ Password ไว้ใน Client เป็นอันขาด แต่ยังไงเราก็ต้องมีอะไรมายืนยันตัวตนในทุก Transaction ที่ส่งไปยัง Server ใช่มั้ยหละ

ระบบ Token จึงเกิดมา มีทั้งแบบ Access Token เดี่ยวๆ ใช้รหัสยาวๆตัวเดียวก็ใช้งานได้แล้ว และแบบ Key/Secret ที่เปรียบได้เหมือน Username และ Password นั่นเอง (Key เอาไว้ส่งบอกว่าเราเป็นใคร Secret มีไว้ Sign Request ดังนั้นหากดักจับได้ ก็จะไม่เห็นค่าของ Secret ในข้อมูลที่ส่งไป)

ให้เก็บ Key/Secret หรือ Access Token ไว้ในแอพฯแทน Password แต่อย่างไรก็ตาม รหัสพวกนี้ก็สามารถเอาไปสร้าง Request หลอกได้ (โดยเฉพาะอย่างยิ่ง Access Token ของ Facebook น่ากลัวมาก ได้มาก็ทำอะไรได้หลายอย่างละ)

พวกข้อมูลเหล่านี้ถือเป็นข้อมูล Sensitive พอสมควร เวลาเก็บให้ Encrypt ไว้อย่างแน่นหนาจริงจังทุกครั้ง

ทางฝั่ง Server ก็ต้องเตรียมระบบ Revoke Token เหล่านี้ทิ้งเมื่อเกิดเหตุไม่ดีด้วย รวมถึงหาก การตั้ง Token Expiration สำหรับ Token ที่ไม่ได้มีการใช้มาสักพักไว้ก็ดี

Obfuscate โค้ดด้วยตอนปล่อย Release

ศัตรูของแอปที่ปล่อยไปคือการ Decompile เพราะมันเปิดให้เห็นหมดทุกอย่างว่าแอปทำอะไร

แพลตฟอร์มที่เป็นเป้าโจมตีด้วยวิธีนี้มากสุดคือแอปที่เขียนด้วยภาษาจาวา ... แอนดรอยด์นั่นเอง มัน Decompile ง่ายมากๆ และดูโค้ดได้ทุกอย่างเลย

เราไม่สามารถห้ามการ Decompile ได้ แต่เราสามารถทำให้การ Decompile อ่านยากขึ้นมากได้ด้วยการ Obfuscate โค้ดโดยใช้ Proguard ลองไปอ่านเพิ่มที่บล็อก ทำความรู้จัก ProGuard เครื่องมือที่จะทำให้แอพฯแอนดรอยด์คุณเล็กลงกว่าครึ่งและยัง Reverse Engineer ยากขึ้น ได้ครับ

จงใส่ใจกับ Security

อย่าคิดว่าแอพฯเราไม่มีคนมาแฮคหรอก แอพฯเราไม่ต้อง Secure หรอก เพราะช่องโหว่เล็กๆช่องเดียว อาจทำให้ผลงานที่คุณทำมาหลายเดือนต้องพังและล่มสลายไปต่อหน้าต่อตา ความเสียหายมันมูลค่ามหาศาลเลยนะ

ขอให้ตระหนักไว้เสมอว่า Security เป็นสิ่งที่ "ต้องทำ" การออกแบบแอพฯจง "Start with Security" เพราะมันถือเป็นฟีเจอร์หนึ่งที่สำคัญ ตอนออกแอพฯมาก็ควรจะเขียนพ่วงไว้ย่อหน้าท้ายๆด้วยว่าระบบเรามีการเก็บข้อมูลอย่างปลอดภัย

ตอนนี้ Privacy Concern เริ่มเป็นที่พูดถึงขึ้นเรื่อยๆ แม้แต่ในไทยเองก็ตาม ให้ความสำคัญตรงนี้กันด้วยจ้า

หลีกเลี่ยงการให้เพื่อนยืมมือถือ

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


จบแล้น แบบพื้นฐาน เนื้อหาเบาๆไม่หนักมาก เนอะๆๆ

บทความที่เกี่ยวข้อง

Oct 25, 2014, 14:01
37566 views
[Geek] nonce, Signature และ https สามข้อพื้นฐานของการทำ API ฝั่ง Server
Oct 20, 2014, 20:41
16594 views
[Geek] Best Practices ของการทำ Push Notifications บนแอนดรอยด์
0 Comment(s)
Loading