Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

IngressNightmare: 9.8 Critical Unauthenticated Remote Code Execution Vulnerabilities in Ingress NGINX- 1620

Wiz.ioPosted 11 Months Ago
  • The Ingress NGINX Controller on Kubernetes is a popular ingress controller for managing incoming network traffic and routing it to the proper Pod. This is built on top of the popular NGINX reverse proxy software. The author claims that 41% of internet facing clusters use this software. Since it's internet facing, an authentication bypass or an RCE bug would be catastrophic for these services.
  • The service attempts to translate Kubernetes Ingress objects into NGINX configurations. The Admission Controller is a Kubernetes API server for reviewing, modifying and blocking requests. These controllers don't require authentication.
  • In the Admission Controller code, the AdmissionReview request generates a temporary NGINX configuration file using a template. Then, to test for validity, it runs nginx -t. Since the configuration file has user controlled inputs, the path is unauthenticated and the config is executed, this makes it a great attack surface.
  • The authreq parameter is used for authentication-related annotations. However, this field has zero input sanitization. Hence, it's possible to add arbitrary directives to the NGINX configuration file. There are several other variants of this on the authtls and mirror parameters. So, why is this injection a big deal?
  • The NGINX configuration format has a lot of directives, many of which are undocumented. the ssl_engine directive is able to load shared modules, without top-of-file restrictions like load_module. Doing this would allow for the execution of arbitrary code but requires a file to be on the system.
  • The pod runs an NGINX instance itself. When processing NGINX, the request body is saved to a temporary file if its large enough. Although NGINX removes the file immediately, there is an open file descriptor in the /proc file system. Using this, it's possible to access the contents of the file from the NGINX configuration. To make this race condition easier, making the Content-Length larger than the body will keep NGINX waiting. Sadly, this requires brute forcing PIDs and file descriptors, but that's worth the problem.
  • Here's the full path to RCE:
    1. Upload the .so payload by abusing the file buffer feature.
    2. Send an AdmissionReview request to the controller with directive injections. In particular, inject the ssl_engine to load the shared library from step 1.
    3. Try different PID paths over and over again. Eventually, it will execute and you'll get RCE.
  • Overall, a great write up or a relatively unknown attack surface. This covers the fact that running nginx -t can lead to code execution, making configuration injection a very serious vulnerability.