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

posted on 04 Oct 2005 14:46 by keztudio in Tutorial

เรามักจะใช้ 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]$ nslookup
Default Server: ns.my.isp
Address: 10.0.0.1
> set q=ns
> dumb.target.jay
Server: ns.my.isp
Address: 10.0.0.1
Non-authoritative answer:
dumb.target.jay nameserver = dumb.target.jay
dumb.target.jay nameserver = ns2.dumb.target.jay
Authoritative 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 ; serial
5H ; refresh
1H ; retry
4d4h ; expire
1D ) ; minimum
1H IN NS dumb.target.jay.
20H IN NS ns.dumb.target.jay.
20H IN NS ns.dumbs.isp.
20H IN A 192.168.1.85
1D IN HINFO "Pentium 133" "Red Hat 6.1"
1D IN MX 10 mail
mail 1D IN A 192.168.1.2
really 1D IN A 192.168.1.20
1D IN TXT "Admin's Trusted Workstation"
1D IN HINFO "Athlon 850" "Red Hat 6.1"
rather 1D IN A 192.168.1.15
1D IN HINFO "Pentium 266" "Mandrake 7.1"
serious 1D IN CNAME extra
extra 1D IN A 192.168.1.80
ns 1D IN A 192.168.1.30
r_g 1D IN A 192.168.1.68
roblimo 1D IN MX 10 r_g
1D IN A 192.168.1.44
tahara 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 แต่ละโฮสต์จะสอบถาม name server ถึง 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.jay
txt chaos version.bind
; <<>> DiG 8.2 <<>> @dumb.target.jay dumb.target.jay
txt 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 to
SERVER: 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 named
named 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 เท่านั้น ถ้าป้องกันจากการโจมตีขั้นสูงแล้วต้องใช้อีกวิธีหนึ่ง

Comment

Comment:

Tweet

กำลังค้นหาว่า ทำไม username ถึงมีการเข้าใชซ้ำซ้อนได้

#1 By tuktuk (202.129.8.186) on 2008-12-24 21:46