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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
local nmap = require "nmap"
local pgsql = require "pgsql"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local unpwdb = require "unpwdb"
local openssl = stdnse.silent_require "openssl"
description = [[
Performs password guessing against PostgreSQL.
]]
---
-- @usage
-- nmap -p 5432 --script pgsql-brute <host>
--
-- @output
-- 5432/tcp open pgsql
-- | pgsql-brute:
-- | root:<empty> => Valid credentials
-- |_ test:test => Valid credentials
--
-- @args pgsql.nossl If set to <code>1</code> or <code>true</code>, disables SSL.
-- @args pgsql.version Force protocol version 2 or 3.
-- SSL Encryption
-- --------------
-- We need to handle several cases of SSL support
-- o SSL can be supported on a server level
-- o SSL can be enforced per host or network level
-- o SSL can be denied per host or network level
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
-- Version 0.4
-- Created 01/15/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
-- Revised 02/20/2010 - v0.2 - moved version detection to pgsql library
-- Revised 03/04/2010 - v0.3 - added code from ssh-hostkey.nse to check for SSL support
-- - added support for trusted authentication method
-- Revised 09/10/2011 - v0.4 - changed account status text to be more consistent with other *-brute scripts
portrule = shortport.port_or_service(5432, "postgresql")
--- Connect a socket to the server with or without SSL
--
-- @param host table as received by the action function
-- @param port table as received by the action function
-- @param ssl boolean, if true connect using SSL
-- @return socket connected to server
local function connectSocket(host, port, ssl)
local socket = nmap.new_socket()
-- set a reasonable timeout value
socket:set_timeout(5000)
socket:connect(host, port)
-- let's be responsible and avoid sending communication in the clear
if ( ssl ) then
local status = pgsql.requestSSL(socket)
if ( status ) then
socket:reconnect_ssl()
end
end
return socket
end
action = function( host, port )
local status, response, ssl_enable, output
local result, response, status, nossl = {}, nil, nil, false
local valid_accounts = {}
local pg
if ( nmap.registry.args['pgsql.version'] ) then
if ( tonumber(nmap.registry.args['pgsql.version']) == 2 ) then
pg = pgsql.v2
elseif ( tonumber(nmap.registry.args['pgsql.version']) == 3 ) then
pg = pgsql.v3
else
stdnse.debug1("Unsupported version %s", nmap.registry.args['pgsql.version'])
return
end
else
pg = pgsql.detectVersion(host, port )
end
local usernames, passwords
status, usernames = unpwdb.usernames()
if not status then
return stdnse.format_output(false, usernames)
end
status, passwords = unpwdb.passwords()
if not status then
return stdnse.format_output(false, passwords)
end
-- If the user explicitly does not disable SSL, enforce it
if ( ( nmap.registry.args['pgsql.nossl'] == 'true' ) or
( nmap.registry.args['pgsql.nossl'] == '1' ) ) then
nossl = true
end
for username in usernames do
ssl_enable = not(nossl)
for password in passwords do
stdnse.debug1("Trying %s/%s ...", username, password )
local socket = connectSocket( host, port, ssl_enable )
status, response = pg.sendStartup(socket, username, username)
-- if nossl is enforced by the user, we're done
if ( not(status) and nossl ) then
break
end
-- SSL failed, this can occur due to:
-- 1. The server does not do SSL
-- 2. SSL was denied on a per host or network level
--
-- Attempt SSL connection
if ( not(status) ) then
socket:close()
ssl_enable = false
socket = connectSocket( host, port, ssl_enable )
status, response = pg.sendStartup(socket, username, username)
if (not(status)) then
if ( response:match("no pg_hba.conf entry for host") ) then
stdnse.debug1("The host was denied access to db \"%s\" as user \"%s\", aborting ...", username, username )
break
else
stdnse.debug1("sendStartup returned: %s", response )
break
end
end
end
-- Do not attempt to authenticate if authentication type is trusted
if ( response.authtype ~= pgsql.AuthenticationType.Success ) then
status, response = pg.loginRequest( socket, response, username, password, response.salt)
end
if status then
-- Add credentials for other pgsql scripts to use
if nmap.registry.pgsqlusers == nil then
nmap.registry.pgsqlusers = {}
end
nmap.registry.pgsqlusers[username]=password
if ( response.authtype ~= pgsql.AuthenticationType.Success ) then
table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "<empty>" ) )
else
table.insert( valid_accounts, string.format("%s => Trusted authentication", username ) )
end
break
end
socket:close()
end
passwords("reset")
end
output = stdnse.format_output(true, valid_accounts)
return output
end
|