fortra / impacket

Impacket is a collection of Python classes for working with network protocols.
https://www.coresecurity.com
Other
13.46k stars 3.57k forks source link

Infinite loop in secretsdump.py while extracting domain hashes #1606

Open rodrigozanatta opened 1 year ago

rodrigozanatta commented 1 year ago

This is not a new bug. There is some reports, like #413 #256

I try to read the code and understand what happens. Look like it is a while and reading the debug data, look like just a simple programming error, like this:

Somehow, it goes back in the number and do the infinite loop. So, it look likes only need to do a for i in range(total_bocks)

Obvious the code is more complex and because it make a lot of obscure call, I can't understand easly. But why not only make a simple for without going back (or a option to do this).

What is the problem here? How the algorithm works? Why the indice goes back?

anadrianmanrique commented 1 year ago

@rodrigozanatta can you provide some sample to trigger this issue? thanks

rodrigozanatta commented 1 year ago

@rodrigozanatta can you provide some sample to trigger this issue? thanks

I don't want to make the file public. Show me what test do you want me to make. Can I do it and send the results?

anadrianmanrique commented 1 year ago

@rodrigozanatta can you provide some sample to trigger this issue? thanks

I don't want to make the file public. Show me what test do you want me to make. Can I do it and send the results?

I understand. Can you describe the database in order to try to replicate the scenario? number of users, AD structure, number of computers, etc, I think that could help

rodrigozanatta commented 1 year ago

I understand. Can you describe the database in order to try to replicate the scenario? number of users, AD structure, number of computers, etc, I think that could help

@anadrianmanrique I did something better. I run the program with debug, sanitize the result, and send it. What you need to know:

How the infinite loop happens?

I could print the hex value in the address page 5822 or others. Could it helps? What part of the ntds.dit file could help to fix this bug?

I did atach the Log: log.txt

rodrigozanatta commented 1 year ago

Now I remember what I study. Because I use -use-vss

It will enter in line 2564 in /impacket/examples/secretsdump.py

line 2563    # Now let's keep moving through the NTDS file and decrypting what we find
line 2564    while True:
line 2565        try:
line 2566            record = self.__ESEDB.getNextRow(self.__cursor, filter_tables=self.__filter_tables_usersecret)
line 2567        except:
line 2568            LOG.error('Error while calling getNextRow(), trying the next one')
line 2569                continue
line 2570
line 2571         if record is None:
line 2572             break

The only way to exit this infinite loop is if record is None.

If I am not wrong, the __ESEDB.getNextRow() is in impacket/ese.py

    def getNextRow(self, cursor, filter_tables = None):
        cursor['CurrentTag'] += 1

        tag = self.__getNextTag(cursor)
        #hexdump(tag)

        if tag is None:
            # No more tags in this page, search for the next one on the right
            page = cursor['CurrentPageData']
            if page.record['NextPageNumber'] == 0:
                # No more pages, chau
                return None
            else:
                cursor['CurrentPageData'] = self.getPage(page.record['NextPageNumber'])
                cursor['CurrentTag'] = 0
                return self.getNextRow(cursor, filter_tables = filter_tables)
        else:
            return self.__tagToRecord(cursor, tag['EntryData'], filter_tables = filter_tables)

Look like the problem is in the line: if page.record['NextPageNumber'] == 0: I want that to happens.

This is the problem.. How to change the logic of the file. Do you know what is happening?

anadrianmanrique commented 1 year ago

Ok, let me see what I can do with this. I will try to replicate the issue in my env . I'll let you know if I need more information. Thanks!

rodrigozanatta commented 1 year ago

Whell, all the problem is how cursor was made. I could print it's value, just need to setup it. Only reading the code, it is difficult to understand.

One easy way to fix this in my noob view is just:

used_page = set()
if page not in used_page:
    used_page.add(page)
else:
    # will enter in infinite loop, stop it!!!
    break

But I have no idea how it will impact others cases :)

AkechiShiro commented 7 months ago

@anadrianmanrique is there any news on this issue? Were you able to reproduce or not ?