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
|
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local table = require "table"
local tns = require "tns"
local unpwdb = require "unpwdb"
local rand = require "rand"
local openssl = stdnse.silent_require "openssl"
description = [[
Attempts to enumerate valid Oracle user names against unpatched Oracle 11g
servers (this bug was fixed in Oracle's October 2009 Critical Patch Update).
]]
---
-- @usage
-- nmap --script oracle-enum-users --script-args oracle-enum-users.sid=ORCL,userdb=orausers.txt -p 1521-1560 <host>
--
-- If no userdb is supplied the default userlist is used
--
-- @output
-- PORT STATE SERVICE REASON
-- 1521/tcp open oracle syn-ack
-- | oracle-enum-users:
-- | haxxor is a valid user account
-- | noob is a valid user account
-- |_ patrik is a valid user account
--
-- @args oracle-enum-users.sid the instance against which to attempt user
-- enumeration
-- Version 0.3
-- Created 12/07/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
-- Revised 21/07/2010 - v0.2 - revised to work with patched systems <patrik>
-- Revised 21/07/2010 - v0.3 - removed references to smb in get_random_string
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "auth"}
portrule = shortport.port_or_service(1521, 'oracle-tns' )
local function checkAccount( host, port, user )
local helper = tns.Helper:new( host, port, nmap.registry.args['oracle-enum-users.sid'] )
local status, data = helper:Connect()
local tnscomm, auth
local auth_options = tns.AuthOptions:new()
if ( not(status) ) then
return false, data
end
-- A bit ugly, the helper should probably provide a getSocket function
tnscomm = tns.Comm:new( helper.tnssocket )
status, auth = tnscomm:exchTNSPacket( tns.Packet.PreAuth:new( user, auth_options, helper.os ) )
if ( not(status) ) then
return false, auth
end
helper:Close()
return true, auth["AUTH_VFR_DATA"]
end
local function fail (err) return stdnse.format_output(false, err) end
action = function( host, port )
local known_good_accounts = { "system", "sys", "dbsnmp", "scott" }
local status, salt
local count = 0
local result = {}
local usernames
if ( not( nmap.registry.args['oracle-enum-users.sid'] ) and not( nmap.registry.args['tns.sid'] ) ) then
return fail("Oracle instance not set (see oracle-enum-users.sid or tns.sid)")
end
status, usernames = unpwdb.usernames()
if( not(status) ) then
return fail("Failed to load the usernames dictionary")
end
-- Check for some known good accounts
for _, user in ipairs( known_good_accounts ) do
status, salt = checkAccount(host, port, user)
if( not(status) ) then return salt end
if ( salt ) then
count = count + #salt
end
end
-- did we atleast get a single salt back?
if ( count < 20 ) then
return fail("None of the known accounts were detected (oracle < 11g)")
end
-- Check for some known bad accounts
count = 0
for i=1, 10 do
local user = rand.random_string(10,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")
status, salt = checkAccount(host, port, user)
if( not(status) ) then return salt end
if ( salt ) then
count = count + #salt
end
end
-- It's unlikely that we hit 3 random combinations as valid users
if ( count > 60 ) then
return fail(("%d of %d random accounts were detected (Patched Oracle 11G or Oracle 11G R2)"):format(count/20, 10))
end
for user in usernames do
status, salt = checkAccount(host, port, user)
if ( not(status) ) then return salt end
if ( salt and #salt == 20 ) then
table.insert( result, ("%s is a valid user account"):format(user))
end
end
if ( #result == 0 ) then
table.insert( result, "Failed to find any valid user accounts")
end
return stdnse.format_output(true, result)
end
|