0xzdh / o365spray Goto Github PK
View Code? Open in Web Editor NEWUsername enumeration and password spraying tool aimed at Microsoft O365.
License: MIT License
Username enumeration and password spraying tool aimed at Microsoft O365.
License: MIT License
Hi!
While trying to run o365spray, following bit crashes:
PS C:\o365spray> py .\o365spray.py --help
Traceback (most recent call last):
File "C:\data\tools\__Azure\o365spray\o365spray.py", line 4, in <module>
from o365spray.__main__ import main # type: ignore
File "C:\data\tools\__Azure\o365spray\o365spray\__main__.py", line 14, in <module>
from o365spray.core import ( # type: ignore
File "C:\data\tools\__Azure\o365spray\o365spray\core\__init__.py", line 8, in <module>
from o365spray.core.handlers import Enumerator # type: ignore
File "C:\data\tools\__Azure\o365spray\o365spray\core\handlers\__init__.py", line 1, in <module>
from o365spray.core.handlers.enumerator import Enumerator # type: ignore
File "C:\data\tools\__Azure\o365spray\o365spray\core\handlers\enumerator.py", line 37, in <module>
class Enumerator(BaseHandler):
File "C:\data\tools\__Azure\o365spray\o365spray\core\handlers\enumerator.py", line 45, in Enumerator
loop: asyncio.base_events._UnixSelectorEventLoop,
AttributeError: module 'asyncio.base_events' has no attribute '_UnixSelectorEventLoop'
Could you please look into this?
Regards,
Mariusz
If you have a large list of likely users to enumerate with --enum
, say more than 7 million (common when inferring emails from popular names in a country, for instance), o365spray will use tons of memory, more than 16GB in some cases (regardless of --enum-method
).
This is likely due to this pattern of concurrency in o365spray/core/handlers/enumerator/modules/base.py:
blocking_tasks = [
self.loop.run_in_executor(
self.executor,
partial(
self._enumerate,
domain=domain,
user=user,
password=password,
),
)
for user in userlist
]
if blocking_tasks:
await asyncio.wait(blocking_tasks)
If there was a concurrency limit of some sort, such as what is suggested here, I suspect this wouldn't happen. This limit could be set to a sufficiently high value like 10000 by default to mitigate this issue for large wordlists and also prevent performance impacts for smaller wordlists. It could also be configurable in an argument for better flexibility.
I have replaced URLs with REDACTED due to privacy concerns. Please tell me if this prevents my issue from being solved.
user@pop-os:~/Downloads/o365spray$ python3 o365spray.py --spray -U ../../users.txt -P ../rockyou.txt --count 2 --domain REDACTED
*** O365 Spray ***
>----------------------------------------<
> version : 3.0.0
> domain : REDACTED
> spray : True
> userfile : ../../users.txt
> passfile : ../rockyou.txt
> count : 2 passwords/spray
> lockout : 15.0 minutes
> validate_module: getuserrealm
> spray_module : oauth2
> rate : 10 threads
> safe : 10 locked accounts
> timeout : 25 seconds
> start : 2022-09-29 16:47:37
>----------------------------------------<
[2022-09-29 16:47:37,905] [info] Validating: REDACTED
[2022-09-29 16:47:38,414] [info] [WARNING] The following domain appears to be using O365, but is Federated: REDACTED
[!] --> ADFS AuthURL: REDACTED
[2022-09-29 16:47:38,414] [info]
[ ? ] Switch to the ADFS module for password spraying [Y/n] n
Traceback (most recent call last):
File "/home/user/Downloads/o365spray/o365spray.py", line 6, in <module>
main()
File "/home/user/Downloads/o365spray/o365spray/__main__.py", line 272, in main
spray(args, output_directory, enum)
File "/home/user/Downloads/o365spray/o365spray/core/handlers/sprayer/spray.py", line 39, in spray
passlist += Helper.get_list_from_file(args.passfile)
File "/home/user/Downloads/o365spray/o365spray/core/utils/helper.py", line 135, in get_list_from_file
list_ = [line.strip() for line in f if line.strip() not in [None, ""]]
File "/home/user/Downloads/o365spray/o365spray/core/utils/helper.py", line 135, in <listcomp>
list_ = [line.strip() for line in f if line.strip() not in [None, ""]]
File "/usr/lib/python3.10/codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 923: invalid continuation byte
Thank you in beforehand!
In the code:
if args.paired:
logging.info("Password spraying using paired usernames:passwords.")
loop.run_until_complete(spray.run(passlist))
# Note: Since we are pairing usernames and passwords, we can ignore the
# lockout reset wait call as we should only be running a single
# cycle
The note is not true in all cases, if the paired list contains multiple passwords for the same user, the lockout policy should still be used. e.g.
alice:qwerty
bob:password123
bob:bobisthebest
During command line parsing, validate the provided username and password files exist.
Hi,
This issue is similar to MSOLspray's one.
During our tests we've found, that when sprayed User with a correct password - attempt failed due to Conditional Access Policy requirements, following error code will be thrown:
AADSTS53003: Access has been blocked by Conditional Access policies. The access policy does not allow
token issuance.
error_uri: https://login.microsoft.com/error?code=53003
https://login.microsoft.com/error?code=53003%22,%22suberror%22:%22message_only%22%7D
Whereas the same attempt with a wrong password brings no such error.
The conclusion is that AADSTS53003 error code indicates correct password, but CAP getting into way.
I guess it's worth adding corresponding logic to handle that :)
Regards,
Mariusz.
o365spray --validate --domain test.com --proxy-url https://127.0.0.1:8080
Traceback (most recent call last):
File "", line 198, in _run_module_as_main
File "", line 88, in _run_code
File "/home/kali/Desktop/tools/o365spray/o365spray/main.py", line 11, in
from o365spray import version
ModuleNotFoundError: No module named 'o365spray'
Issue after running the installation in the following way
git clone https://github.com/0xZDH/o365spray.git
cd o365spray
pip install -r requirements.txt
Whenever I am trying to start a spray it says that the Domains are not using O365 although they are provided in the Description as working. I then tried to validate them manually and the following error came up:
root@UnknownPC:~/o365spray# python3 o365spray -v -d portal.office.com
/usr/bin/python3: can't find 'main' module in '/root/o365spray/o365spray'
When running the spray command I get this error:
root@UnknownPC:~/o365spray# python3 o365spray.py --spray -U names.txt -P 10-million-password-list-top-1000000.txt -c 5 -d https://outlook.office365.com/
*** O365 Spray ***
----------------------------------------<
version : 1.3.7
domain : https://outlook.office365.com/
spray : True
userfile : names.txt
passfile : 10-million-password-list-top-1000000.txt
count : 5 passwords/spray
lockout : 15.0 minutes
validate_type : getuserrealm
spray_type : activesync
rate : 10 threads
safe : 10 locked accounts
timeout : 25 seconds
output : .
start : 2023-05-27 00:49:30
----------------------------------------<
[*] Performing O365 validation for: https://outlook.office365.com/
[FAILED] The following domain is not using O365: https://outlook.office365.com/
I am running Ubuntu as WLS on my Windows 11 PC and have python 3 as well as o365spray installed.
Thanks for any help!
Installing with Python 3.9.2, pipx 1.1.0 and pip 20.3.4 results in the error message AttributeError: module 'o365spray' has no attribute '__version__'
, additionally the SetuptoolsDeprecationWarning: The license_file parameter is deprecated, use license_files instead.
warning is displayed.
Used command pipx install git+https://github.com/0xZDH/o365spray
.
I apologize in advance, I am not a git pro, I don't know how to pull/branch yet; I will learn, but I need to get back to my pentest first. Below I have a change suggestion to ignore lines in the userlist file that start with a comment (#). Use case: I start with a list, and as I find invalid usernames, etc, I like to keep them in the list, but comment them out with some reason why. I considered it for the password file as well, but a password starting with # is possible. I also considered using some form of line.partition("#")[0] to catch it anyplace in the line, but again it may be potentially valid for a password.
I modified modules/generate/helpers.py as follows (just add the if check):
def get_users(conf: Configuration) -> list[str]:
user_list: list[str] = []
for line in conf.user_file:
line = line.rstrip()
if line[0] == "#":
continue
user_list.append(line)
return user_list
Thanks for your work, I will attempt to contribute more effectively!
Currently trying to test password spraying and having the following error when I run a spray using both the autodiscover and MSOL modules. Activesync module works fine.
Command-line
python o365spray.py --spray -u USER@DOMAIN --domain DOMAIN.onmicrosoft.com -p PASSWDTEST1 --spray-module autodiscover --debug --proxy http://127.0.0.1:8080
OR
python o365spray.py --spray -u USER@DOMAIN --domain DOMAIN.onmicrosoft.com -p PASSWDTEST1 --spray-module msol --debug --proxy http://127.0.0.1:8080
Debug output
[2021-07-30 13:18:19,753] INFO - __main__.py:233 - Running O365 validation for: DOMAIN
[2021-07-30 13:18:19,755] DEBUG - connectionpool.py:973 - Starting new HTTPS connection (1): login.microsoftonline.com:443
[2021-07-30 13:18:20,111] DEBUG - connectionpool.py:452 - https://login.microsoftonline.com:443 "GET /getuserrealm.srf?login=user@DOMAIN&xml=1 HTTP/1.1" 200 451
[2021-07-30 13:18:20,112] INFO - __main__.py:263 - [VALID] The following domain is using O365: DOMAIN
[2021-07-30 13:18:20,112] DEBUG - selector_events.py:59 - Using selector: EpollSelector
[2021-07-30 13:18:20,113] INFO - __main__.py:451 - Running password spray against 1 users.
[2021-07-30 13:18:20,113] INFO - __main__.py:497 - Password spraying the following passwords: ['PASSWDTEST1']
[2021-07-30 13:18:20,113] DEBUG - sprayer.py:375 - 'Sprayer' object has no attribute 'helper'
[2021-07-30 13:18:20,114] INFO - sprayer.py:136 -
This is using the latest version. Any ideas what is causing this or if I am doing something wrong?
When installing the tool via setuptools using: python setup.py install
- the installation is broken via: ModuleNotFoundError: No module named 'o365spray.core'
.
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.