|
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
-
-
- from binascii import unhexlify
- from ldap3.protocol.formatters.formatters import format_sid
- import argparse
- import datetime
- import json
- import ldap3
- import logging
- import os
- import ssl
- import sys
- import hashlib
- import binascii
-
-
- ### Data utils
-
-
- def cast_to_dict(cid):
- out = {}
- for key, value in cid.items():
- if type(value) == bytes:
- out[key] = str(value)
- elif type(value) == list:
- if len(value) == 1:
- value = value[0]
- if type(value) == bytes:
- out[key] = str(value)
- elif type(value) == datetime.datetime:
- out[key] = value.strftime('%Y-%m-%d %T')
- elif type(value) == datetime.timedelta:
- # Output format to change
- out[key] = value.seconds
- else:
- out[key] = value
- else:
- newlist = []
- for element in value:
- if type(element) == bytes:
- newlist.append(str(element))
- elif type(element) == datetime.datetime:
- newlist.append(element.strftime('%Y-%m-%d %T'))
- elif type(element) == datetime.timedelta:
- # Output format to change
- newlist.append(element.seconds)
- out[key] = newlist
- elif type(value) == datetime.datetime:
- out[key] = value.strftime('%Y-%m-%d %T')
- elif type(value) == datetime.timedelta:
- # Output format to change
- out[key] = value.seconds
- else:
- out[key] = value
- return out
-
-
- def dict_get_paths(d):
- paths = []
- for key in d.keys():
- if type(d[key]) == dict:
- paths = [[key]+p for p in dict_get_paths(d[key])]
- else:
- paths.append([key])
- return paths
-
-
- def dict_path_access(d, path):
- for key in path:
- if key in d.keys():
- d = d[key]
- else:
- return None
- return d
-
-
-
- class LDAPConsole(object):
- """docstring for LDAPConsole."""
-
- def __init__(self, ldap_server, ldap_session, target_dn, debug=True):
- super(LDAPConsole, self).__init__()
- self.ldap_server = ldap_server
- self.ldap_session = ldap_session
- self.delegate_from = None
- self.target_dn = target_dn
- self.debug = debug
-
- def queryallusers(self, subtree, attributes=['*']):
- results = {}
- try:
- # https://ldap3.readthedocs.io/en/latest/searches.html#the-search-operation
- print (subtree+','+self.target_dn)
- self.ldap_session.search(subtree+','+self.target_dn, '(&(uid=*))' , attributes=attributes )
- for entry in self.ldap_session.response:
- print(entry)
-
- for entry in self.ldap_session.response:
- if entry['type'] != 'searchResEntry':
- continue
- results[entry['dn']] = entry["attributes"]
- except ldap3.core.exceptions.LDAPInvalidFilterError as e:
- print("Invalid Filter. (ldap3.core.exceptions.LDAPInvalidFilterError)")
- except Exception as e:
- raise e
- return results
-
- def doLdapLogin(self,subtree, username, password):
- results = {}
- try:
- self.ldap_session.search(subtree+','+self.target_dn, '(&(uid='+username+'))' , attributes=['ntPassword'] )
-
- for entry in self.ldap_session.response:
- if entry['type'] != 'searchResEntry':
- continue
- hash = hashlib.new('md4', password.encode('utf-16le')).digest()
- ntPassword = binascii.hexlify(hash).upper().decode("utf-8")
- #print (str(ntPassword))
- print (entry['attributes']['ntPassword'])
- results['data'] = entry["attributes"]
- if entry['attributes']['ntPassword'] == ntPassword:
- results['authen'] = "yeah"
- else:
- results['authen'] = "none"
- except ldap3.core.exceptions.LDAPInvalidFilterError as e:
- print("Invalid Filter. (ldap3.core.exceptions.LDAPInvalidFilterError)")
- except Exception as e:
- raise e
- return results
-
-
-
-
-
- def init_ldap_connection(target, tls_version, args, username, password):
- if tls_version is not None:
- use_ssl = True
- port = 636
- tls = ldap3.Tls(validate=ssl.CERT_NONE, version=tls_version)
- else:
- use_ssl = False
- port = 389
- tls = None
- ldap_server = ldap3.Server(target, get_info=ldap3.ALL, port=port, use_ssl=use_ssl, tls=tls)
- ldap_session = ldap3.Connection(ldap_server, user=username, password=password, authentication='SIMPLE',auto_bind=True)
-
-
- return ldap_server, ldap_session
-
-
- def init_ldap_session(args, username, password):
- if args.dc_ip is not None:
- target = args.dc_ip
-
- if args.use_ldaps is True:
- try:
- return init_ldap_connection(target, ssl.PROTOCOL_TLSv1_2, args, username, password )
- except ldap3.core.exceptions.LDAPSocketOpenError:
- return init_ldap_connection(target, ssl.PROTOCOL_TLSv1, args, username, password )
- else:
- return init_ldap_connection(target, None, args, username, password )
-
-
-
-
- def bytessize(data):
- l = len(data)
- units = ['B','kB','MB','GB','TB','PB']
- for k in range(len(units)):
- if l < (1024**(k+1)):
- break
- return "%4.2f %s" % (round(l/(1024**(k)),2), units[k])
-
- def parse_args():
- parser = argparse.ArgumentParser(add_help=True, description='')
- parser.add_argument('--use-ldaps', action='store_true', help='Use LDAPS instead of LDAP')
- parser.add_argument("-q", "--quiet", dest="quiet", action="store_true", default=False, help="show no information at all")
- parser.add_argument("-debug", dest="debug", action="store_true", default=False, help="Debug mode")
- parser.add_argument("-o", "--outfile", dest="jsonfile", default="ldap.json", help="Output JSON file. (default: ldap.json)")
- parser.add_argument("-b", "--base", dest="searchbase", default=None, help="Search base for LDAP query.")
-
- authconn = parser.add_argument_group('authentication & connection')
- authconn.add_argument('--dc-ip', action='store', metavar="ip address", help='IP Address of the domain controller')
- authconn.add_argument("-u", "--user", dest="auth_username", metavar="USER", action="store", help="user to authenticate with")
-
- secret = parser.add_argument_group()
- cred = secret.add_mutually_exclusive_group()
- cred.add_argument("-p", "--password", dest="auth_password", metavar="PASSWORD", action="store", help="password to authenticate with")
-
- if len(sys.argv) == 1:
- parser.print_help()
- sys.exit(1)
-
- args = parser.parse_args()
-
- return args
-
-
- if __name__ == '__main__':
- args = parse_args()
-
- print("[+]================LDAP2JSON======================================[+]")
-
- print()
-
-
-
- ldap_server, ldap_session = init_ldap_session(
- args=args,
- username=args.auth_username,
- password=args.auth_password
- )
-
- if args.debug:
- print("[>] Authentication successful!")
-
- print("[>] Extracting all objects from LDAP ...")
-
- data = {}
-
- baseDN = "dc=majornet,dc=local"
-
- if args.debug:
- print("[>] Querying to LDAP on %s ..." % baseDN)
-
- lc = LDAPConsole(ldap_server, ldap_session, baseDN, debug=args.debug)
- response = lc.queryallusers("ou=users", attributes=["displayName"])
- if args.debug:
- print("[>] LDAP query (objectClass=*) returned %d objects" % len(response))
- if args.debug:
- print("[>] Parsing data ...")
-
- for cn in response:
- path = cn.split(',')[::-1]
- tmp = data
- for key in path[:-1]:
- if key in tmp.keys():
- tmp = tmp[key]
- else:
- tmp[key] = {}
- tmp = tmp[key]
- tmp[path[-1]] = cast_to_dict(response[cn])
-
- json_data = json.dumps(data, indent=4)
- if args.debug:
- print("[>] JSON data generated.")
-
- print("[>] Writing json data to %s" % args.jsonfile)
- f = open(args.jsonfile, 'w')
- f.write(json_data)
- f.close()
- print("[>] Written %s bytes to %s" % (bytessize(json_data), args.jsonfile))
-
- response = lc.doLdapLogin("ou=users", username='emorrone',password='morrone')
- print (response['authen'])
- response = lc.doLdapLogin("ou=users", username='emorrone',password='emorrone')
- print (response['authen'])
-
-
- ### ./bin/python ldap2json.py -u "cn=ldapadmin,dc=majornet,dc=local" -p "secret" --dc-ip "127.0.0.1" -b "dc=majornet,dc=local" -debug
|