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!

How an obscure PHP footgun led to RCE in Craft CMS- 1560

Asset NotePosted 1 Year Ago
  • PHP is full of security footguns. Many of them have been fixed, such as 'abc' == 0. However, there are some that still remain. In the case of Craft CMS, a popular PHP based CMS, there are still some footguns lurking.
  • PHP can be used both on the command line and as a web server. So, the global variables $_SERVER['argc'] and $_SERVER['argv']. If you run this as a web server then PHP will take argv from the query string, if you have enabled this! In the case of PHP, this functionality was on in the default Docker container.
  • In the case of Craft CMS, there is some code that runs for parsing CLI functions. If the argv entry is empty, then it skips this though. Normally from a website, this would it would be empty. Like many programs, there is a lot of option processing when running the application.
  • Here's the crazy bug though: since $_SERVER['argv'] can be controlled from web! This allows an attacker to control the configurations of the running website. For example, --configPath=/aaa will set the configuration path to a non-existent location, remotely.
  • At this point, the vulnerability feels like than RCE but the path needs to be found. They tried some easy wins but no dice. The path that looked interesting was a request to get a file remotely. If a PHP file could be included then this would mean RCE. However, there was a file_exists check before this that prevented using HTTP, PHP or other many other types of files.
  • Upon further inspection, the ftp:// URI supports file existence checks. Using a file here is blocked by the allow_url_include security feature. But, a template CAN be included! So, they created an FTP server with anonymous access and a file called index.twig with {{7*7}} in it. When craft loads the file, it gets evaluated!
  • Craft CMS attempts to sandbox the Twig template renderer. So, simple calls to system are denied. They found that using {{ ['system', 'id'] | sort('call_user_func') }} bypassed the verification, which I don't really understand how it works.
  • Understanding esoteric portions of languages and frameworks can be useful but it's hard to see the payoff until something like this happens sometimes. Great find!