0xZDH/o365spray

Feature Request: Safe Mode

seajaysec opened this issue · 8 comments

Hey! This tool is awesome. I’ve been using it on engagements and it works great. One feature that I’d love would be a --safe flag that halts spraying if a user-defined number of accounts sequentially return the LOCKED OUT status. Would it be possible to add something like that in?

0xZDH commented

Will look into adding this. Should be easy enough to implement.

0xZDH commented

c8e44fa
Added a --safe flag to handle lockouts. Currently, if the flag is set the code will terminate on a single locked account, but termination is not immediate. The way the code is structured a pool is built for asynchronous requests. If a locked account is identified, no further requests will be added to the pool, but the current pool's queue will continue until finished. This is something I need to spend some time working on so I am going to leave this issue open. Once I am able to terminate the pool I will modify the flag to allow a specification of a user-defined number of accounts before termination.

0xZDH commented

8b54d66
--safe flag should now be supported fully after a rewrite of the way this tool asynchronously runs.

I think this feature does not work well with threading.
The threading count is by default set to 10 concurrent requests.
With a safe limit of 2 I had the case that 1 account got locked in one spray and 5 accounts got locked in the next round within two seconds.

A workaround would be to use 1 thread only when enabling --safe or somehow enforce a slight delay between the requests to detect lockouts within a run.

@0xZDH Do you have an idea on how to fix this issue while keeping threading enabled?

0xZDH commented

@cmprmsd sorry for the delayed response - not sure if this issue is still relevant for you, but as an answer:

The --safe flag is meant as a safeguard for mass lock outs when spraying a large data set. With threading, things are executing concurrently so if there are 10 threads, those threads will complete before things exit since they are already in flight. If you have a strict lockout policy to deal with, lowering the threads is the right solution for the time being.

Thanks for your reply!

Could the threads maybe check a global "locked_account" variable before execution right before sending the request?

I understand that the requests might already be in progress and stopping them is not possible any more at that time.

0xZDH commented

The spray modules do exactly that - they check the global lock count before making the HTTP request: https://github.com/0xZDH/o365spray/blob/master/o365spray/core/handlers/sprayer/modules/oauth2.py#L37

Just as you said, the requests in each thread at that point are already in progress so instead of hard exiting and not catching the responses - we conclude the parsing of the responses and then exit.