Zimbra-SOAP-API 开发指南6 —— 预认证

发布于 2024-09-03 11:38:22 字数 7490 浏览 10 评论 0

0x00 前言

本文将要继续扩充开源代码 Zimbra_SOAP_API_Manage 的实用功能,添加预认证的登录方式,分享开发细节。

0x01 简介

本文将要介绍以下内容:

  • 预认证
  • 计算 preauth
  • SOAP 实现
  • 开源代码

0x02 预认证

参考资料: https://wiki.zimbra.com/wiki/Preauth

简单理解:通过 preAuthKey 结合用户名、时间戳和到期时间,计算得出的 HMAC 作为身份验证的令牌,可用于用户邮箱和 SOAP 登录

默认配置下,Zimbra 未启用预认证的功能,需要手动开启

(1) 开启预认证并生成 PreAuthKey

命令如下:

/opt/zimbra/bin/zmrov generateDomainPreAuthKey <domain>

其中, <domain> 对应当前 Zimbra 服务器的域名,可通过执行命令 /opt/zimbra/bin/zmprov gad 获得,测试环境的输出如下:

mail.test.com

对应测试环境的命令为: /opt/zimbra/bin/zmprov generateDomainPreAuthKey mail.test.com

测试环境的输出如下:

preAuthKey: fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7

(2) 读取已有的 PreAuthKey

命令如下:

/opt/zimbra/bin/zmprov gd <domain> zimbraPreAuthKey

对应测试环境的命令为: /opt/zimbra/bin/zmprov gd mail.test.com zimbraPreAuthKey

测试环境的输出如下:

zimbraPreAuthKey: fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7

注:如果 Zimbra 存在多个域名,那么会有多个 PreAuthKey

0x03 计算 preauth

参考资料 中给出了多种计算 preauth 的示例,但是 Python 的实现代码不完整,这里补全 Python3 下的完整实现代码,详细代码如下:

from time import time
import hmac, hashlib
import sys
def generate_preauth(target, preauth_key, mailbox):
    try:
        preauth_url = target + "/service/preauth"
        timestamp = int(time()*1000)
        data = "{mailbox}|name|0|{timestamp}".format(mailbox=mailbox, timestamp=timestamp)
        pak = hmac.new(preauth_key.encode(), data.encode(), hashlib.sha1).hexdigest()
        print("[+] Preauth url: ")   
        print("%s?account=%s&expires=0&timestamp=%s&preauth=%s"%(preauth_url, mailbox, timestamp, pak))
    except Exception as e:
        print("[!] Error:%s"%(e))

if __name__ == "__main__":
    if len(sys.argv)!=4:
        print('GeneratePreauth')
        print('Use to generate the preauth key')
        print('Usage:')
        print('%s <host> <preauth_key> <mailuser>'%(sys.argv[0])) 
        print('Eg.')
        print('%s https://192.168.1.1 fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7 test1@mail.test.com'%(sys.argv[0]))
        sys.exit(0)
    else:
        generate_preauth(sys.argv[1], sys.argv[2], sys.argv[3])

代码会自动生成可用的 URL,浏览器访问可以登录指定邮箱

0x04 SOAP 实现

SOAP 格式:

<AuthRequest xmlns="urn:zimbraAccount">
<account by="name|id|foreignPrincipal">{account-identifier}</account>
<preauth timestamp="{timestamp}" expires="{expires}">{computed-preauth}</preauth>
</AuthRequest>

SOAP 格式示例:

<AuthRequest xmlns="urn:zimbraAccount">
<account>john.doe@domain.com</account>
<preauth timestamp="1135280708088" expires="0">b248f6cfd027edd45c5369f8490125204772f844</preauth>
</AuthRequest>

需要 timestamppreauth 作为参数,使用预认证登录的详细代码如下:

import sys
import requests
import re
import warnings
warnings.filterwarnings("ignore")
from time import time
import hmac, hashlib

def generate_preauth(target, mailbox, preauth_key):
    try:
        preauth_url = target + "/service/preauth"
        timestamp = int(time()*1000)
        data = "{mailbox}|name|0|{timestamp}".format(mailbox=mailbox, timestamp=timestamp)
        pak = hmac.new(preauth_key.encode(), data.encode(), hashlib.sha1).hexdigest()
        print("[+] Preauth url: ")   
        print("%s?account=%s&expires=0&timestamp=%s&preauth=%s"%(preauth_url, mailbox, timestamp, pak))
        return timestamp, pak
    except Exception as e:
        print("[!] Error:%s"%(e))

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}

def auth_request_preauth(uri,username,timestamp,pak):
    request_body="""<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
       <soap:Header>
           <context xmlns="urn:zimbra">              
           </context>
       </soap:Header>
       <soap:Body>
         <AuthRequest xmlns="urn:zimbraAccount">
            <account>{username}</account>
            <preauth timestamp="{timestamp}" expires="0">{pak}</preauth>
         </AuthRequest>
       </soap:Body>
    </soap:Envelope>
    """
    try:
        r=requests.post(uri+"/service/soap",headers=headers,data=request_body.format(username=username,timestamp=timestamp,pak=pak),verify=False,timeout=15)
        if 'authentication failed' in r.text:
            print("[-] Authentication failed for %s"%(username))
            exit(0)
        elif 'authToken' in r.text:
            pattern_auth_token=re.compile(r"<authToken>(.*?)</authToken>")
            token = pattern_auth_token.findall(r.text)[0]
            print("[+] Authentication success for %s"%(username))
            print("[*] authToken_low:%s"%(token))
            return token
        else:
            print("[!]")
            print(r.text)
    except Exception as e:
        print("[!] Error:%s"%(e))
        exit(0)

timestamp, pak = generate_preauth("https://192.168.1.1", "test1@mail.test.com", "fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7")
token = auth_request_preauth("https://192.168.1.1","test1@mail.test.com",timestamp,pak)

以上代码通过预认证登录,返回可用的 token,通过该 token 可以进行后续的 SOAP 操作,列出文件夹邮件数量的实现代码:

def getfolder_request(uri,token):
    request_body="""<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
       <soap:Header>
           <context xmlns="urn:zimbra">
               <authToken>{token}</authToken>
           </context>
       </soap:Header>
       <soap:Body>
         <GetFolderRequest xmlns="urn:zimbraMail"> 
         </GetFolderRequest>
       </soap:Body>
    </soap:Envelope>
    """
    try:
        print("[*] Try to get folder")
        r=requests.post(uri+"/service/soap",headers=headers,data=request_body.format(token=token),verify=False,timeout=15)
        pattern_name = re.compile(r"name=\"(.*?)\"")
        name = pattern_name.findall(r.text)
        pattern_size = re.compile(r" n=\"(.*?)\"")
        size = pattern_size.findall(r.text)      
        for i in range(len(name)):
            print("[+] Name:%s,Size:%s"%(name[i],size[i]))
    except Exception as e:
        print("[!] Error:%s"%(e))

getfolder_request("https://192.168.1.1",token)

0x05 开源代码

新的代码已上传至 github,地址如下:https://github.com/3gstudent/Homework-of-Python/blob/master/Zimbra_SOAP_API_Manage.py

添加了使用预认证登录的功能

0x06 小结

本文扩充了 Zimbra SOAP API 的调用方法,添加了使用预认证登录的功能。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

明媚如初

暂无简介

0 文章
0 评论
538 人气
更多

推荐作者

qq_7J1imQ

文章 0 评论 0

《一串符号》

文章 0 评论 0

hls.

文章 0 评论 0

雅心素梦

文章 0 评论 0

塔塔猫

文章 0 评论 0

微信用户

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文