Nmap Development mailing list archives
[NSE] NSE HTTP library
From: Sven Klemm <sven () c3d2 de>
Date: Wed, 16 Jan 2008 22:57:16 +0100
I've written a HTTP library for NSE in lua. I implemented the following 3 functions so far: http.get( host, port, path ), http.request( host, port, request ) and http.get_url( url ). The host parameter may either be a string or table. The port parameter may either be a number or a table. This means you can directly pass the host or port tables you get from nmap into these functions. The return value of the functions is a table with the following structure: {status = 200, header = {}, body ="<html>...</html>"} The header table has an entry for each received header with the header name being the key. Status is the HTTP Status code of the request. In case of an error status is nil. body is a string containing the body of the request. The library supports http as well as https. I've also attached a sample script that checks for publicly accessible svn-Metadata that demonstrates the usage. It would be really cool if this could be integrated into nmap. Cheers, Sven -- Sven Klemm http://cthulhu.c3d2.de/~sven/
-- See nmaps COPYING for licence module(...,package.seeall) require 'stdnse' require 'url' -- -- http.get( host, port, path ) -- http.request( host, port, request ) -- http.get_url( url ) -- -- host may either be a string or table -- port may either be a number or a table -- -- the format of the return value is a table with the following structure: -- {status = 200, header = {}, body ="<html>...</html>"} -- the header table has an entry for each received header with the header name being the key -- table also has an entry named "status" which contains the http status code of the request -- in case of an error status is nil -- fetch relative URL with get request get = function( host, port, path ) local hostname = host if type(host) == 'table' then hostname = ( host.name ~= '' and host.name ) or host.ip end local data data = "GET "..path.." HTTP/1.1\r\n" data = data .. "Host: "..hostname.."\r\n" data = data .. "User-Agent: Nmap NSE\r\n" data = data .. "Connection: close\r\n\r\n" return http.request( host, port, data ) end -- URL with get request get_url = function( u ) local parsed = url.parse( u ) local port = {} port.service = parsed.scheme port.number = parsed.port if not port.number then if parsed.scheme == 'https' then port.number = 443 else port.number = 80 end end local path = parsed.path or "/" if parsed.query then path = path .. "?" .. parsed.query end return get( parsed.host, port, path ) end -- send http request and return the result as table -- host may be a table or the hostname -- port may be a table or the portnumber request = function( host, port, data ) if type(host) == 'table' then host = ( host.name ~= '' and host.name ) or host.ip end local protocol = 'tcp' if type(port) == 'table' then if nmap.have_ssl() and ( port.service == 'https' or ( port.version and port.version.service_tunnel == 'ssl' ) ) then protocol = 'ssl' end port = port.number end socket = nmap.new_socket() socket:connect( host, port, protocol ) socket:send( data ) local buffer = stdnse.make_buffer( socket, "\r?\n" ) local status, line, result local header, body = {}, {} -- header loop while true do status, line = buffer() if (not status or line == "") then break end table.insert(header,line) end result = {status=nil,header={},body=""} -- build nicer table for header for key, value in pairs( header ) do if key == 1 then local code _, _, code = string.find( value, "HTTP/%d\.%d (%d+)") result.status = tonumber(code) else _, _, key, value = string.find( value, "(.+): (.*)" ) if key and value then result.header[key] = value:gsub( '[\r\n]+', '' ) end end end -- body loop while true do status, line = buffer() if (not status) then break end table.insert(body,line) end socket:close() result.body = table.concat( body ) return result end
id = ".svn/entries" description = "checks for accessable svn metadata" author = "Sven Klemm <sven () c3d2 de>" license = "See nmaps COPYING for licence" categories = {"safe","discovery"} require "shortport" require "http" portrule = shortport.port_or_service({80,443},{'http','https','http-proxy'}) action = function(host, port) local answer = http.get( host, port, "/.svn/entries" ) if answer.status == 200 and not answer.body:match('<html') then return "Readable subversion metadata" end end
Attachment:
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [NSE] NSE HTTP library Sven Klemm (Jan 16)
- Re: [NSE] NSE HTTP library Kris Katterjohn (Jan 16)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 17)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 18)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 18)
- RE: [NSE] NSE HTTP library Thomas Buchanan (Jan 18)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 18)
- Re: [NSE] NSE HTTP library Thomas Buchanan (Jan 19)
- RE: [NSE] NSE HTTP library Thomas Buchanan (Jan 19)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 20)
- Re: [NSE] NSE HTTP library Fyodor (Jan 31)
- Re: [NSE] NSE HTTP library Sven Klemm (Jan 17)
- Re: [NSE] NSE HTTP library Kris Katterjohn (Jan 16)