1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Added support for LDAP substring searches to ldap.lua. These can now be performed alone or in conjunction with other LDAP query types.

Added a new quick filter (qfilter) to ldap-search.nse that allows the user to specify, on the command line, an attribute and corresponding value to search the LDAP directory for.  The use of the asterisk '*' as a wildcard is permitted in the value parameter.

Updated asn1.lua with some minor notes on a hex value that was used.
This commit is contained in:
tomsellers
2011-10-29 10:18:52 +00:00
parent 1b469acdae
commit bca60ba8de
3 changed files with 83 additions and 7 deletions

View File

@@ -281,7 +281,9 @@ ASN1Encoder = {
end,
---
-- Encodes an ASN1 sequence
-- Encodes an ASN1 sequence, the value of 30 below breaks down as
-- 0x30 = 00110000 = 00 1 10000
-- hex binary Universal Constructed value Data Type = SEQUENCE (16)
encodeSeq = function(self, seqData)
return bin.pack('HAA' , '30', self.encodeLength(#seqData), seqData)
end,

View File

@@ -6,12 +6,14 @@
--
-- Credit goes out to Martin Swende who provided me with the initial code that got me started writing this.
--
-- Version 0.4
-- Version 0.5
-- Created 01/12/2010 - v0.1 - Created by Patrik Karlsson <patrik@cqure.net>
-- Revised 01/28/2010 - v0.2 - Revised to fit better fit ASN.1 library
-- Revised 02/02/2010 - v0.3 - Revised to fit OO ASN.1 Library
-- Revised 09/05/2011 - v0.4 - Revised to include support for writing output to file, added decoding certain time
-- formats
-- Revised 10/29/2011 - v0.5 - Added support for performing wildcard searches via the substring filter.
--
module("ldap", package.seeall)
@@ -404,6 +406,14 @@ end
-- @param filter table containing the filter to be created
-- @return string containing the ASN1 byte sequence
function createFilter( filter )
-- In the following code the values 0x80, 0x81, 0x82 when used in the context of an
-- LDAP substring FILTER mean:
-- 0x80 = 10000000 = 10 0 00000 = 0 - match beginning of target string
-- 0x81 = 10000001 = 10 0 00001 = 1 - match any location in target string
-- 0x82 = 10000010 = 10 0 00010 = 2 - match end of target string
-- hex binary Context Specific Primitive Sequence meaning
local asn1_type = asn1.BERtoInt( asn1.BERCLASS.ContextSpecific, true, filter.op )
local filter_str = ""
@@ -413,7 +423,35 @@ function createFilter( filter )
end
else
local obj = encode( filter.obj )
local val = encode( filter.val )
local val = ''
if ( filter.op == FILTER['substrings'] ) then
local tmptable = stdnse.strsplit('*', filter.val)
local tmp_result = ''
if (#tmptable <= 1 ) then
tmp_result = bin.pack('HAA' , '81', string.char(#filter.val), filter.val)
else
for indexval, substr in ipairs(tmptable) do
if (indexval == 1) and (substr ~= '') then
tmp_result = bin.pack('HAA' , '80', string.char(#substr), substr)
end
if (indexval ~= #tmptable) and (indexval ~= 1) and (substr ~= '') then
tmp_result = tmp_result .. bin.pack('HAA' , '81', string.char(#substr), substr)
end
if (indexval == #tmptable) and (substr ~= '') then
tmp_result = tmp_result .. bin.pack('HAA' , '82', string.char(#substr), substr)
end
end
end
val = asn1.ASN1Encoder:encodeSeq( tmp_result )
else
val = encode( filter.val )
end
filter_str = filter_str .. obj .. val
end

View File

@@ -11,7 +11,10 @@ anonymous bind will be used as a last attempt.
-- @args ldap.username If set, the script will attempt to perform an LDAP bind using the username and password
-- @args ldap.password If set, used together with the username to authenticate to the LDAP server
-- @args ldap.qfilter If set, specifies a quick filter. The library does not support parsing real LDAP filters.
-- The following values are valid for the filter parameter: computer, users or all. If no value is specified it defaults to all.
-- The following values are valid for the filter parameter: computer, users,custom or all. If no value is specified it defaults to all.
-- @args ldap.searchattrib When used with the 'custom' qfilter, this parameter works in conjunction with ldap.searchvalue to allow the user to specify a custom attribute and value as search criteria.
-- @args ldap.searchvalue When used with the 'custom' qfilter, this parameter works in conjunction with ldap.searchattrib to allow the user to specify a custom attribute and value as search criteria.
-- This parameter DOES PERMIT the use of the asterisk '*' as a wildcard.
-- @args ldap.base If set, the script will use it as a base for the search. By default the defaultNamingContext is retrieved and used.
-- If no defaultNamingContext is available the script iterates over the available namingContexts
-- @args ldap.attrib If set, the search will include only the attributes specified. For a single attribute a string value can be used, if
@@ -22,8 +25,11 @@ anonymous bind will be used as a last attempt.
-- of .CSV as well as the hostname and port will automatically be added based on the output type selected.
--
-- @usage
-- nmap -p 389 --script ldap-search --script-args ldap.username="'cn=ldaptest,cn=users,dc=cqure,dc=net'",ldap.password=ldaptest,
-- ldap.qfilter=users,ldap.attrib=sAMAccountName <host>
-- nmap -p 389 --script ldap-search --script-args 'ldap.username="cn=ldaptest,cn=users,dc=cqure,dc=net",ldap.password=ldaptest,
-- ldap.qfilter=users,ldap.attrib=sAMAccountName' <host>
--
-- nmap -p 389 --script ldap-search --script-args 'ldap.username="cn=ldaptest,cn=users,dc=cqure,dc=net",ldap.password=ldaptest,
-- ldap.qfilter=custom,ldap.searchattrib="operatingSystem",ldap.searchvalue="Windows *Server*",ldap.attrib={operatingSystem,whencreated,OperatingSystemServicePack}' <host>
--
-- @output
-- PORT STATE SERVICE REASON
@@ -46,12 +52,27 @@ anonymous bind will be used as a last attempt.
-- | sAMAccountName: VMABUSEXP008$
-- | dn: CN=ldaptest,CN=Users,DC=cqure,DC=net
-- |_ sAMAccountName: ldaptest
--
--
-- PORT STATE SERVICE REASON
-- 389/tcp open ldap syn-ack
-- | ldap-search:
-- | Context: DC=cqure,DC=net; QFilter: custom; Attributes: operatingSystem,whencreated,OperatingSystemServicePack
-- | dn: CN=USDC01,OU=Domain Controllers,DC=cqure,DC=net
-- | whenCreated: 2010/08/27 17:30:16 UTC
-- | operatingSystem: Windows Server 2008 R2 Datacenter
-- | operatingSystemServicePack: Service Pack 1
-- | dn: CN=TESTBOX,OU=Test Servers,DC=cqure,DC=net
-- | whenCreated: 2010/09/04 00:33:02 UTC
-- | operatingSystem: Windows Server 2008 R2 Standard
-- |_ operatingSystemServicePack: Service Pack 1
-- Credit
-- ------
-- o Martin Swende who provided me with the initial code that got me started writing this.
-- Version 0.6
-- Version 0.7
-- Created 01/12/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
-- Revised 01/20/2010 - v0.2 - added SSL support
-- Revised 01/26/2010 - v0.3 - Changed SSL support to comm.tryssl, prefixed arguments with ldap, changes in determination of namingContexts
@@ -59,6 +80,8 @@ anonymous bind will be used as a last attempt.
-- Capped output to 20 entries, use ldap.maxObjects to override
-- Revised 07/16/2010 - v0.5 - Fixed bug with empty contexts, added objectClass person to qfilter users, add error msg for invalid credentials
-- Revised 09/05/2011 - v0.6 - Added support for saving searches to a file via argument ldap.savesearch
-- Revised 10/29/2011 - v0.7 - Added support for custom searches and the ability to leverage LDAP substring search functionality added to LDAP.lua
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
@@ -80,6 +103,8 @@ function action(host,port)
local username = stdnse.get_script_args('ldap.username')
local password = stdnse.get_script_args('ldap.password')
local qfilter = stdnse.get_script_args('ldap.qfilter')
local searchAttrib = stdnse.get_script_args('ldap.searchattrib')
local searchValue = stdnse.get_script_args('ldap.searchvalue')
local base = stdnse.get_script_args('ldap.base')
local attribs = stdnse.get_script_args('ldap.attrib')
local saveFile = stdnse.get_script_args('ldap.savesearch')
@@ -167,6 +192,17 @@ function action(host,port)
}
elseif qfilter == "computers" or qfilter == "computer" then
filter = { op=ldap.FILTER.equalityMatch, obj='objectClass', val='computer' }
elseif qfilter == "custom" then
if searchAttrib == nil or searchValue == nil then
return "\n\nERROR: Please specify both ldap.searchAttrib and ldap.searchValue using using the custom qfilter."
end
if string.find(searchValue, '*') == nil then
filter = { op=ldap.FILTER.equalityMatch, obj=searchAttrib, val=searchValue }
else
filter = { op=ldap.FILTER.substrings, obj=searchAttrib, val=searchValue }
end
elseif qfilter == "all" or qfilter == nil then
filter = nil -- { op=ldap.FILTER}
else