วันจันทร์, กันยายน 11, 2549

จุดอ่อนของ DNS server

เรามักจะใช้ DNS server กันอย่างไม่รู้คุณค่า บทความนี้จะกล่าวถึงรายละเอียดการโจมตี DNS server และคุณสามารถทำอะไรเพื่อการรักษาความปลอดภัยที่ดีขึ้น ซึ่งจะตอบคำถามต่อไปนี้คือ
* แคร็กเกอร์(crackers) ใช้ประโยชน์(exploit) จาก DNS เซิร์ฟเวอร์ของคุณได้อย่างไร ?* คุณสามารถทำให้การรักษาความปลอดภัยของ DNS server แข็งกร่งโดยการกำหนดค่า(configuration)ได้อย่างไร ?* คุณสามารถทำให้การบุกรุก DNS server ของคุณเป็นฝันร้ายสำหรับผู้ที่บุกรุกได้อย่างไร ?
ซึ่งอธิบายในลักษณะของการโจมตีและการป้องกัน การป้องกันดำเนินการใน DNS server ที่ใช้ BIND เวอร์ชัน 8 แต่แนวความคิดใช้ได้กับ DNS server ทุกชนิด บทความนี้จะเป็นประโยชน์สำหรับผู้ดูแลระบบ
การโจมตี: ผู้โจมตีหาข้อมูลจาก DNS server ของคุณให้ได้มากที่สุดสมมติว่าโดเมนของเป้าหมายคือ dumb.target.jay เราต้องการรู้ว่า name server ของ dumb.tarbet.jay คืออะไรจึงใช้คำสั่ง nslookup ในยูนิกซ์ ดังต่อไปนี้:
[jay@max jay]$ nslookupDefault Server: ns.my.ispAddress: 10.0.0.1> set q=ns> dumb.target.jayServer: ns.my.ispAddress: 10.0.0.1Non-authoritative answer:dumb.target.jay nameserver = dumb.target.jaydumb.target.jay nameserver = ns2.dumb.target.jayAuthoritative answers can be found from:dumb.target.jay internet address = 192.168.1.85>
ต่อมาเมื่อรู้ว่าอะไรเป็น name server เพื่อใช้หาข้อมูล จึงถามเซิร์ฟเวอร์นี้ สำหรับรายการของโซน (zone)ใช้คำสั่ง dig เพื่อถามถึง zone transfer:
[jay@max zone]# dig @192.168.1.85 dumb.target.jay axfr; <<>> DiG 8.2 <<>> @192.168.1.85 dumb.target.jay axfr; (1 server found)$ORIGIN dumb.target.jay.@ 20H IN SOA ns1 hostmaster.dumb.target.jay (2000111001 ; serial5H ; refresh1H ; retry4d4h ; expire1D ) ; minimum1H IN NS dumb.target.jay.20H IN NS ns.dumb.target.jay.20H IN NS ns.dumbs.isp.20H IN A 192.168.1.851D IN HINFO "Pentium 133" "Red Hat 6.1"1D IN MX 10 mailmail 1D IN A 192.168.1.2really 1D IN A 192.168.1.201D IN TXT "Admin's Trusted Workstation"1D IN HINFO "Athlon 850" "Red Hat 6.1"rather 1D IN A 192.168.1.151D IN HINFO "Pentium 266" "Mandrake 7.1"serious 1D IN CNAME extraextra 1D IN A 192.168.1.80ns 1D IN A 192.168.1.30r_g 1D IN A 192.168.1.68roblimo 1D IN MX 10 r_g1D IN A 192.168.1.44tahara 1D IN A 192.168.1.27
ดูจากข้อมูลที่เราได้จากการใช้คำสั่งสองคำสั่ง จะเห็นว่ามีรายชื่อของเครื่องทั้งหมดที่อยู่ในโซนนี้ นอกจากนี้ถ้าคุณดูที่ HINFO คุณสามารถรู้ได้ว่าเครื่องเหล่านี้ใช้ลีนุกซ์อะไร ทำให้เรารู้อะไรบ้าง ถ้ามีรายการของ exploitที่ใช้ได้กับ Red Hat 6.1 ถ้าสามารถรู้ zone transfer และทำอย่างที่ทำข้างต้นและหา "Red Hat" จะพบเครื่องสองเครื่องที่เสี่ยงต่อการถูกโจมตีซึ่งรวมถึงเครื่อง workstation ของ sysadmin ด้วย จากนี้จึงมุ่งความสนใจไปที่สองเครื่องนี้ซึ่งมักจะมีความเชื่อถือกันเองระหว่างสองเครื่องนี้ด้วย เป็นขึ้นตอนแรกสำหรับcracker เมื่อต้องการรู้ข้อมูลเกี่ยวกับเน็ตเวิร์คนั้น
กำหนดค่า DNS server อย่างมีความเข้าใจ
DNS ได้รับการออกแบบในตอนที่อินเตอร์เน็ตเป็นสถานที่ที่น่าเชื่อใจกว่านี้มาก ไซต์ใหญ่ ๆ มากมายหลายแห่งยังคงกำหนดค่า DNS server ของพวกเขาให้บอกข้อมูลออกไปจำนวนมากต่อใครก็ตามที่ร้องขอ ข้อมูลในส่วนของ HINFO และ TXT เป็นประโยชน์สำหรับผู้บริหารไซต์นั้นที่จะต้องดูแลเครื่องจำนวนมากในไซต์ แต่เป็นประโยชน์มากกว่าสำหรับ cracker ผู้ซึ่งพยายามหาข้อมูลเกี่ยวกับคอมพิวเตอร์ของบริษัทคุณ
DNS ควรให้ข้อมูลเกี่ยวกับ ip/name mapping เท่านั้น เปรียบเทียบได้กับในบริษัทของคุณที่คุณจะให้ให้แผนกต้อนรับลูกค้าบอกถึงหมายเลขโทรศัพท์ภายในของบุคคลที่ต้องการเท่านั้น ไม่รวมถึงตำแหน่ง คุณสมบัติและโครงการของบริษัท คุณไม่ทำอย่างนั้นแน่นอนเพราะหมายถึงการเสี่ยงต่อการปล่อยให้ความลับของบริษัทรั่วใหล และอาจสูญเสียบุคคลากรของบริษัทคุณให้กับบริษัทอื่นคุณสามารถกำหนดค่าของ name server ของคุณได้อย่างง่าย ๆ ให้มันให้ข้อมูลจำเป็นจริง ๆ โดยการแก้ไขไฟล์ /etc/named.conf ไฟล์กำหนดค่าหลักของ BIND
options {directory "/var/named";};zone "dumb.target.jay" {type master;file "zone/db.dumb.target.jay";};zone "1.168.192.in-addr.arpa" {type master;file "zone/db.192.168.1";};
การกำหนดค่านี้แสดงให้เห็นเพียงส่วนของ options ซึ่งแสดงให้เห็น global setting, forward และreverse zone สำหรับโดเมนสมมติ dump.target.jay ตัวอย่างข้างบนได้ละส่วนของ root server และ localhost ไว้เพื่อความกระชับ ตัวอย่างนี้ใช้สำหรับ primary name server มากกว่าที่จะเป็นsecondary name server
ขั้นแรกให้ดูที่ zone transfer, zone transfer ปกติใช้เพื่อให้ secondary name server ได้อัปเดทข้อมูลให้เหมือนกับ primary name server เท่านั้น นอกจากนี้แล้วมันใช้เพื่อหาข้อมูลของเป้าหมายเท่านั้นสมมติว่า secondary name server มี ip address เป็น 192.168.1.30 และ 10.1.1.4 ดังนั้นเครื่องอื่นก็ไม่มีความจำเป็นต้องใช้ zone transfer ต่อมาจึงจำกัดมันดังนี้:
options {
directory "/var/named";
allow-transfer { 192.168.1.30; 10.1.1.4; };
};
สมมติว่าเน็ตเวิร์คภายในของคุณมีเพียงเครื่องที่มี subnet 192.168.1.x เท่านั้น เครื่องภายนอก subnet นี้ควรที่จะสอบถาม(query)ได้เฉพาะโซนที่คุณรับผิดชอบอยู่เท่านั้น สิ่งนี้สำคัญเพราะการโจมตี DNS serverส่วนใหญ่จำเป็นที่ผู้โจมตีต้องสามารถสอบถาม server อื่นซึ่งมักจะเป็นโดเมนที่ผู้โจมตีควบคุมอยู่ ถ้าเราไม่อนุญาตให้ผู้ใช้ภายนอกสามารถสอบถามถึงโดเมนที่ไม่ใช่ของเรา เราจะป้องกันจากการโจมตีได้หลายอย่าง
options {directory "/var/named";allow-transfer { 192.168.1.30; 10.1.1.4; };allow-query { 192.168.1.0/24; };};zone "dumb.target.jay" {type master;file "zone/db.dumb.target.jay";allow-query { any; };};zone "1.168.192.in-addr.arpa" {type master;file "zone/db.192.168.1";allow-query { any; };};
ถึงตอนนี้ใคร ๆ ก็สามารถสอบถามถึงโดเมน dumb.target.jay และ reverse ของมัน มีเพียงโฮสต์ภายในเน็ตเวิร์คเท่านั้นที่สามารถสอบถามอย่างอื่นได้ ท้ายสุดให้อนุญาตให้มีการสอบถามแบบเรียกตัวเอง (recursive)ได้จากโฮสต์ภายในเท่านั้น โดยต้องทำแต่ละโฮสต์ให้มีเฉพาะไลบรารีสำหรับการ resolve ip/hostname(resolver library) ซึ่งจะถาม name server สำหรับ name/ip mapping แต่ละโฮสต์จะสอบถาม nameserver ถึง ip ของ dumb.tarbet.jay name server จะสอบถาม root server เพื่อให้หาว่าโฮสต์ใดที่รับผิดชอบโดเมน .jay root server จะตอบ ip มาซึ่งมันจะติดต่อและถาม server ที่รับผิดชอบโดเมนtarget.jay ควรมีเพียงโฮสต์ภายในเน็ตเวิร์คของคุณเท่านั้นที่สามารถถาม name server เพื่อให้ทำอย่างนี้ได้เพราะโฮสต์ภายนอกมี name server ของตัวเองอยู่แล้ว การอนุญาตให้โฮสต์ภายนอกสอบถาม name serverของคุณให้ตอบแบบเรียกตัวเองสามารถนำไปสู่การโจมตีแบบ cache poisoning ได้ และโดยทั่วไปสิ่งนี้จะให้ข้อมูลที่มากเกินไปสู่ภายนอกเน็ตเวิร์ค
options {directory "/var/named";allow-transfer { 192.168.1.30; 10.1.1.4; };allow-query { 192.168.1.0/24; };allow-recursion { 192.168.1.0/24; };};
เอาละเราได้ทำให้การรักษาความปลอดภัยของ DNS แน่นหนาขึ้นแล้ว แต่ยังมีอะไรเหลืออีกล่ะ บางคนยังสามารถสอบถาม HINFO และ TXT records ได้ถึงแม้ว่าจะไม่สามารถทำการสอบถาม zone transfer ดังต่อไปนี้:
[jay@max jay]$ dig @localhost dumb.target.jay hinfo; <<>> DiG 8.2 <<>> @localhost dumb.target.jay hinfo; (1 server found);; res options: init recurs defnam dnsrch;; got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0,ADDITIONAL: 0;; QUERY SECTION:;; dumb.target.jay, type = HINFO, class = IN;; ANSWER SECTION:dumb.target.jay. 1D IN HINFO "Pentium 166" "Red Hat 6.1";; Total query time: 1 msec;; FROM: max.fictional.attacker to SERVER: localhost 127.0.0.1;; WHEN: Sun Nov 12 00:17:08 2000;; MSG SIZE sent: 33 rcvd: 69
คุณมีทางเลือกหนึ่งในสองทางดังต่อไปนี้คือ:
* เอา record ของ HINFO และ TXT ออกจากไฟล์ที่เกี่ยวกับ zone หรือ* เซ็ต DNS เป็นแบบ Split Horizon DNS
ทางเลือกหลังหมายถึงการทำ name server สองชุด ชุดแรกอยู่หลังไฟร์วอล อีกชุดหนึ่งอยู่ข้างนอกโดยใช้ Network Address Translation (NAT) ที่อยู่ภายในเน็ตเวิร์ค ชุดที่อยู่ภายในเน็ตเวิร์คใช้เหมือนกับ ชุดที่อยู่ภายนอกเน็ตเวิร์คแต่ชุดที่อยู่ภายในให้ข้อมูลทุกอย่างรวมทั้ง TXT และ HINFO ในขณะที่ชุดที่อยู่ภายนอกจะให้ข้อมูลที่จำกัดมากโดยจะไม่ให้ข้อมูลแทบทุกอย่างที่เกี่ยวกับเครื่องที่อยู่ภายในเน็ตเวิร์ค เนื่องจาก NAT ทำให้ดูเหมือนกับว่าเน็ตเวิร์คภายในมีเพียงเครื่องเดียว
การทำ Split Horizon DNS เป็นงานที่ต้องใช้เวลามาก แต่จะประหยัดเวลาสำหรับการทำโครงการที่เกี่ยวกับ DNS ที่สำคัญโครงการต่อไป ในตอนนี้ให้ระมัดระวังเกี่ยวกับ record ของ HINFO/TXT ให้มากและใช้หลักการให้ข้อมูลสู่ภายนอกให้น้อยที่สุดและให้ข้อมูลสู่ผู้ใช้ในสิ่งที่เขาต้องการจริง ๆ ไม่ควรตั้งชื่อของผู้ดูแลระบบว่า admin อาจเรียกใหม่ในชื่อ overlord
การ crack name server ของคุณเราได้แก้ไขช่องโหว่ที่เกี่ยวกับการให้ข้อมูลที่มากเกินไปแล้ว อย่างไรก็ตาม DNS server ที่ใช้ BIND เองยังมีช่องโหว่ทางด้านการรักษาความปลอดภัยอยู่เรื่อย ๆ เช่น BIND เวอร์ชัน 8.2 - 8.22 ที่ยังไม่ได้แก้ไขช่องโหว่มีช่องโหว่ที่สามารถใช้เพื่อให้ได้สิทธิ์ของ root จากเซิร์ฟเวอร์อื่นได้ คุณสามารถอ่านรายละเอียดได้ที่นี่
script kiddies (ผู้ซึ่งนำสคริปต์ที่ผู้อื่นเขียนขึ้นมาใช้เพื่อการบุกรุกสู่ระบบ) จำนวนมากจะสแกนโฮสต์ในอินเตอร์เน็ตจำนวนมากเพื่อหา BIND เวอร์ชันที่มีช่องโหว่ ดังต่อไปนี้:
[jay@max bog]$ dig @dumb.target.jay dumb.target.jaytxt chaos version.bind; <<>> DiG 8.2 <<>> @dumb.target.jay dumb.target.jaytxt chaos version.bind; (1 server found);; res options: init recurs defnam dnsrch;; got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1,AUTHORITY: 0, ADDITIONAL: 0;; QUERY SECTION:;; version.bind, type = TXT, class = CHAOS;; ANSWER SECTION:VERSION.BIND. 0S CHAOS TXT "8.2.2";; Total query time: 1 msec;; FROM: max.fictional.attacker toSERVER: dumb.target.jay 192.168.1.85;; WHEN: Mon Oct 20 18:30:05 2000;; MSG SIZE sent: 30 rcvd: 63[jay@max bog]$
จะเห็นได้ว่า BIND บอกเวอร์ชันและมันก็มีช่องโหว่เสียด้วย มันมีผลเสียอย่างร้ายแรงที่ script kiddie จงใจสแกนโฮสต์ในอินเตอร์เน็ตเพื่อหา BIND เวอร์ชันที่มีช่องโหว่ พวกเขาอาจดาวน์โหลด perl script ที่ยาวเพียงสามบรรทัดเพื่อที่จะสแกนหา name server ที่มีช่องโหว่นี้ พวกเขาสามารถหาเซิร์ฟเวอร์ของเราเจอได้ นอกจากนี้ ถ้า cracker ที่มีความชำนาญกำลังหาข้อมูลเกี่ยวกับคอมพิวเตอร์ของเรา เขาต้องการรู้ว่าเรามีname server ที่มีช่องโหว่หรือไม่ เขาสามารถหาข้อมูลนั้นโดยไม่ให้ผู้ดูแลระบบรู้ได้ด้วย ปกปิดเวอร์ชันของ BIND ของ cracker และสคริปต์ของพวกเขา:แก้ไขช่องโหว่ รันโดยยูสเซอร์ที่ไม่ใช่ rootโชคดีที่เราสามารถเปลี่ยนข้อความที่มากับ name server ได้โดยเพิ่มเติมลงไปในไฟล์ /etc/named.confในส่วนของ options ดังต่อไปนี้:
options {directory "/var/named";allow-transfer { 192.168.1.30; 10.1.1.4; };allow-query { 192.168.1.0/24; };version "Go away!";};
คุณอาจเปลี่ยนเป็นข้อความเป็น "10.0.0" เพื่อให้ดูก้าวร้าวน้อยลง หรือ "4.9.7" เพื่อให้เขาเลิกยุ่งกับเซิร์ฟเวอร์
การใช้มาตรการนี้คุณควรแก้ไขช่องโหว่ของ name server ของคุณอย่างสม่ำเสมอ ถึงแม้จะทำเช่นนี้แล้วแต่คุณก็อาจมีช่องโหว่อีกคือ DNS server ส่วนมากจะรันโดย root ซึ่งเปิดให้มีการได้สิทธิ์ของ rootจากเซิร์ฟเวอร์อื่นในระหว่างช่วงเวลาที่มีการค้นพบช่องโหว่และการแก้ไขช่องโหว่ ในระหว่างนี้สิ่งเดียวที่ช่วยได้คือทำให้การรักษาความปลอดภัยของ name server เข้มแข็งยิ่งขึ้น อับดับแรกที่ต้องทำซึ่งทำได้ง่ายคือให้BIND รันโดยยูสเซอร์อื่น ถ้าไม่ใช่ root ที่รัน BIND คุณสามารถหาได้โดยพิมพ์ดังต่อไปนี้:
[jay@max jay]$ ps -ef grep namednamed 9179 1 0 12:15 ? 00:00:00 named -u named
คอลัมน์แรกแสดงชื่อยูสเซอร์ที่รัน BIND เครื่องที่ผมใช้ทดสอบคือ Mandrake 7.1 โปรแกรม namedของ BIND รันโดยยูสเซอร์ named ถ้าคุณใช้ระบบปฏิบัติการที่แสดงให้เห็นว่า named รันโดย rootให้หาสคริปต์เริ่มต้น(init script) ที่เริ่มการทำงานของ named แล้วจึงแก้ไขให้ใช้ flag -u และ -g ดังต่อไปนี้:
/usr/sbin/named -u dns_user -g dns_group
คุณจำเป็นต้องสร้างยูสเซอร์ dns_user และกลุ่ม dns_group โดยคุณจะใช้ชื่ออะไรก็ได้ที่ต้องการMandrakeSoft ใช้ยูสเซอร์ named และกลุ่ม root ส่วนผมเลือกเอายูสเซอร์ bob และกลุ่ม lessเพื่อไม่ให้ยูสเซอร์อื่นและcracker สงสัย ในกรณีใด ๆ ก็ตามให้ใช้ทั้งสอง flag นอกจากนี้ยูสเซอร์ที่สร้างมานี้ควรปิดการใช้งานจาก shell เช่น /bin/false และควรมี home directory เป็น /var/named หรืออะไรก็ตามที่เป็นไดเร็กทอรีของ DNS
ขั้นตอนง่าย ๆ เหล่านี้จะป้องกันจากการได้สิทธิ์ของ root จากเซิร์ฟเวอร์อื่น (remote root exploit) ในname server ที่ใช้ BIND 8.2 - 8.22 ซึ่งป้องกันได้เพียงไม่ไห้ script kiddie ใช้ shell ได้ และพวกเขาจำเป็นต้องพยายามเพิ่มเติมเพื่อให้ได้สิทธิ์ของ root วิธีนี้สามารถหยุดการโจมตีจาก script kiddie เท่านั้น ถ้าป้องกันจากการโจมตีขั้นสูงแล้วต้องใช้อีกวิธีหนึ่ง
เทคนิคขั้นสูง: chroot the server
เราสามารถตีวงเซิร์ฟเวอร์ให้รันอยู่ในสภาวะ chroot ได้ซึ่งจะจำกัดให้เซิร์ฟเวอร์สามารถเข้าถึงได้เพียงส่วนย่อยของ filesystem เท่านั้น มักจะเป็น /home/dns หรือ /chroot/dns โมดูล DNS.pm ของBastille Linux สามารถ chroot DNS server จากระบบของ Red Hat 6.0-6.2 ซึ่งรายละเอียดอยู่ในเว็ปไซต์ของผู้เขียน http://www.bastille-linux.org/jay มีรายละเอียดเกี่ยวกับ chroot ที่นั่นด้วย

0 ความคิดเห็น: