Show Notes

81 - Reused VMWare exploits & Escaping Azure Container Instances

Easy vulnerability that shows how checking the magic numbers of a file isn’t always sufficient. For some types of files all that matters is that the processor can detect its own content within another file. PHP is an example of this, it doesn’t care how the file starts or ends, just that it can find the <?php tags and code to run.

In this attack the author was able to bypass a file-upload filter that checked the magic number (first few bytes of a file) to ensure it was an image by uploading a corrupted image that also contained PHP within it. Its a classic trick, but its great to see it still alive and kicking.


While we don’t know what application this vulnerability was found in to discuss the patch keeping any sort of user content outside of the web-root is a good starting place, and not running language processors on requests to what should be static files.

The vulnerability here is simply that Opera’s Pinboard feature allows pinning URLs starting with javascript: creating a clickable link on a Pinboard that will execute JavaScript. Unfortunately (for the attacker) these tabs open in a new window and not within the Pinboard context unless middle clicking, then these links will trigger them within the Pinboard context.

The Pinboard context is important here not so much because one might want to steal the data on a pinboard but because within Opera the Pinboards open within a higher-privileged opera: schema. This means the tab (and any XSS inside of it) can access browser features unavailable normal websites.

The example HTTP request to add a pin to the pinboard provided by the author doesn’t show anything unique that an attacker would need to disclose or guess; not even a unique cookie so I’m actually curious how Opera is associating the requests to a particular board. This does mean that it could have been used in a wide-spread targeted attack. So despite the need to middle click, hitting enough people its bound to land on a few.

The second half of the post deals with abusing these extra features to create a reasonably impactful attack chain:

  • Open a New Tab at file:///etc/passwd
  • Use the opr.pinboardPrivate.getThumbnail function to generate a thumbnail of the newly created tab
  • Send the base64 encoded version of that thumbnail to the attacker’s server

Authentication bypass by including a magic string in the URL. The string isn’t exactly magic, rather it seems like this page (setcup.cgi) has a single file that needs to be access without authentication. So in an adhoc check, the application just looks for a string that is unique to that request line and turns off authentication. The problem being that it doesn’t check any of the context around that string.

If todo=PNPX_GetShareFolderList is present anywhere in the request line then authentication will be turned off. This can be used to disclose files such as:

  • NETGEAR_D7000.cfg which contains the device configuration including a hashed admin password
  • BRS_swisscom_success.html which contains the plaintext admin password

Once the admin password has been disclosed then an attacker can authenticate with the device and enable Telnet for RCE.

This is a vulnerability within the check-spelling workflow specifically and not GitHub Actions. This workflow is used to, well, check the spelling on an incoming Pull Request. New PR comes in, spelling is checked according to an in-repo configuration, and spelling issues are added as a comment to the PR.

The problem comes from the advice.txt or files the workflow uses from inside the repository. The Advice file is used to provide content that is inserted directly into Github comments or logs

Since this file is within the repository the Pull Request can actually change the file being read for advice, so an malicious attacker could create a symline from advice.txt to /proc/self/environ to leak the environment vars of the GitHub Action runner including the GITHUB_TOKEN

Patch - Commit The primary change is that they added a perl script that checks if the file’s absolute path lives within the workspace path and not inside the .git folder. The same commit also drops support for windows based runners.

The Shopify GraphQL endpoint has a mutation appCreditCreate for Shopify apps to issue credits to merchants that can be used towards future app purchases. While this mutation cannot be used through the GraphQL endpoint at /admin/internal/web/graphql/core the GraphiQL app provided by Shopify however does allow the mutation. Allowing unauthorized users to create credits

tl;dr Cool chain to escape and impact other containers on Azure Container Instances hosted by Kubernetes clusters (some are hosted by Service Fabric Clusters which are not vulnerable in this way), first is the container escape itself into the containing node/vm, followed by a leaked JWT useful to run commands against all nodes in the cluster.

Container Escape

The post starts off with some background on Azure Container Instances, and talks about WhoC a container they developed and released in August at Defcon 29. Which uses a neat trick to disclose the container runtime binary to a remote server. You can read the details on the WhoC Github but the gist is re-executing /proc/self/exe inside the container and replacing the dynamic linker to pass execution to something to exfil it.

Using that they discover that it is using a very old versions of runC from late 2016 to late 2017. These have known vulnerabilities, so escaping the container is straight forward.

Cross-Node Interaction

They include a semi-rabbit hole into thinking that the cluster’s apiserver is vulnerable to another known vulnerability. The vulnerability involves redirecting requests from the apiserver to another node, so redirect an exec to another note to exec on it. As long as you cna issue the exec to your node, you can redirect it it.

It turns out while the API server was potentially vulnerable to this, issued execs actually came from another server, the bridge, that was not vulnerable. While the known vuln was a rabbit hole, what they discovered was that requests from the bridge included an Authorization header with a JWT. This JWT had pods/exec privileges across the entire cluster, including the API server. With apiserver access, the entire cluster can be compromised.

Server Side Request Forgery in pods bridge

After reporting the first issue, they then discovered another attack on the pods bridge which would lead to the same kind of compromise. When the bridge constructs the request for an exec command from a pod, it takes the node IP from the customer pod’s status.hostIP field. This field could be controlled by an attacker and continuously overwritten to circumvent the api server’s continuous correction of the field. On it’s own, this wouldn’t have been useful for an attacker because the URL would still point to your pod’s namespace even if the request was directed to a different pod’s IP.

However, this field wasn’t validated to make sure it was even a proper IP address, it could be any arbitrary string, including URL components. This gives you an injection into the request URL, which you can use to trick the bridge into executing a command on the API server container instead of your own.