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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
local brute = require "brute"
local comm = require "comm"
local creds = require "creds"
local nmap = require "nmap"
local pop3 = require "pop3"
local shortport = require "shortport"
local string = require "string"
description = [[
Tries to log into a POP3 account by guessing usernames and passwords.
]]
---
-- @args pop3loginmethod The login method to use: <code>"USER"</code>
-- (default), <code>"SASL-PLAIN"</code>, <code>"SASL-LOGIN"</code>,
-- <code>"SASL-CRAM-MD5"</code>, or <code>"APOP"</code>. Defaults to <code>"USER"</code>,
--
-- @output
-- PORT STATE SERVICE
-- 110/tcp open pop3
-- | pop3-brute-ported:
-- | Accounts:
-- | user:pass => Login correct
-- | Statistics:
-- |_ Performed 8 scans in 1 seconds, average tps: 8
author = {"Philip Pickering", "Piotr Olma"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
Driver = {
new = function(self, host, port, login_function, is_apop)
local o = {}
setmetatable(o, self)
self.__index = self
o.port = port
o.host = host
o.login_function = login_function
o.is_apop = is_apop
return o
end,
-- Attempts to connect to the POP server
-- @return true on success
-- @return false, brute.Error object on failure
connect = function(self)
self.socket = brute.new_socket()
local opts = {timeout=10000, recv_before=true}
local best_opt, line, _
self.socket, _, best_opt, line = comm.tryssl(self.host, self.port, "" , opts)
if not self.socket then
local err = brute.Error:new("Failed to connect.")
err:setAbort(true)
return false, err
end --no connection
if not pop3.stat(line) then
local err = brute.Error:new("Failed to make a pop-connection.")
err:setAbort(true)
return false, err
end -- no pop-connection
if self.is_apop then
self.additional = string.match(line, "<[%p%w]+>") --apop challenge
end
return true
end, --connect
-- Attempts to login to the POP server
--
-- @param username string containing the login username
-- @param password string containing the login password
-- @return status, true on success, false on failure
-- @return brute.Error object on failure
-- creds.Account object on success
login = function(self, username, password)
local pstatus
local perror
pstatus, perror = self.login_function(self.socket, username, password, self.additional)
if pstatus then
return true, creds.Account:new(username, password, creds.State.VALID)
else
local err
if (perror == pop3.err.pwError) then
err = brute.Error:new("Wrong password.")
elseif (perror == pop3.err.userError) then
err = brute.Error:new("Wrong username.")
err:setInvalidAccount(username)
else
err = brute.Error:new("Login failed.")
end
return false, err
end
end, --login
disconnect = function(self)
self.socket:close()
end, --disconnect
check = function(self)
return true
end, --check
}
portrule = shortport.port_or_service({110, 995}, {"pop3","pop3s"})
action = function(host, port)
local pMeth = nmap.registry.args.pop3loginmethod
if (not pMeth) then pMeth = nmap.registry.pop3loginmethod end
if (not pMeth) then pMeth = "USER" end
--determine function we will use to login to server
local is_apop = false
local login_function
if (pMeth == "USER") then
login_function = pop3.login_user
elseif (pMeth == "SASL-PLAIN") then
login_function = pop3.login_sasl_plain
elseif (pMeth == "SASL-LOGIN") then
login_function = pop3.login_sasl_login
elseif (pMeth == "SASL-CRAM-MD5") then
login_function = pop3.login_sasl_crammd5
elseif (pMeth == "APOP") then
login_function = pop3.login_apop
is_apop = true
else
login_function = pop3.login_user
end
local engine = brute.Engine:new(Driver, host, port, login_function, is_apop)
engine.options.script_name = SCRIPT_NAME
local status, accounts = engine:start()
return accounts
end
|