Apache Cassandra – cassandra-brute.nse – Nmap Script

Posted on Posted in Nmap - Script

Welcome to Apache Cassandra ™

The Apache Cassandra database is the right choice when you need scalability and high availability without compromising performance. Linear scalability and proven fault-tolerance on commodity hardware or cloud infrastructure make it the perfect platform for mission-critical data. Cassandra’s support for replicating across multiple datacenters is best-in-class, providing lower latency for your users and the peace of mind of knowing that you can survive regional outages.

cassandra

Cassandra’s data model offers the convenience of column indexes with the performance of log-structured updates, strong support for denormalization and materialized views, and powerful built-in caching.

Nmap Script:

local bin = require "bin"
local brute = require "brute"
local creds = require "creds"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local cassandra = require "cassandra"

description = [[
Performs brute force password auditing against the Cassandra database.

For more information about Cassandra, see:
http://cassandra.apache.org/
]]

---
-- @usage
-- nmap -p 9160 <ip> --script=cassandra-brute
--
-- @output
-- PORT     STATE SERVICE VERSION
-- 9160/tcp open  apani1?
-- | cassandra-brute: 
-- |   Accounts
-- |     admin:lover - Valid credentials
-- |   Statistics
-- |_    Performed 4581 guesses in 1 seconds, average tps: 4581
--

author = "Vlatko Kosturjak"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}

portrule = shortport.port_or_service({9160}, {"cassandra"})

Driver = {
  
  new = function(self, host, port, options)
    local o = { host = host, port = port, socket = nmap.new_socket() }
    setmetatable(o, self)
    self.__index = self
    return o
  end,
  
  connect = function(self)
    return self.socket:connect(self.host, self.port)
  end,

        -- bit faster login function than in cassandra library (no protocol error checks)
  login = function(self, username, password)
    local response, magic, size, _
    local loginstr = cassandra.loginstr (username, password)

    local status, err = self.socket:send(bin.pack(">I",string.len(loginstr)))
                local combo = username..":"..password
    if ( not(status) ) then
      local err = brute.Error:new( "couldn't send length:"..combo )
      err:setAbort( true )
      return false, err
    end

    status, err = self.socket:send(loginstr)
    if ( not(status) ) then
      local err = brute.Error:new( "couldn't send login packet: "..combo )
      err:setAbort( true )
      return false, err
    end

    status, response = self.socket:receive_bytes(22)
    if ( not(status) ) then
      local err = brute.Error:new( "couldn't receive login reply size: "..combo )
      err:setAbort( true )
      return false, err
    end
      
    _, size = bin.unpack(">I", response, 1)

                magic = string.sub(response,18,22)

    if (magic == cassandra.LOGINSUCC) then
                        stdnse.print_debug(3, "Account SUCCESS: "..combo)
      return true, brute.Account:new(username, password, creds.State.VALID)
    elseif (magic == cassandra.LOGINFAIL) then
                        stdnse.print_debug(3,"Account FAIL: "..combo)
      return false, brute.Error:new( "Incorrect password" )	
                elseif (magic == cassandra.LOGINACC) then
                        stdnse.print_debug(3, "Account VALID, but wrong password: "..combo)
                        return false, brute.Error:new( "Good user, bad password" )	
    else
                        stdnse.print_debug(3, "Unrecognized packet for "..combo)
                        stdnse.print_debug(3, "packet hex: %s", stdnse.tohex(response) )
                        stdnse.print_debug(3, "size packet hex: %s", stdnse.tohex(size) )
                        stdnse.print_debug(3, "magic packet hex: %s", stdnse.tohex(magic) )
      local err = brute.Error:new( response )
      err:setRetry( true )
      return false, err
    end	
  end,
  
  disconnect = function(self)
    return self.socket:close()
  end,
  
}

local function noAuth(host, port)
  local socket = nmap.new_socket()
  local status, result = socket:connect(host, port)

        local stat,err = cassandra.login (socket,"default","")
        socket:close()
        if (stat) then
          return true
        else
          return false
        end
end

action = function(host, port)

  if ( noAuth(host, port) ) then
    return "Any username and password would do, 'default' was used to test."
  end

  local engine = brute.Engine:new(Driver, host, port )
  
  engine.options.script_name = SCRIPT_NAME
  engine.options.firstonly = true
  local status, result = engine:start()

  return result
end
Facebooktwittergoogle_plus