File: pretty.py

package info (click to toggle)
python-ldapdomaindump 0.9.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 268 kB
  • sloc: python: 1,000; makefile: 3
file content (152 lines) | stat: -rw-r--r-- 5,998 bytes parent folder | download | duplicates (3)
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
from __future__ import print_function
from builtins import str
import argparse
import json
import os.path
import re
from time import strftime, gmtime

class PrettyOuput(object):

    def d2b(self, a):
        tbin = []
        while a:
            tbin.append(a % 2)
            a //= 2

        t2bin = tbin[::-1]
        if len(t2bin) != 8:
            for x in range(6 - len(t2bin)):
                t2bin.insert(0, 0)
        return ''.join([str(g) for g in t2bin])

    def convert(self, time):
        if isinstance(time, str):
            return time
        if time == 0:
            return "None"
        if time == -9223372036854775808:
            return "Not Set"
        sec = abs(time) // 10000000
        days = sec // 86400
        sec -= 86400*days
        hrs = sec // 3600
        sec -= 3600*hrs
        mins = sec // 60
        sec -= 60*mins
        result = ""
        if days > 1:
            result += "{0} days ".format(days)
        elif days == 1:
            result += "{0} day ".format(days)
        if hrs > 1:
            result += "{0} hours ".format(hrs)
        elif hrs == 1:
            result += "{0} hour ".format(hrs)
        if mins > 1:
            result += "{0} minutes ".format(mins)
        elif mins == 1:
            result += "{0} minute ".format(mins)
        return result

    def password_complexity(self, data):

        print('''
    +-----------------------------------------+
    | Password Policy Information             |
    +-----------------------------------------+
    ''')

        print("[+] Password Info for Domain:", data[0]['attributes']['dc'][0].upper())
        print("\t[+] Minimum password length: ", data[0]['attributes']['instanceType'][0])
        print("\t[+] Password history length:", data[0]['attributes']['pwdHistoryLength'][0])

        password_properties = self.d2b(data[0]['attributes']['pwdProperties'][0])
        print("\t[+] Password Complexity Flags:", password_properties)
        print("")
        print("\t\t[+] Domain Refuse Password Change:", password_properties[0])
        print("\t\t[+] Domain Password Store Cleartext:", password_properties[1])
        print("\t\t[+] Domain Password Lockout Admins:", password_properties[2])
        print("\t\t[+] Domain Password No Clear Change:", password_properties[3])
        print("\t\t[+] Domain Password No Anon Change:", password_properties[4])
        print("\t\t[+] Domain Password Complex:", password_properties[5])
        print("")
        print("\t[+] Maximum password age:", self.convert(data[0]['attributes']['maxPwdAge'][0]))
        print("\t[+] Minimum password age:", self.convert(data[0]['attributes']['minPwdAge'][0]))
        print("\t[+] Reset Account Lockout Counter:", self.convert(data[0]['attributes']['lockoutDuration'][0]))
        print("\t[+] Account Lockout Threshold:", data[0]['attributes']['lockoutThreshold'][0])
        print("\t[+] Forced Log off Time:", self.convert(data[0]['attributes']['forceLogoff'][0]))

    def domain_info(self, data):
        print('''
    +--------------------------------------+
    | Getting Domain Sid For               |
    +--------------------------------------+
    ''')
        print('[+] Domain Name:', data[0]['attributes']['dc'][0])
        print('Domain Sid:', data[0]['attributes']['objectSid'][0])
        print('')
        return data[0]['attributes']['dc'][0]

    def user_info(self, users, dc):
        print('''
    +------------------------+
    | Users Infos            |
    +------------------------+
    ''')
        for user in users:
            desc = user['attributes'].get('description')[0] if user['attributes'].get('description') else "(null)"
            print("Account: " + dc + "\\" + user['attributes']['sAMAccountName'][0] + "\tName: " + user['attributes']['name'][0] + "\tDesc: " + desc)

        print("")
        for user in users:
            print("user:[" + user['attributes']['sAMAccountName'][0] + "]")
        print("")

    def groups_info(self, groups, dc):
        print('''
    +------------------------+import os.path
    | Groups Infos           |
    +------------------------+
    ''')
        for group in groups:
            print("group:[" + group['attributes']['name'][0] + "]")

        for group in groups:
            if group['attributes'].get('member'):
                users = re.findall(r"^CN=([\w\s\-\_\{\}\.\$\#]+)", '\n'.join(group['attributes']['member']), re.M)
                if users:
                    print("\n[+] Getting domain group memberships:")
                    for user in users:
                        if user == "S-1-5-11":
                            user = "NT AUTHORITY\\Authenticated Users"
                        elif user == "S-1-5-4":
                            user = "NT AUTHORITY\\INTERACTIVE"
                        elif user == "S-1-5-17":
                            user = "NT AUTHORITY\\IUSR"
                        print("Group '" + group['attributes']['name'][0] + "' has member: " + dc + "\\" + user)

def main():
    parser = argparse.ArgumentParser(description='LDAPDomainDump to pretty output like enum4linux.')

    #Main parameters
    parser.add_argument("-d", "--directory", help="The ldapdomaindump directory where the json files are saved. Required files: domain_users.json, domain_groups.json and domain_policy.json")
    args = parser.parse_args()

    if args.directory:
        with open(args.directory + '/domain_policy.json') as f:
            domain = json.load(f)
        with open(args.directory + '/domain_users.json') as f:
            users = json.load(f)
        with open(args.directory + '/domain_groups.json') as f:
            groups = json.load(f)
        pretty = PrettyOuput()
        dc = pretty.domain_info(domain)
        pretty.password_complexity(domain)
        pretty.user_info(users, dc.upper())
        pretty.groups_info(groups, dc.upper())
    else:
        print("Missing parameter --directory /output/")

if __name__ == "__main__":
    main()