Address Space Layout Randomization

วันนี้เจอเรื่องประหลาดที่ไม่ค่อยได้เจอเยอะ เอามาจดเอาไว้

ปัญหาสำคัญในเรื่องของความปลอดภัยของซอฟต์แวร์คือเวลาที่โปรแกรมเมอร์ทำงานพลาด แล้วปล่อยให้แฮกเกอร์เอาโค้ดอื่นๆ มารันในซอฟต์แวร์ตัวเองได้ เช่นบั๊ก Buffer Overflow แฮกเกอร์มักหาทางไปต่อด้วยการหาคำสั่งอื่นๆ โดยเฉพาะพวก System Call ที่สร้างความเสียหายให้กับระบบ หรือเปิดช่องโหว่อื่นๆ ขึ้นมาเรื่อยๆ ง่ายๆ เช่นการสั่ง system() นั้นหมายความว่าแฮกเกอร์จะทำอะไรก็ได้เท่าที่ user ที่รันโปรแกรมนั้นทำได้

ตาม Murphy’s Law แล้ว โปรแกรมที่มีบั๊กนั้นมักจะรันใน root เสมอ

ในดอสนั้นปัญหาอย่างนี้เกิดง่ายมาก เพราะว่าตำแหน่งของ System Call ต่างๆ นั้นตายตัว ถ้าอ่านคู่มือของ OS มาเยอะๆ ก็จะรู้ทันทีว่าควร Jump ไปยัง Address ไหนเพื่อเรียก System Call อะไร เรียกว่าเจาะเข้า process ได้ปุ๊บก็เรียบร้อยกันไปเลย

แล้วอย่างนั้นจะทำยังไงดี

ตอบแบบกำปั้นทุบดินก็คงเป็นว่าไปบอกโปรแกรมเมอร์ให้เขียนโปรแกรมไม่มีบั๊ก เหมือนบอกว่านักการเมืองไม่โกงเมื่อใหร่แล้วบ้านเมืองจะดีเอง

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

คิดง่ายๆ คือเอา System Call ไปซ่อนมันซะเลย ทีนี้จะซ่อนมันที่ไหนดี เพราะถ้าถ้าซ่อนแล้วแฮกเกอร์รู้ มันก็ตามไปรังควานอีกจนได้นั่นแล

ในลินุกซ์นั้นเลยคิดอะไรที่ง่ายกว่านั้นคือการวางตำแหน่งของ ไลบราลี, Heap, Stack ฯลฯ ให้มั่วจนเละเทะ ทีนี่เวลาแฮกเกอร์เจาะเข้ามาได้ก็จะเริ่มทำอะไรไม่ถูก เพราะไม่รู้อะไรอยู่ตรงไหน จะไล่กวาดมั่วซั่ว ก็กวาดไปได้แป๊บเดียวก็พลาดไปทำ exception ขึ้นแล้วโปรแกรมก็ segmentation fault ไป

เทคนิคนี้เรียกย่อๆ ว่า ASLR (Address Space Layout Randomization) มันถูกเสนอขึ้นมาครั้งแรกในปี 2001 ถูกเปิดใช้งานเป็นค่ามาตรฐานในลินุกซ์ครั้งแรกในรุ่น 2.6.12 หรือช่วงปี 2005 ส่วนวินโดวส์นั้นใช้งานครั้งแรกตอน Vista และ Windows Server 2008 แต่พบว่ามีปัญหาในการสุ่มอยู่บ้าง และได้รับการแก้ไขใน SP1 ส่วน OS X นั้นรุ่น 10.5 แม้จะมีการสุ่มตำแหน่งไลบราลีบ้างแต่ก็ไม่ได้ทำเต็มที่อย่างเช่น OS ตัวอื่นๆ นัก

อ่อ ลืมไปว่าบล็อกนี้ geek จัด ถ้าอ่านมาแล้วเหมืนออ่านภาษาขอมก็ขออภัยผู้อ่านครับ

jinja

ส่วนหนึ่งที่ชอบมากใน django คือส่วน template engine ของมัน แม้จะไม่ค่อยชอบที่มันคล้ายๆ python แต่ดันต่างกันนิดหน่อยให้งงเล่นๆ แต่โดยทั่วไปแล้วต้องยอมรับว่า template ของ django มันใช้งานได้จริง

ปัญหาในช่วงหลังมานี้พอดีว่ามีเรื่องต้องทำ code generation เยอะ ด้วยความที่ต้องเขียนสคริปต์ TCL (ภาษารุ่นพ่อ) เพื่อมาใช้งาน NS2 ในการจำลองเครือข่ายคอมพิวเตอร์ แม้ns2 จะใช้ภาษาสคริปต์อย่าง TCL เพื่อความสะดวกในการแก้ไขสคริปต์โดยไม่ต้อง build ใหม่ทั้งระบบแล้วก็ตาม แต่การแก้สคริปเป็นร้อยๆ แบบก็ไม่สนุกนัก แถมภาษา TCL นั้นเขียนลำบาก เขียนผิดทีเล่นเอาหาไม่เจอบ่อยๆ อาจจะเป็นเพราะผมไม่ชำนาญเองก็ได้

วิธีที่ง่ายกว่าคือการสร้างสคริปต์ขึ้นมาใหม่ โดยใช้สคริปต์หลักเป็นโครง แล้วใช้พวก template engine นี่แหละมาสร้างเอา

เมื่อคิดได้อย่างนั้นสิ่งแรกที่ผมทำคือการ พยายามใช้ template engine ของ django มาสร้างสคริปต์ทันที แต่แล้วก็ต้องพบกับความลำบากเมื่อ template engine ของ django นั้นผูกกับตัว web framework จนแกะไม่ออก

สุดท้ายเลยมาเห็นเอา jinja ที่ระบุตัวเองชัดเลยว่าเป็น django-like แต่เอามาใช้งานแยกได้ง่ายๆ ตอนนี้ที่ใช้งานแบบง่ายๆ ก็มีแค่สามสี่บรรทัด

import jinja as jj env = jj.Environment(loader=jj.FileSystemLoader('./')) tmpl = env.get_template('template.tcl') print tmpl.render(number_of_node=3,width=100,height=20,packet_size=20,bandwidth=0.064)

น่าสนใจว่าถ้าเอาไปรวมเข้ากับ web framework อื่นๆ อย่าง web.py ก็น่าจะสวยดีเหมือนกัน