1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
local brute = require "brute"
local creds = require "creds"
local shortport = require "shortport"
local stdnse = require "stdnse"
local ftp = require "ftp"
description = [[
Performs brute force password auditing against FTP servers.
Based on old ftp-brute.nse script by Diman Todorov, Vlatko Kosturjak and Ron Bowes.
]]
---
-- @see ftp-anon.nse
--
-- @usage
-- nmap --script ftp-brute -p 21 <host>
--
-- This script uses brute library to perform password
-- guessing.
--
-- @output
-- PORT STATE SERVICE
-- 21/tcp open ftp
-- | ftp-brute:
-- | Accounts
-- | root:root - Valid credentials
-- | Statistics
-- |_ Performed 510 guesses in 610 seconds, average tps: 0
--
-- @args ftp-brute.timeout the amount of time to wait for a response on the socket.
-- Lowering this value may result in a higher throughput for servers
-- having a delayed response on incorrect login attempts. (default: 5s)
-- 06.08.16 - Modified by Sergey Khegay to support new brute.lua adaptability mechanism.
author = "Aleksandar Nikolic"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
portrule = shortport.port_or_service(21, "ftp")
local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
arg_timeout = (arg_timeout or 5) * 1000
Driver = {
new = function(self, host, port)
local o = {}
setmetatable(o, self)
self.__index = self
o.host = host
o.port = port
return o
end,
connect = function( self )
self.socket = brute.new_socket()
-- discard buffer, we'll create a new one over the BruteSocket later
local realsocket, code, message, buffer = ftp.connect(self.host, self.port, {request_timeout=arg_timeout})
if not realsocket then
return false, brute.Error:new( "Couldn't connect to host: " .. (code or message) )
end
self.socket.socket = realsocket
return true
end,
login = function (self, user, pass)
local buffer = stdnse.make_buffer(self.socket, "\r?\n")
local status, code, message = ftp.auth(self.socket, buffer, user, pass)
if not status then
if not code then
return false, brute.Error:new("socket error during login: " .. message)
elseif code == 530 then
return false, brute.Error:new( "Incorrect password" )
elseif code == 421 then
local err = brute.Error:new("Too many connections")
err:setReduce(true)
return false, err
else
stdnse.debug1("WARNING: Unhandled response: %d %s", code, message)
local err = brute.Error:new("Unhandled response")
err:setRetry(true)
return false, err
end
end
stdnse.debug1("Successful login: %s/%s", user, pass)
return true, creds.Account:new( user, pass, creds.State.VALID)
end,
disconnect = function( self )
ftp.close(self.socket)
return true
end
}
action = function( host, port )
local status, result
local engine = brute.Engine:new(Driver, host, port)
engine.options.script_name = SCRIPT_NAME
status, result = engine:start()
return result
end
|