diff --git a/CHANGELOG b/CHANGELOG index 1bed409f7..564c6b4a9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,11 @@ # Nmap Changelog ($Id$); -*-text-*- -o [NSE] Added the script redis-info that lists version and statistic information - gathered from the Redis network key-value store. [Patrik] +o [NSE] Added the script memcached-info that lists version and statistics + information from the distributed memory object caching service memcached + [Patrik] + +o [NSE] Added the script redis-info that lists version and statistic + information gathered from the Redis network key-value store. [Patrik] o [NSE] Added the script redis-brute that performs brute force password guessing against the Redis network key-value store. [Patrik] diff --git a/scripts/memcached-info.nse b/scripts/memcached-info.nse new file mode 100644 index 000000000..09e8db144 --- /dev/null +++ b/scripts/memcached-info.nse @@ -0,0 +1,125 @@ +description = [[ +Retrieves information from distributed memory object caching system memcached +]] + +--- +-- @usage +-- nmap -p 11211 --script memcached-info +-- +-- @output +-- 11211/tcp open unknown +-- | memcached-info: +-- | Process ID 18568 +-- | Uptime 6950 seconds +-- | Server time Sat Dec 31 14:16:10 2011 +-- | Architecture 64 bit +-- | Used CPU (user) 0.172010 +-- | Used CPU (system) 0.200012 +-- | Current connections 10 +-- | Total connections 78 +-- | Maximum connections 1024 +-- | TCP Port 11211 +-- | UDP Port 11211 +-- |_ Authentication no +-- + +author = "Patrik Karlsson" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"discovery", "safe"} + +require 'shortport' +require 'tab' + +-- currently, we only support the TCP, text based protocol +portrule = shortport.port_or_service(11211, "memcached", "tcp") + +local filter = { + + ["pid"] = { name = "Process ID" }, + ["uptime"] = { name = "Uptime", func = function(v) return ("%d seconds"):format(v) end }, + ["time"] = { name = "Server time", func = function(v) return os.date("%c", v) end }, + ["pointer_size"] = { name = "Architecture", func = function(v) return v .. " bit" end }, + ["rusage_user"] = { name = "Used CPU (user)" }, + ["rusage_system"] = { name = "Used CPU (system)"}, + ["curr_connections"] = { name = "Current connections"}, + ["total_connections"] = { name = "Total connections"}, + ["maxconns"] = { name = "Maximum connections" }, + ["tcpport"] = { name = "TCP Port" }, + ["udpport"] = { name = "UDP Port" }, + ["auth_enabled_sasl"] = { name = "Authentication" } + +} + +local order = { + "pid", "uptime", "time", "pointer_size", "rusage_user", "rusage_system", + "curr_connections", "total_connections", "maxconns", "tcpport", "udpport", + "auth_enabled_sasl" +} + +local function fail(err) return ("\n ERROR: %s"):format(err) end + +local function mergetab(tab1, tab2) + for k, v in pairs(tab2) do + tab1[k] = v + end + return tab1 +end + +local function recvResponse(socket) + local kvs = {} + repeat + local status, response = socket:receive_buf("\r\n") + if ( not(status) ) then + return false, "Failed to receive response from server" + end + local k,v = response:match("^STAT ([^%s]*) (.*)$") + if ( k and v ) then + kvs[k] = v + end + until ( "END" == response or "ERROR" == response ) + + return true, kvs +end + +action = function(host, port) + + local socket = nmap.new_socket() + socket:set_timeout(10000) + local status = socket:connect(host, port) + if ( not(status) ) then + return fail("Failed to connect to server") + end + + status = socket:send("stats\r\n") + if ( not(status) ) then + return fail("Failed to send request to server") + end + + local status, kvs = recvResponse(socket) + if( not(status) ) then + return fail(kvs) + end + + status = socket:send("stats settings\r\n") + if ( not(status) ) then + return fail("Failed to send request to server") + end + + local status, kvs2 = recvResponse(socket) + if( not(status) ) then + return fail(kvs2) + end + + kvs = mergetab(kvs, kvs2) + + local result = tab.new(2) + for _, item in ipairs(order) do + if ( kvs[item] ) then + local name = filter[item].name + local val = ( filter[item].func and filter[item].func(kvs[item]) or kvs[item] ) + tab.addrow(result, name, val) + end + end + return stdnse.format_output(true, tab.dump(result)) + +end \ No newline at end of file diff --git a/scripts/script.db b/scripts/script.db index 45942db13..5d0194a13 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -162,6 +162,7 @@ Entry { filename = "ldap-search.nse", categories = { "discovery", "safe", } } Entry { filename = "lexmark-config.nse", categories = { "discovery", "safe", } } Entry { filename = "lltd-discovery.nse", categories = { "broadcast", "discovery", "safe", } } Entry { filename = "maxdb-info.nse", categories = { "default", "version", } } +Entry { filename = "memcached-info.nse", categories = { "discovery", "safe", } } Entry { filename = "metasploit-xmlrpc-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } } Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }