Nmap Development mailing list archives
Re: autonomous system numbers NSE script
From: jah <jah () zadkiel plus com>
Date: Thu, 19 Jun 2008 01:56:26 +0100
On 18/06/2008 01:40, Michael Pattrick wrote:
Hey everyone, I wrote this script to find autonomous system numbers using the method described here [1]. But there are two problems: - A query will return the same ASN if its in the same BGP netblock. My script also discovers the BGP netblock, is there any way to cache results in this case - ie check if the IP fits into a netblock that we've already scanned? - The website states that the the best way is the DNS method, and hosts making too many whois queries will be blocked, is there a way to forge DNS query packets in NSE or would there need to be some kind of DNS API? I tried making the raw packet in a lua script and ssending it out but wireshark claimed that the packet was malformed :(
<snip>
[1] http://www.team-cymru.org/Services/ip-to-asn.html
Hi Michael, As Kris said, I've had the same requirement for whois.nse. In that script, it deals with quite a lot of information and so the goal was to have a single host result showing the whois record and other hosts in the same range to return "See the results for x.x.x.x" to avoid repeating the same results over and over. On the basis that your script doesn't show a lot of data, you might get a way with repeating the same ASN info for each target in that block and this is quite easy to do using mutex and the registry. I've attached a very rough script that will a) do the dns method. This required some reading of RFC 1035 (and specifically Section 4.1.2. - QNAME) to get a non-malformed query (a good exercise though, I enjoyed it) and b) cache results to prevent multiple queries for the same netblock using the registry and a mutex and which you might find useful. There are two caveats: 1) I haven't worked out how to get information about which dns server to use and so --script-args dns=some.dns.server is required to get this script to run. 2) The method by which the script reads the dns response is very shaky indeed. It finds end of the original query in the answer and fetches everything after 13 bytes further on - it works, but I can't imagine it will always work... Does anyone have any idea how to get ones dns server for a use in a script? Finally, it occurs to me that ASN numbers might be integrated into whois.nse since it ought to be possible to get route information from the Regional Internet Registries. Ripe certainly serves-up route info as part of an IP address lookup, but at the moment I don't know if any of the others do. It might be worth looking into this possibility in either case. Regards, jah
id = "ASN" description = "nmap <target> --script asn --script-args dns=<recursion_enabled_dns_server>" require "comm" require "ipOps" hostrule = function( host ) return true end if not nmap.registry.asn then nmap.registry.asn = {} nmap.registry.asn.cache = {} end local mutex = nmap.mutex( id ) action = function( host ) -- get args or die local dns_server if nmap.registry.args.dns then dns_server = nmap.registry.args.dns else return end -- wait mutex "lock" -- check for cached data for _, cache in ipairs( nmap.registry.asn.cache ) do if ip_in_net( host.ip, cache.bgp) then mutex "done" return " \nBGP Prefix: " .. cache.bgp .. "\nAS number: " .. cache.asn .. "\nCountry Code: " .. cache.co_id end end -- format data local t = {} t[4], t[3], t[2], t[1] = host.ip:match( "([^\.]*)\.([^\.]*)\.([^\.]*)\.([^\.]*)" ) local tsoh = labels( t ) local z = { "origin", "asn", "cymru", "com" } local zone = labels( z ) local t_id = string.char( tonumber( t[2] ), tonumber( t[3] ) ) -- not at all random... local dns_std = string.char( 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) local null_char = string.char( 0x00 ) local qtype = string.char( 0x00, 0x10 ) local qclass = string.char( 0x00, 0x01 ) local query = tsoh .. zone .. null_char .. qtype .. qclass local data = t_id .. dns_std .. query -- send data local options = {} options.proto = "udp" options.lines = 1 options.timeout = 1000 local status, result = comm.exchange( dns_server, 53, data, options ) if not status then mutex "done" return end -- read result - this method is tenuous!! local _, offset = string.find( result, query ) local line = string.sub( result, offset + 13 ) fields = {line:match( ("([^|]*)|"):rep(3) )} -- cache result local blob = {} blob.bgp = fields[2]:gsub( "^%s*(.-)%s*$", "%1" ) blob.asn = fields[1]:gsub( "^%s*[^0](.-)%s*$", "%1" ) blob.co_id = fields[3]:gsub( "^%s*(.-)%s*$", "%1" ) table.insert( nmap.registry.asn.cache, blob ) mutex "done" -- return result return " \nBGP Prefix: " .. blob.bgp .. "\nAS number: " .. blob.asn .. "\nCountry Code: " .. blob.co_id end -- labels -- given a table of strings, return a string made up of concateneted labels -- where each label consists of a length value (cast as char) followed by that number of characters. function labels( t ) local ret = "" for _, v in ipairs(t) do ret = ret .. string.char( string.len(v) ) .. v end return ret end -- ip_in_net -- returns true if the supplied ip address falls inside the supplied range function ip_in_net(ip, net) local i, j, net_lo, net_hi, dw_ip local m_dotted = "(%d+%.%d+%.%d+%.%d+)[%s]*[-][%s]*(%d+%.%d+%.%d+%.%d+)" local m_cidr = "(%d+)[.]*(%d*)[.]*(%d*)[.]*(%d*)[/]+(%d+)" if net:match(m_dotted) then net_lo, net_hi = net:match(m_dotted) net_lo = ipOps.todword(net_lo) net_hi = ipOps.todword(net_hi) elseif net:match(m_cidr) then net_lo, net_hi = two_dwords(net, m_cidr) end dw_ip = ipOps.todword(ip) if net_lo <= dw_ip and dw_ip <= net_hi then return true end return false end -- two_dwords -- returns the two ip addresses at either end of a cidr range, as dwords function two_dwords(str, patt) local a, b, c, d, e, lo_net, host a, b, c, d, e = str:match(patt) local ipt = {b, c, d} local strip = "" for _, cap in ipairs(ipt) do if cap == "" then cap = "0" end strip = strip .. "." .. cap end lo_net = a .. strip if e ~= "" then e = tonumber(e) if e and e <=32 then host = 32 - e end end return ipOps.todword(lo_net), ipOps.todword(lo_net) + 2^host - 1 end
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- autonomous system numbers NSE script Michael Pattrick (Jun 17)
- Re: autonomous system numbers NSE script Kris Katterjohn (Jun 17)
- Re: autonomous system numbers NSE script jah (Jun 18)
- Re: autonomous system numbers NSE script Fyodor (Jun 28)
- Re: How is whois.nse coming along? jah (Jun 29)
- Re: How is whois.nse coming along? Kris Katterjohn (Jun 29)
- Re: How is whois.nse coming along? jah (Jun 29)
- Re: How is whois.nse coming along? Patrick Donnelly (Jun 29)
- Re: autonomous system numbers NSE script Fyodor (Jun 28)